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

eri*_*kcw 13 python nlp similarity nltk tf-idf

我正在尝试使用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
Run Code Online (Sandbox Code Playgroud)

切片向量使len(u)== len(v)正确的方法?我认为余弦相似性适用于不同长度的矢量.

我正在使用这个功能:

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))) 
Run Code Online (Sandbox Code Playgroud)

另外 - 向量中tf_idf值的顺序是否重要?它们应该被分类 - 或者对于这个计算是否不重要?

Ken*_*oom 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
Run Code Online (Sandbox Code Playgroud)

文件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
Run Code Online (Sandbox Code Playgroud)

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

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


Pac*_*ace 6

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

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

例:

Term | Doc1 | Doc2
Foo     .3     .7
Bar  |  0   |  8
Baz  |  1   |  1
Run Code Online (Sandbox Code Playgroud)

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


Vic*_*Yan 5

在将向量输入到 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))
Run Code Online (Sandbox Code Playgroud)