2016-11-03 2 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 - Спасибо, я предполагаю, что общее количество уникальных тем? Как я могу это найти? Количество тем может варьироваться от случая к случаю, мне, вероятно, понадобится способ подсчета их apriori – newdev14

1

С быстрым взглядом там Безразлично» t, похоже, является готовой функцией, которая будет принимать входные данные этой формы. У вас есть два варианта, которые будут зависеть от проблемы, размера массивов и прочего. Вы можете преобразовать каждый из двух векторов темы-веса в разреженные векторы scipy, а затем использовать cosine_similarity sklearn (http://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.cosine_similarity.html) ИЛИ вы можете просто написать свой собственный cosine_similarity. То, как я буду делать последнее, - это переносить каждый вектор на 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)) 
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

вы, вероятно, имеете в виду: max (d1.keys() + d2.keys()) + 1? – newdev14

+0

Ваш последний комментарий - это именно то, что у меня есть. для ясности, 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 - тема). – travelingbones

Смежные вопросы