余弦相似度和tf-idf

43
我对有关TF-IDF和余弦相似度的评论感到困惑。
我阅读了两者的相关资料,在维基百科中查找余弦相似度时,我发现了这句话:“在信息检索的情况下,两个文档的余弦相似度将在0到1之间变化,因为词频(tf-idf权重)不能为负数。两个词频向量之间的夹角不能大于90°。”
现在我在想……它们不是两件不同的事吗?
tf-idf已经包含在余弦相似度中了吗?如果是,那么是什么鬼——我只能看到内部点积和欧几里德长度。
我原以为tf-idf是在对文本运行余弦相似度之前可以做的事情。难道我错过了什么?

3
我发现了一个很棒的博客,它真的很有帮助。 - divyum
是的,tfidf只是计算文本文档特征向量的众多方法之一,余弦相似度只是比较相似性的几种方式之一。其他方法包括Jaccard、Pearson、Levenshtein等...请参见例如[https://lylelin317.wordpress.com/2014/03/11/distance-and-similarity-measuring-methods-in-machine-learning/]。使用tfidf并不意味着余弦相似度,反之亦然。 - smci
不幸的是,那篇博客文章没有帮助,只让人更加困惑如何找到文档之间的相似之处。 - SacWebDeveloper
6个回答

49

Tf-idf是一种用于文本的转换,可以得到两个实值向量。您可以通过取它们的点积并将其除以它们的范数乘积来获得任意一对向量的余弦相似度。这产生了向量之间夹角的余弦。

如果d2q是tf-idf向量,则

enter image description here

其中θ是向量之间的夹角。由于tf-idf向量是非负的,因此θ的取值范围为0到90度,cos θ的取值范围为1到0。

tf-idf与余弦相似度/向量空间模型之间没有特别深入的联系;tf-idf只是在文档-词项矩阵中工作得非常好。但它在该领域之外也有用途,原则上,您可以在VSM中替换另一个转换。

(公式摘自维基百科,因此出现了d2。)


3
谢谢,那我没有错 :D 很高兴能够迅速得到你的回答,而不必等待学校的时间^^ - N00programmer
这种说法是否仍然适用:“tf-idf和余弦相似度/向量空间模型之间没有特别深入的联系”?我想知道对于归一化tf-idf向量是否有任何暗示,或者使用余弦相似度只是在实践中表现良好的巧合? - zyxue
如果我要从头开始创建一个信息检索的Python程序。我有一组文档和查询数据集。由于余弦相似度需要两个向量,所以我应该计算文档和查询的TFIDF还是只计算文档的TFIDF? - Anthony Mifsud
我在某处读到并验证了tf-idf向量的点积将直接给出余弦相似度。您能详细说明一下原因吗? - Hossein Kalbasi
因为它们作为TF-IDF的一部分进行了L2归一化。 - Chris Coffee

45
TF-IDF仅是衡量文本中标记重要性的一种方法;它是将文档转化为数字列表的常见方式(术语向量提供了您正在获取余弦的角的一条边)。
要计算余弦相似度,您需要两个文档向量;向量用索引表示每个唯一术语,并且该索引处的值是该术语对文档和文档相似性概念的重要性的某种度量。
您可以简单地计算文档中每个术语出现的次数(术语频率),并将整数结果用作向量中的术语得分,但结果不会很好。极为常见的术语(例如“is”、“and”和“the”)会导致许多文档看起来相似。(这些特定示例可以通过使用停用词列表来处理,但是其他常见术语不足以被视为停用词,会导致相同类型的问题。在Stackoverflow上,“question”可能属于此类别。如果您正在分析烹饪食谱,则可能会遇到“egg”这个词的问题。)
TF-IDF通过考虑每个术语在一般情况下出现的频率(文档频率)来调整原始术语频率。逆文档频率通常是术语出现的文档数除以文档总数的对数(图片来源于维基百科)。

IDF, credit to wikipedia

请注意,'log'只是一个微小的细节,帮助长期运作--当其参数增加时,它会增长,因此如果术语很少,则IDF将很高(许多文档除以非常少的文档),如果术语很常见,则IDF将很低(许多文档除以许多文档~=1)。
假设您有100个食谱,除了一个不需要鸡蛋,现在您有另外三个包含单词“egg”的文档,第一个文档中出现一次,第二个文档中出现两次,第三个文档中出现一次。“egg”每个文档中的词频为1或2,文档频率为99(或者,可以说是102,如果计算新文档。我们坚持使用99)。
'egg'的TF-IDF为:
1 * log (100/99) = 0.01    # document 1
2 * log (100/99) = 0.02    # document 2
1 * log (100/99) = 0.01    # document 3

这些数字都比较小,相比之下,让我们来看另一个词,它只在你的100个食谱语料库中出现了9次:“芝麻菜”。它在第一个文档中出现了两次,在第二个文档中出现了三次,在第三个文档中则没有出现。
“芝麻菜”的TF-IDF值为:
1 * log (100/9) = 2.40  # document 1
2 * log (100/9) = 4.81  # document 2
0 * log (100/9) = 0     # document 3

"'芝麻菜'对于文档2非常重要,至少与'鸡蛋'相比如此。谁在乎鸡蛋出现了多少次?每个东西都含有鸡蛋!这些术语向量比简单计数更具信息性,并且它们将导致文档1和2(关于文档3)比使用简单的术语计数更接近。在这种情况下,可能会得出相同的结果(嘿!我们只有两个术语),但差异会更小。

这里的要点是TF-IDF生成更有用的文档中术语的度量,因此您不会专注于非常常见的术语(停用词,“鸡蛋”),而忽视重要的术语(“芝麻菜”)。"


1
实际公式,即sklearnTfIdf使用的公式是TF + TF*IDF - John Strood

8
完整的余弦相似度数学算法步骤在这些教程中有解释: 假设您想计算两个文档之间的余弦相似度,第一步是计算这两个文档的tf-idf向量。然后找到这两个向量的点积。这些教程将帮助您 :)

-1

-1

Tf-idf仅用于基于tf-词项频率-从文档中找到向量,该词项频率用于查找术语在文档中出现的次数和逆文档频率-它给出了术语在整个集合中出现的次数的度量。

然后,您可以找到文档之间的余弦相似度。


-1

TFIDF是一种逆文档频率矩阵,在寻找与文档矩阵的余弦相似性时返回相似的列表。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接