2016-11-03 134 views
0

我试图找到代表两个文件的余弦相似如下:余弦相似

d1: [(0,1), (3,2), (6, 1)] 
d2: [(1,1), (3,1), (5,4), (6,2)] 

其中每个文档是一个主题的权重向量,其中的主题是在元组的第一个元素重量是第二个元素

我不知道如何去计算余弦相似性在这种情况下与这个加权计划? Python中是否有任何模块/软件包会让我做这样的事情?

回答

0

一个很简单的想法是创建的权重的向量,然后使用scipy.spatial.distance.cosine计算余弦距离(等于1-相似性):

In [1]: from scipy.spatial.distance import cosine 
In [2]: import numpy as np 
In [3]: d1 = [(0,1), (3,2), (6, 1)] 
In [4]: d2 = [(1,1), (3,1), (5,4), (6,2)] 
In [5]: def get_weights(d): 
    ...:  w = [ 0. ] * N 
    ...:  for i, weight in d: 
    ...:   w[i] = weight 
    ...:  return np.array(w) 
    ...: 

In [6]: w1 = get_weights(d1) 
In [7]: w2 = get_weights(d2) 
In [8]: 1-cosine(w1, w2) 
Out[8]: 0.3481553119113957 
+0

如果向量是长还是有很多可能的话题,那么你需要让他们疏 - 否则很危险,使他们密集。 – gabe

+0

的确,假设矢量很稀疏,并且有很多主题。 – mdml

+0

@mdml - 谢谢,我假设N是唯一主题的总数?我如何找到?主题的数量可能因案例而异,我可能需要一种方法来计算它们的先验性: – newdev14

1

随着快速看有没有按” t似乎是一种现成的功能,它将采用该形式的输入。你有两个选择,这取决于问题,阵列的大小和其他事情。您可以将两个主题权重矢量中的每一个转换为稀疏的scipy矢量,然后使用sklearn的cosine_similarity(http://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.cosine_similarity.html),或者您可以编写自己的余弦相似度。我会做后者的方式是将每个向量转换为字典(用于快速查找)。

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)) 
1

是的,python中有包, scikit-learn's cosine sim. documentation here。下面,我给你一个手动的方式来做到这一点:

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... 
+0

谢谢,但公式中的主题数是两个文档中的总数,而不是唯一的主题数量......这是什么需要 – newdev14

+0

你可能意思是:最大(d1.keys()+ d2.keys())+ 1? – newdev14

+0

你最近的评论正是我所拥有的。为清楚起见,最大(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是主题)。 – travelingbones