Косинус сходства векторов разной длины?

Я пытаюсь использовать 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 в векторах важен? Должны ли они сортироваться - или это не имеет значения для этого расчета?

Ответ 1

Вы вычисляете сходимость косинусов терминальных векторов? Термины векторов должны быть одинаковой длины. Если слов нет в документе, то для этого термина оно должно иметь значение 0.

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

Пример:

Term | Doc1 | Doc2
Foo     .3     .7
Bar  |  0   |  8
Baz  |  1   |  1

Здесь вы имеете два вектора (.3,0,1) и (.7,8,1) и можете вычислить сходство косинусов между ними. Если вы сравнили (.3,1) и (.7,8), вы бы сравнили оценку Doc1 Baz с партией Doc2 Bar, которая не имела бы смысла.

Ответ 2

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

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

Документ 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

В этом случае теоретически вам нужно вставить вектор Document 1 с нулями в конце. На практике при вычислении точечного продукта вам нужно только умножить элементы до конца вектора 1 (так как исключение дополнительных элементов вектора 2 и их умножение на ноль точно совпадают, но посещение дополнительных элементов происходит медленнее).

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

Ответ 3

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