不同长度矢量的余弦相似度?

时间:2010-06-25 20:27:51

标签: python nlp similarity nltk tf-idf

I'm trying to use TF-IDF将文档分类。我已经为某些文档计算了tf_idf,但现在当我尝试计算其中两个文档之间的余弦相似度时,我得到一个追溯说:

#len(u)==201, len(v)==246

cosine_distance(u, v)
ValueError: objects are not aligned

#this works though:
cosine_distance(u[:200], v[:200])
>> 0.52230249969265641

是否对矢量进行切片以使len(u)== len(v)正确的方法?我认为余弦相似性适用于不同长度的矢量。

我正在使用this function

def cosine_distance(u, v):
    """
    Returns the cosine of the angle between vectors v and u. This is equal to
    u.v / |u||v|.
    """
    return numpy.dot(u, v) / (math.sqrt(numpy.dot(u, u)) * math.sqrt(numpy.dot(v, v))) 

另外 - 矢量中tf_idf值的顺序是否重要?它们应该被排序 - 或者这个计算不重要吗?

3 个答案:

答案 0 :(得分:9)

您需要将向量中相应单词的条目相乘,因此应该有单词的全局顺序。这意味着理论上你的向量应该是相同的长度。

实际上,如果在另一个文档之前看到一个文档,则在看到第一个文档后,第二个文档中的单词可能已添加到全局顺序中,因此即使向量具有相同的顺序,第一个文档也可能是更短,因为它没有不在该向量中的单词的条目。

文件1:快速的棕色狐狸跳过懒狗。

Global order:     The quick brown fox jumped over the lazy dog
Vector for Doc 1:  1    1     1    1     1     1    1   1   1

文件2:跑步者很快。

Global order:     The quick brown fox jumped over the lazy dog runner was
Vector for Doc 1:  1    1     1    1     1     1    1   1   1
Vector for Doc 2:  1    1     0    0     0     0    0   0   0    1     1

在这种情况下,理论上你需要在末尾填充带有零的Document 1向量。实际上,在计算点积时,您只需要将元素乘以向量1的末尾(因为省略向量2的额外元素并将它们乘以零完全相同,但访问额外元素的速度较慢)。

然后你可以分别计算每个向量的大小,为此,向量不需要具有相同的长度。

答案 1 :(得分:6)

你在计算术语向量的余弦相似度吗?术语向量应该是相同的长度。如果文档中没有单词,则该术语的值应为0.

我不确定你使用余弦相似性的矢量是什么,但是当进行余弦相似时,你的矢量应该总是相同的长度和顺序非常重要。

示例:

Term | Doc1 | Doc2
Foo     .3     .7
Bar  |  0   |  8
Baz  |  1   |  1

这里有两个向量(.3,0,1)和(.7,8,1),可以计算它们之间的余弦相似度。如果您比较(.3,1)和(.7,8),您将比较Baz的Doc1分数与Bar的Doc2分数,这是没有意义的。

答案 2 :(得分:2)

尝试构建向量,然后将它们提供给cosine_distance函数:

import math
from collections import Counter
from nltk import cluster

def buildVector(iterable1, iterable2):
    counter1 = Counter(iterable1)
    counter2= Counter(iterable2)
    all_items = set(counter1.keys()).union( set(counter2.keys()) )
    vector1 = [counter1[k] for k in all_items]
    vector2 = [counter2[k] for k in all_items]
    return vector1, vector2


l1 = "Julie loves me more than Linda loves me".split()
l2 = "Jane likes me more than Julie loves me or".split()


v1,v2= buildVector(l1, l2)
print(cluster.util.cosine_distance(v1,v2))