Косинус сходства векторов разной длины?
Я пытаюсь использовать 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))