Вычислить Косинус сходство дано 2 строки приговора


С Python: tf-idf-cosine: чтобы найти сходство документа, можно рассчитать сходство документов с помощью Косинуса tf-idf. Без импорта внешних библиотек, это какие-либо способы вычисления косинусного сходства между 2 строками?

s1 = "This is a foo bar sentence ."
s2 = "This sentence is similar to a foo bar sentence ."
s3 = "What is this string ? Totally not related to the other two lines ."

cosine_sim(s1, s2) # Should give high cosine similarity
cosine_sim(s1, s3) # Shouldn't give high cosine similarity value
cosine_sim(s2, s3) # Shouldn't give high cosine similarity value
4 54

4 ответа:

простая реализация pure-Python будет:

import re, math
from collections import Counter

WORD = re.compile(r'\w+')

def get_cosine(vec1, vec2):
     intersection = set(vec1.keys()) & set(vec2.keys())
     numerator = sum([vec1[x] * vec2[x] for x in intersection])

     sum1 = sum([vec1[x]**2 for x in vec1.keys()])
     sum2 = sum([vec2[x]**2 for x in vec2.keys()])
     denominator = math.sqrt(sum1) * math.sqrt(sum2)

     if not denominator:
        return 0.0
     else:
        return float(numerator) / denominator

def text_to_vector(text):
     words = WORD.findall(text)
     return Counter(words)

text1 = 'This is a foo bar sentence .'
text2 = 'This sentence is similar to a foo bar sentence .'

vector1 = text_to_vector(text1)
vector2 = text_to_vector(text2)

cosine = get_cosine(vector1, vector2)

print 'Cosine:', cosine

принты:

Cosine: 0.861640436855

косинусная формула, используемая здесь, описана здесь.

это не включает взвешивание слов tf-idf, но для использования tf-idf вам нужно иметь достаточно большой корпус, из которого можно оценить веса tfidf.

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

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

смысл слова

наиболее важным предположением здесь является то, что можно получить вектор, который представляет каждый слово в рассматриваемом предложении. Этот вектор обычно выбирается для захвата контекстов, в которых может появиться слово. Например, если мы рассмотрим только три контекста "ешь", "красный" и "пушистый", слово "кошка" может быть представлено как [98, 1, 87], потому что если бы вы прочитали очень очень длинный кусок текста (несколько миллиардов слов не редкость по сегодняшнему стандарту), слово "кошка" появилось бы очень часто в контексте "пушистый" и "ешь", но не так часто в контексте "красный". Точно так же" собака "может быть представлена как [87,2,34], а" зонтик " может быть [1,13,0]. Представляя эти векторы как точки в трехмерном пространстве, " кошка "явно ближе к" собаке", чем к" зонтику", поэтому" кошка "также означает нечто более похожее на" собаку", чем на"зонтик".

эта линия работы была исследована с начала 90-х годов (например,этой работа Греффенштетта) и дал некоторые удивительно хорошие результаты. Например, вот несколько случайных записей в тезаурусе, который я недавно построил, мой компьютер прочитал Википедию:

theory -> analysis, concept, approach, idea, method
voice -> vocal, tone, sound, melody, singing
james -> william, john, thomas, robert, george, charles

эти списки похожих слов были получены полностью без вмешательства человека-вы вводите текст и возвращаетесь через несколько часов.

проблема с ключевыми словами

надежно установите, на что похож X, нам нужно увидеть много примеров использования X в контексте. Когда X-это одно слово, такое как" голос", это не слишком сложно. Однако, поскольку X становится больше, шансы найти естественные вхождения X становятся экспоненциально медленнее. Для сравнения, у Google есть около 1B страниц, содержащих слово "fox" , и ни одной страницы, содержащей "ginger foxes love fruit", несмотря на то, что это совершенно правильное английское предложение, и мы все понимаем, что это средства.

состав

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

самый простой и очевидный способ-сложить или умножить отдельные векторы слов вместе. Это приводит к нежелательному побочному эффекту, что " кошки Чейз собаки " и "собаки Чейз кошки" будет означать то же самое для вашей системы. Кроме того, если вы умножаете, вы должны быть очень осторожны, или каждое предложение будет представлено [0,0,0,...,0], который побеждает точку.

более дальнеишее чтение

Я не буду обсуждать более сложные методы композиции, которые были до сих пор предложены. Я предлагаю вам прочитать Катрин Эрк "векторные пространственные модели значения слова и значения фразы: опрос". Это очень хороший опрос высокого уровня, чтобы вы начали. К сожалению, не находится в свободном доступе на веб-сайте издателя, напишите автору напрямую, чтобы получить копию. В этой статье вы найдете ссылки на многие другие конкретные методы. Более понятные из них являются Митчел и Lapata (2008) и Барони и Зампарелли (2010).


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

спасибо @vpekar за вашу реализацию. Это очень помогло. Я только что обнаружил, что он пропускает вес tf-idf при вычислении косинусного подобия. Счетчик (слово) возвращает словарь, который имеет список слов вместе с их появлением.

потому что(м, д) = сим(м, д) = (д · д)/(|г||д|) = (сумма(Ци, Ди)/(корень(сумма(qi2)))*(корень(сумма(ви2))) где я = 1 до V)

  • qi-это вес TF-idf Терма i в запросе.
  • di-это tf-idf
  • вес термина I в документе. |q / и| d / - длины q и Д.
  • это косинусное подобие q и d . . . . . . или, эквивалентно, косинус угла между q и d.

пожалуйста, не стесняйтесь просматривать мой код здесь. Но сначала вам нужно будет загрузить пакет anaconda. Он автоматически установит вам путь python в Windows. Добавьте этот интерпретатор python в Eclipse.

Ну, если вы знаете о слово вложениями как перчатка/Word2Vec/Numberbatch, ваша работа наполовину сделана. Если не позволите мне объяснить, как это можно решить. Преобразуйте каждое предложение в маркеры слов и представляйте каждый из этих маркеров как векторы высокой размерности (используя предварительно обученные вложения слов, или вы могли бы железнодорожный них себе даже!). Итак, теперь вы просто не фиксируете их поверхностное сходство, а скорее извлекаете значение каждого слова, которое включает предложение в целом. После этого вычислите их косинусное подобие и вы будете установлены.