2010-06-25 5 views
10

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 

이 벡터를 얇게입니다 그래서 렌 (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 값의 순서인가? 그들은 정렬되어야합니까 - 아니면이 계산에 중요하지 않습니까?

답변

5

용어 벡터의 코사인 유사성을 계산하고 있습니까? 용어 벡터는 같은 길이 여야합니다. 단어가 문서에 없으면 해당 단어에 대해 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 점수를 비교할 수 있습니다.

+0

나는 cosine_distance 함수에 전달하고있어 벡터는 tf_idf 값의 파이썬 목록입니다. V [5] == [0.0060830126968545294, 0.00048241996565891193, 0.0020712248617478965, 0.0110036199241575, 0.0110036199241575] 당신은 순서가 중요한 말 - 벡터 (최소 ->의 가장 큰 질서의 내용을 정렬하는 올바른 방법이 무엇인지 문서의 단어?) – erikcw

+0

단어에 일부 전역 순서를 지정해야합니다. doc2에서 foo 앞에 bar가 나타나면 bar의 tf_idf 값은 여전히 ​​첫 번째 항목이어야합니다. – Pace

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 

이 경우 이론적으로 문서 1 벡터를 0으로 채워야합니다. 실제로, 내적을 계산할 때 벡터 1의 끝까지 요소를 곱하면됩니다 (벡터 2의 여분의 요소를 생략하고 0으로 곱하는 것은 똑같습니다. 그러나 여분의 요소를 방문하는 것은 더 느립니다).

그런 다음 각 벡터의 크기를 별도로 계산할 수 있으며 벡터의 길이가 동일 할 필요는 없습니다.

+0

코사인 유사성을 계산할 때 패딩 된 0은 차이를 만듭니다. 코사인 유사도에 사용하는 함수는 다음과 같습니다. cosine-similarity = dot-product (u, v)/sqrt (점 제품 (u, u)) * sqrt (점 제품 (v, v)) ([1, 1, 1, 1, 1, 1, 1, 1, 0, 0,], [1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1]) == 0.3333333333333333 코사인 유사도 ([1, 1, 1, 1, 1, 1, 1, 1], [1,1,00000000 ]) == 0.4714045207910316 문제는 코사인 유사성의 제수가 자체의 내적 결과를 수행한다는 것입니다. 그래서 패딩은 효과가 있습니다. 어쨌든이 문제를 알고 있습니까? – erikcw

+0

@erikcw :'Doc1 * Doc1'에 대한 내적을 계산할 때'Doc1'의 전체 길이로 갈 필요가 있습니다. 'Doc2 * Doc2'의 경우'Doc2'의 전체 길이로 갈 필요가 있습니다. 내적 제품의 해당 부분에 대해서는 더 긴 벡터를 자르지 말고 더 짧은 벡터를 채울 필요는 없습니다. 그러나'Doc1 * Doc2'를 계산할 때 더 긴 벡터를 안전하게자를 수 있습니다. 그래서 당신의 코드는 '코사인 유사성 (corosine-similarity)'기능을 사용하지 않고 패딩/절단에 대한 결정을 내리는 '점 - 제품'기능을 갖도록 설계되어야합니다. –

+0

@larsmans : 두 번째 그림의 벡터가 일치하지 않는 길이가 의도적입니다. –

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