Косинус Сходство векторов разной длины? - PullRequest
12 голосов
/ 26 июня 2010

Я пытаюсь использовать 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

Делает вектор так, чтобы 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))) 

Также - это порядокЗначения tf_idf в векторах важны?Должны ли они быть отсортированы - или это не имеет значения для этого расчета?

Ответы [ 3 ]

9 голосов
/ 30 июня 2010

Вам нужно умножить записи для соответствующих слов в векторе, поэтому для слов должен быть глобальный порядок. Это означает, что в теории ваши векторы должны быть одинаковой длины.

На практике, если один документ был просмотрен раньше другого, слова во втором документе могли быть добавлены в глобальный порядок после просмотра первого документа, поэтому даже если векторы имеют одинаковый порядок, первый документ может быть короче, поскольку в нем нет записей для слов, которых не было в этом векторе.

Документ 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 нулями в конце. На практике при вычислении скалярного произведения вам нужно только умножить элементы до конца вектора 1 (поскольку пропуск дополнительных элементов вектора 2 и умножение их на ноль абсолютно одинаковы, но посещение дополнительных элементов происходит медленнее).

Затем вы можете вычислить величину каждого вектора в отдельности, и для этого векторы не обязательно должны быть одинаковой длины.

6 голосов
/ 26 июня 2010

Вы вычисляете косинусное подобие векторов терминов?Термин векторов должен быть одинаковой длины.Если в документе нет слов, тогда для него должно быть значение 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, который не имеет смысла.

2 голосов
/ 19 февраля 2013

Попробуйте построить векторы перед передачей их в функцию 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))
...