Косинусное расстояние — это распространенная метрика поиска схожих объектов, часто в разряженном пространстве. Поэтому косинусное расстоние часто применяют для сравнения текстов. Ниже приведу код для поиска наиболее похожего текста с помощью встроенных функций sklearn.
Пусть у нас есть большое количество текстов, предобработаем тексты с помощью tf-idf, после этого возьмем новый текст и найдем 3 самых похожих.
import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import linear_kernel # зададим массив текстов some_texts = [ 'текст номер один', 'текст следующий под номером два', 'третий набор слов', 'что-то ещё для полноценного дата-сета', 'пример текстового документа', ] df = pd.DataFrame({'texts': some_texts}) # А к данному тексту будем искать наиболее похожий из заданного выше набора find_nearest_to = "текст номер три" # формирование весов tf-idf tfidf = TfidfVectorizer() mx_tf = tfidf.fit_transform(some_texts) new_entry = tfidf.transform([find_nearest_to]) # расчет косинусного расстояния cosine_similarities = linear_kernel(new_entry, mx_tf).flatten() # запишем все попарные результаты сравнений df['cos_similarities'] = cosine_similarities # и отсортируем по убыванию (т.к. cos(0)=1) df = df.sort_values(by=['cos_similarities'], ascending=[0]) # Выведем 3 самых близких результата for index, row in df[0:3].iterrows(): print(row['texts'], row['cos_similarities']) # output: # текст номер один 0.7891589913464455 # текст следующий под номером два 0.23490553492076713 # третий набор слов 0.0
Заметим, что в данном примере мы не использовали cosine_similarity, а почему-то взяли linear_kernel. Дело в том, что когда вектора нормализованы (а они нормализованы после TfidfVectorizer) результат будет одинаковый, однако linear_kernel требует меньше вычислительной мощности и вычислится быстрее. Особенно это будет хорошо заметно на больших данных. Если же вектора не нормализованы, то правильно использовать sklearn.metrics.pairwise.cosine_similarity .
Пример также можно рассматривать как рекомендательную систему на большом корпусе каких-то объектов, работает быстро и хорошо подходит для бейзлайна. В случае с объектами не текстовыми, рекомендуется также попробовать использовать CountVectorizer, вместо TfidfVectorizer.