Косинусное сходство с использованием TFIDF

Есть несколько вопросов по SO и в сети, описывающих, как взять cosine similarity между двумя строками и даже между двумя строками с TFIDF в качестве весов. Но вывод такой функции, как linear_kernel из scikit меня немного смущает.

Рассмотрим следующий код:

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer

a = ['hello world', 'my name is', 'what is your name?']
b = ['my name is', 'hello world', 'my name is what?']

df = pd.DataFrame(data={'a':a, 'b':b})
df['ab'] = df.apply(lambda x : x['a'] + ' ' + x['b'], axis=1)
print(df.head())

                    a                 b                                   ab
0         hello world        my name is               hello world my name is
1          my name is       hello world               my name is hello world
2  what is your name?  my name is what?  what is your name? my name is what?

Вопрос: я хотел бы иметь столбец, который представляет собой косинусное сходство между строками в a и строками в b.

Что я пробовал:

Я обучил классификатор TFIDF на ab, чтобы включить все слова:

clf = TfidfVectorizer(ngram_range=(1, 1), stop_words='english')
clf.fit(df['ab'])

Затем я получил разреженную матрицу TFIDF из столбцов a и b:

tfidf_a = clf.transform(df['a'])
tfidf_b = clf.transform(df['b'])

Теперь, если я использую scikit linear_kernel, что рекомендуют другие, я возвращаю матрицу Грама (nfeatures, nfeatures), как указано в их документах.

from sklearn.metrics.pairwise import linear_kernel
linear_kernel(tfidf_a,tfidf_b)

array([[ 0.,  1.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])

Но мне нужен простой вектор, где первым элементом является cosin_sim между первой строкой a и первой строкой b, вторым элементом является cos_sim (a [1], b [1]) и т. Д. .

Используя python3, scikit-learn 0.17.


person David    schedule 21.04.2016    source источник


Ответы (2)


Я думаю, что ваш пример немного падает, потому что ваш TfidfVectorizer отфильтровывает большинство ваших слов, потому что у вас есть параметр stop_words = 'english' (вы включили почти все стоп-слова в пример). Я удалил это и сделал ваши матрицы плотными, чтобы мы могли видеть, что происходит. Что, если бы вы сделали что-то подобное?

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from scipy import spatial

a = ['hello world', 'my name is', 'what is your name?']
b = ['my name is', 'hello world', 'my name is what?']

df = pd.DataFrame(data={'a':a, 'b':b})
df['ab'] = df.apply(lambda x : x['a'] + ' ' + x['b'], axis=1)

clf = TfidfVectorizer(ngram_range=(1, 1))
clf.fit(df['ab'])

tfidf_a = clf.transform(df['a']).todense()
tfidf_b = clf.transform(df['b']).todense()

row_similarities = [1 - spatial.distance.cosine(tfidf_a[x],tfidf_b[x]) for x in range(len(tfidf_a)) ]
row_similarities

[0.0, 0.0, 0.72252389079716417]

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

person flyingmeatball    schedule 23.04.2016
comment
спасибо, это сработало. Почему вы не понимаете, как я строю полный корпус? - person David; 25.04.2016
comment
Потому что обычно есть лучший способ сделать это, чем использовать .apply для такого типа задач. Здесь 6 документов, 3 строки в двух столбцах, два отдельных документа (a и b) или 3 документа (по одному на строку). Это важно для вычисления частоты в TFIDF, и я не уверен, что способ построения ab теперь отражает то, что вы собираетесь делать. - person flyingmeatball; 25.04.2016

person    schedule
comment
Хотя этот фрагмент кода может решить проблему, он не объясняет, почему и как он отвечает на вопрос. Пожалуйста, включите объяснение своего кода, так как это действительно помогает улучшить качество вашего Почта. Помните, что вы отвечаете на вопрос для читателей в будущем, и эти люди могут не знать причины вашего предложения кода. - person Scott Weldon; 20.10.2016
comment
Я считаю этот код самодокументированным и даже не знаю Python. - person Seth; 04.10.2019
comment
Я чувствую, что где-то в рамках подобия косинуса должна быть функция косинуса, но ее нет. Почему? - person Adam Bajger; 03.04.2021