Ответ
Инвариантность к длине вектора (масштабу) — это ключевое свойство, которое делает cosine similarity особенно полезным для поиска ближайших соседей в задачах обработки текстов и рекомендательных систем.
Почему это важно:
- При сравнении текстовых документов, представленных в виде векторов (TF-IDF, word2vec, BERT-эмбеддинги), длина вектора часто соответствует количеству слов или общей частоте терминов. Два документа на одну тему могут сильно различаться по длине (например, краткая статья и подробный обзор), но иметь схожее семантическое направление.
- Cosine similarity измеряет косинус угла между векторами, игнорируя их евклидову норму. Это позволяет находить семантически близкие объекты, даже если они имеют разную «интенсивность».
Пример на Python:
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
# Два документа с одинаковой тематикой, но разной длиной
doc_short = np.array([1, 2, 1]) # TF-IDF для короткого текста
doc_long = np.array([10, 20, 10]) # TF-IDF для длинного текста (тот же баланс терминов)
doc_other = np.array([1, 0, 3]) # Документ на другую тему
print("Cosine similarity (short vs long):", cosine_similarity([doc_short], [doc_long])[0][0]) # 1.0
print("Euclidean distance (short vs long):", np.linalg.norm(doc_short - doc_long)) # Большое значение
print("Cosine similarity (short vs other):", cosine_similarity([doc_short], [doc_other])[0][0]) # ~0.5345
Другие преимущества для nearest neighbor search:
- Эффективность для разреженных данных: Хорошо работает с разреженными матрицами (например, TF-IDF), где большинство элементов — нули.
- Устойчивость к доминированию частых признаков: В рекомендательных системах пользователь с большим количеством взаимодействий не будет автоматически считаться похожим на всех.
Когда использовать: Поиск похожих документов, коллаборативная фильтрация, кластеризация текстовых эмбеддингов.
Ответ 18+ 🔞
Давай разберём эту штуку, как будто я тебе на кухне объясняю, с пивом в руке. Сиди, слушай.
Вот представь: есть у тебя два текста. Один — короткий пост в телеге, три строчки. Другой — целая диссертация на ту же тему. По логике, они про одно и то же, да? Но если тупо сравнивать цифры, как будто ты взвешиваешь картошку, то диссертация будет весить овердохуища. И обычная метрика расстояния скажет: «Нет, брат, они разные, как Луна и жопа». А это же пиздец как несправедливо!
Так вот, инвариантность к длине вектора (масштабу) — это как раз волшебный пендель этой проблеме в сраку. Косинусная мера смотрит не на «вес», а на направление. Как будто сравнивает не две кучи картошки, а два вектора — куда они смотрят. Если оба смотрят в одну сторону (тематика одна), то косинус угла между ними будет близок к единице, даже если один вектор — спичка, а другой — телеграфный столб.
Почему это охренительно важно:
- Всякие там TF-IDF, эмбеддинги из BERT — это по сути и есть вектора. Длина — это частота слов или общая «болтливость» документа. А косинусной мере похуй на болтливость. Её интересует суть, семантический курс.
- Она измеряет косинус угла. Угол ноль градусов? Косинус 1.0. Идеальное совпадение по смыслу. И не важно, что один документ — это «люблю пиццу», а второй — трёхтомник «История пиццы от неолита до наших дней».
Смотри, как это в коде выглядит, ёпта:
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
# Два документа на одну тему. Один — чирикнул, второй — разорался.
doc_short = np.array([1, 2, 1]) # Короткий текст, TF-IDF мелкий
doc_long = np.array([10, 20, 10]) # Длинный текст, но пропорции те же! Тот же баланс слов.
doc_other = np.array([1, 0, 3]) # А это уже про другое совсем
print("Косинусная близость (короткий vs длинный):", cosine_similarity([doc_short], [doc_long])[0][0]) # 1.0
print("Евклидово расстояние (короткий vs длинный):", np.linalg.norm(doc_short - doc_long)) # Цифра огромная, пиздец!
print("Косинусная близость (короткий vs другой):", cosine_similarity([doc_short], [doc_other])[0][0]) # ~0.5345
Видишь? Евклидова метрика — терпения ноль ебать — орет, что документы разные (большая цифра = большое расстояние). А косинусная — хитрая жопа — говорит: «Ребят, вы в одном направлении, у вас косинус 1.0, полная идентичность по смыслу». А с третьим, другим документом, она честно показывает ~0.53, мол, есть сходство, но так себе.
Чем ещё она хороша для поиска соседей:
- Любит разреженные данные. Когда в твоей матрице из нулей торчат единички (как в TF-IDF), она не парится и работает быстро.
- Не даёт засилью частых признаков всех обмануть. В рекомендашках: если один юзер лайкнул хуй в пальто всего, а другой — только пять фильмов, но осмысленно, они не станут «похожими» только потому, что первый — маньяк-активист.
Короче, когда это юзать: Когда ищешь похожие документы, строишь рекомендации или кластеризуешь текстовые эмбеддинги. Когда тебе важна суть, а не размер. А если нужно учитывать именно «вес» или интенсивность — тогда это не твой инструмент, иди на евклидову метрику. Всё, вопрос закрыт.