Python 带权文档的余弦相似性
我试图找出两份文件的余弦相似性,如下所示:Python 带权文档的余弦相似性,python,scikit-learn,cosine-similarity,trigonometry,Python,Scikit Learn,Cosine Similarity,Trigonometry,我试图找出两份文件的余弦相似性,如下所示: d1: [(0,1), (3,2), (6, 1)] d2: [(1,1), (3,1), (5,4), (6,2)] 其中,每个文档都是主题权重向量,其中主题是元组中的第一个元素,权重是第二个元素 我不知道在这种情况下,如何使用这种加权方案来计算余弦相似性?Python中是否有任何模块/包可以让我做这样的事情 一个非常简单的想法是创建一个权重向量,然后使用它来计算余弦距离(等于1-相似度): 通过快速查看,似乎没有现成的函数可以接受这种形式的输入。
d1: [(0,1), (3,2), (6, 1)]
d2: [(1,1), (3,1), (5,4), (6,2)]
其中,每个文档都是主题权重向量,其中主题是元组中的第一个元素,权重是第二个元素
我不知道在这种情况下,如何使用这种加权方案来计算余弦相似性?Python中是否有任何模块/包可以让我做这样的事情 一个非常简单的想法是创建一个权重向量,然后使用它来计算余弦距离(等于1-相似度):
通过快速查看,似乎没有现成的函数可以接受这种形式的输入。您有两种选择,这取决于问题、数组的大小和其他因素。您可以将两个主题权重向量转换为稀疏scipy向量,然后使用sklearn的cosine_相似度(),也可以编写自己的cosine_相似度。我做后者的方法是将每个向量转换为dict(以便更快地查找),如下所示
import math
def vect_to_topic_weight(vector):
return {a:b for a,b in vector}
def norm(vector):
return math.sqrt(sum(vector[k]**2 for k in vector.iterkeys()))
def dot(a,b):
return sum(a[k]*b.get(k,0) for k in a.iterkeys())
# returns the cosine_similarity, with inputs as topic_weight dicts
def cosine_similarity(a, b):
return dot(a,b) / float(norm(a)*norm(b))
是的,有python中的包,例如。下面我为您提供了一种手动方式:
import numpy as np
d1 = dict([(0,1), (3,2), (6, 1)])
d2 = dict([(1,1), (3,1), (5,4), (6,2)])
l = max(d1.keys() + d2.keys()) + 1 ## Number of topics observed
v1 = np.zeros((l,))
for i in xrange(l):
if i in d1.keys():
v1[i] = d1[i]
v2 = np.zeros((l,))
for i in xrange(l):
if i in d2.keys():
v2[i] = d2[i]
## now v1 and v2 are 1-d np arrays representing your docs.
v1 = v1/np.sqrt(np.dot(v1,v1)) ## normalize
v2 = v2/np.sqrt(np.dot(v2,v2)) ## normalize
cos_sim = np.dot(v1,v2) ## should get .348155...
如果向量很长,或者有很多可能的主题,那么您希望保持它们稀疏,否则使它们密集是危险的。如果向量稀疏,并且有很多主题,则为True。@mdml-谢谢,我假设N是唯一主题的总数?我怎么能找到呢?主题的数量可能因情况而异,我可能需要一种方法来计算它们apriori@newdev14:完全正确,
N
是主题的数量。应该足够简单,例如,max(d1+d2中的d为d[0])
Yes,或者参见travelingbones的答案/注释,其获得n个等级的方式类似,但公式中的主题数量是两个文档的总数,而不是唯一的主题数量…这是所需的。您可能的意思是:max(d1.keys()+d2.keys())+1?你最后的评论和我的一模一样。为了清楚起见,max(d1.keys()+d2.keys())=max([0,3,6]+[1,3,5,6])=max([0,3,6,1,3,5,6])=6。我们想要+1 b/c主题的数量是7(0是一个主题)。作为一般规则,使用ipython,在中键入每行(或子行的每个元素),并让它对其求值,以便您可以看到代码在做什么。
import numpy as np
d1 = dict([(0,1), (3,2), (6, 1)])
d2 = dict([(1,1), (3,1), (5,4), (6,2)])
l = max(d1.keys() + d2.keys()) + 1 ## Number of topics observed
v1 = np.zeros((l,))
for i in xrange(l):
if i in d1.keys():
v1[i] = d1[i]
v2 = np.zeros((l,))
for i in xrange(l):
if i in d2.keys():
v2[i] = d2[i]
## now v1 and v2 are 1-d np arrays representing your docs.
v1 = v1/np.sqrt(np.dot(v1,v1)) ## normalize
v2 = v2/np.sqrt(np.dot(v2,v2)) ## normalize
cos_sim = np.dot(v1,v2) ## should get .348155...