如何从 sklearn 中的 TF*IDF 值获取字数
Posted
技术标签:
【中文标题】如何从 sklearn 中的 TF*IDF 值获取字数【英文标题】:How to get word count from TF*IDF value in sklearn 【发布时间】:2015-11-22 01:22:25 【问题描述】:我想仅使用一组句子的 tf*idf 矩阵来获取给定句子中单词的计数。我使用来自 sklearn.feature_extraction.text 的 TfidfVectorizer。
例子:
from sklearn.feature_extraction.text import TfidfVectorizer
sentences = ("The sun is shiny i like the sun","I have been exposed to sun")
vect = TfidfVectorizer(stop_words="english",lowercase=False)
tfidf_matrix = vect.fit_transform(sentences).toarray()
我希望能够仅使用 tfidf_matrix[0] 和可能的 vect.idf_ 来计算“太阳”一词在第一句(即 2)中出现的次数。 我知道有无数种方法可以获得词频和字数,但我有一个特殊情况,我只有一个 tfidf 矩阵。 我已经尝试将第一句中单词“sun”的 tfidf 值除以其 idf 值得到 tf.然后我将 tf 乘以句子中的单词总数,得到单词数。不幸的是,我得到了错误的值。
【问题讨论】:
你能适应另一个 tfidf 矩阵吗?有一个选项use_idf
可以设置为False
。
其实我做不到。但是,让我们假设我可以。将use_idf
设置为False
将允许我拥有术语频率(我已经可以通过将 tf*idf 值除以 idf 值来获得)。如何根据词频值计算字数?
对不起,我现在意识到我误解了提示。您是否也在规范化术语向量?
没问题.. 是的,默认范数设置为“l2”,所以是的术语向量被归一化。
【参考方案1】:
直观的做法就是您所尝试的:将每个 tf 值乘以您正在检查的句子中的单词数。但是,我认为这里的关键观察是每一行都已通过其欧几里德长度进行了归一化。因此,将每一行乘以该句子中的单词数最多近似非规范化行,这就是你得到奇怪值的原因。 AFAIK,如果不提前知道每个原始行的规范,就无法对 tf*idf 矩阵进行非规范化。这主要是因为有无限数量的向量可以映射到任何一个归一化向量。因此,如果没有规范,您将无法检索到原始向量的正确幅度。 See this answer 了解更多关于我的意思的详细信息。
话虽如此,我认为在我们的案例中有一种解决方法。我们至少可以检索每个句子中术语计数的归一化比率,即 sun 出现的次数是 shiny 的两倍。我发现对每一行进行规范化,使 tf 值的总和为 1,then 将这些值乘以 stopword-filtered 句子的长度似乎可以检索到原始单词很重要。
演示:
sentences = ("The sun is shiny i like the sun","I have been exposed to sun")
vect = TfidfVectorizer(stop_words="english",lowercase=False)
mat = vect.fit_transform(sentences).toarray()
q = mat / vect.idf_
sums = np.ones((q.shape[0], 1))
lens = np.ones((q.shape[0], 1))
for ix in xrange(q.shape[0]):
sums[ix] = np.sum(q[ix,:])
lens[ix] = len([x for x in sentences[ix].split() if unicode(x) in vect.get_feature_names()]) #have to filter out stopwords
sum_to_1 = q / sums
tf = sum_to_1 * lens
print tf
产量:
[[ 1. 0. 1. 1. 2.]
[ 0. 1. 0. 0. 1.]]
我尝试了一些更复杂的句子,它似乎工作正常。如果我遗漏了什么,请告诉我。
【讨论】:
这很完美!谢谢你的解释和代码。以上是关于如何从 sklearn 中的 TF*IDF 值获取字数的主要内容,如果未能解决你的问题,请参考以下文章
使用 sklearn 如何计算文档和查询之间的 tf-idf 余弦相似度?
在python中使用sklearn为n-gram计算TF-IDF