Как рассчитать схожесть предложения, используя модель word2vec gensim с python

Согласно Gensim Word2Vec, я могу использовать модель word2vec в пакете gensim для вычисления сходства между двумя словами.

например.

trained_model.similarity('woman', 'man') 
0.73723527

Однако модель word2vec не может предсказать сходство предложения. Я узнал модель LSI с подобием предложения в gensim, но, похоже, это не может сочетаться с моделью word2vec. Длина тела каждого предложения у меня не очень длинная (короче 10 слов). Итак, есть ли какие-то простые способы достижения этой цели?

Ответ 1

На самом деле это довольно сложная проблема, о которой вы просите. Вычисление сходства предложений требует построения грамматической модели предложения, понимания эквивалентных структур (например, "он ходил в магазин вчера" и "вчера, он ходил в магазин" ), обнаруживая сходство не только в местоимениях и глаголах, но и в правильные существительные, поиск статистических совпадений/отношений во множестве реальных текстовых примеров и т.д.

Простейшая вещь, которую вы могли бы попробовать - хотя я не знаю, как бы это было хорошо, и это, безусловно, не дало бы вам оптимальных результатов - было бы сначала удалить все "стоп-слова" (такие слова, как "the", "an" и т.д., которые не добавляют большого значения в предложение), а затем запустите word2vec в словах в обоих предложениях, суммируйте векторы в одном предложении, суммируйте векторы в другом предложении, а затем найдите разница между суммами. Суммируя их вместо того, чтобы делать разницу по словам, вы, по крайней мере, не будете подчиняться порядку слов. Это, как говорится, будет терпеть неудачу во многих отношениях и не будет хорошим решением любыми способами (хотя хорошие решения этой проблемы почти всегда связаны с некоторым количеством НЛП, машинным обучением и другой умностью).

Итак, короткий ответ: нет, нет простого способа сделать это (по крайней мере, не делать это хорошо).

Ответ 2

Поскольку вы используете gensim, вам, вероятно, следует использовать его реализацию doc2vec. doc2vec является расширением word2vec до phrase-, sentence- и уровня документа. Это довольно простое расширение, описанное здесь

http://cs.stanford.edu/~quocle/paragraph_vector.pdf

Gensim хорош, потому что он интуитивно понятен, быстр и гибок. Замечательно, что вы можете получить предварительно подготовленные вложения слов с официальной страницы word2vec, а слой syn0 модели gensim Doc2Vec представлен так, что вы можете заполнять вложения слов этими высококачественными векторами!

GoogleNews-векторы-negative300.bin.gz

Я думаю, что gensim, безусловно, самый простой (и пока для меня лучший) инструмент для встраивания предложения в векторное пространство.

Существуют другие методы sentence- для векторного, чем тот, который был предложен в статье Ле и Миколова выше. Сохер и Мэннинг из Стэнфорда, безусловно, являются двумя самыми известными исследователями, работающими в этой области. Их работа основана на принципе композиционно - семантика предложения происходит от:

1. semantics of the words

2. rules for how these words interact and combine into phrases

Они предложили несколько таких моделей (становящихся все более и более сложными) о том, как использовать композицию для построения представлений уровня sentence-.

2011 - развертывание рекурсивного автоэнкодера (очень просто. Начните здесь, если интересно)

2012 - матрично-векторная нейронная сеть

2013 - нейронная тензорная сеть

2015 - Дерево ЛСТМ

все его работы доступны на socher.org. Некоторые из этих моделей доступны, но я все же рекомендую gensim doc2vec. Во-первых, УРАЭ 2011 года не особенно сильна. Кроме того, он предварительно подготовлен с весами, подходящими для перефразирования новостных данных. Код, который он предоставляет, не позволяет вам переучивать сеть. Вы также не можете поменять местами разные векторы слов, так что вы застряли с вложениями 2011 года pre-word2vec из Turian. Эти векторы, конечно, не находятся на уровне word2vec или GloVe.

Еще не работал с Tree LSTM, но это выглядит очень многообещающе!

tl; dr Да, используйте gensim doc2vec. Но другие методы существуют!

Ответ 3

Если вы используете word2vec, вам нужно вычислить средний вектор для всех слов в каждом предложении/документе и использовать косинусное сходство между векторами:

import numpy as np
from scipy import spatial

index2word_set = set(model.wv.index2word)

def avg_feature_vector(sentence, model, num_features, index2word_set):
    words = sentence.split()
    feature_vec = np.zeros((num_features, ), dtype='float32')
    n_words = 0
    for word in words:
        if word in index2word_set:
            n_words += 1
            feature_vec = np.add(feature_vec, model[word])
    if (n_words > 0):
        feature_vec = np.divide(feature_vec, n_words)
    return feature_vec

Рассчитать сходство:

s1_afv = avg_feature_vector('this is a sentence', model=model, num_features=300, index2word_set=index2word_set)
s2_afv = avg_feature_vector('this is also sentence', model=model, num_features=300, index2word_set=index2word_set)
sim = 1 - spatial.distance.cosine(s1_afv, s2_afv)
print(sim)

> 0.915479828613

Ответ 4

вы можете использовать алгоритм расстояния между словами. здесь простое описание об ОМУ.

#load word2vec model, here GoogleNews is used
model = gensim.models.KeyedVectors.load_word2vec_format('../GoogleNews-vectors-negative300.bin', binary=True)
#two sample sentences 
s1 = 'the first sentence'
s2 = 'the second text'

#calculate distance between two sentences using WMD algorithm
distance = model.wmdistance(s1, s2)

print ('distance = %.3f' % distance)

P.s.: Если вы столкнулись с ошибкой об импорте библиотеки pyemd, ее можно установить с помощью следующей команды:

pip install pyemd

Ответ 5

Как только вы вычислите сумму двух наборов словесных векторов, вы должны взять косинус между векторами, а не diff. Косинус может быть вычислен путем принятия точечного произведения двух векторов, нормированных. Таким образом, количество слов не является фактором.

Ответ 6

Я использую следующий метод, и он работает хорошо. Сначала вам нужно запустить POSTagger, а затем отфильтровать ваше предложение, чтобы избавиться от слов остановки (детерминанты, союзы,...). Я рекомендую TextBlob APTagger. Затем вы строите word2vec, беря среднее значение каждого слова в предложении. Метод n_similarity в Gemsim word2vec делает именно это, позволяя сравнивать два набора слов для сравнения.

Ответ 7

Я хотел бы обновить существующее решение, чтобы помочь людям, которые собираются рассчитать семантическое сходство предложений.

Шаг 1:

Загрузите подходящую модель с помощью gensim и вычислите слова векторов для слов в предложении и сохраните их как список слов

Шаг 2: Вычисление вектора предложения

Вычисление семантического сходства между предложениями было затруднено до недавнего времени бумагой, названной " ПРОСТОЙ, НО КАТЕГОРИЯ БАЗЫ ДЛЯ ПРЕДОСТАВЛЕНИЯ EMBEDDINGS ", который предлагает простой подход, вычисляя взвешенное среднее словесных векторов в предложении и затем удаляя проекции средних векторов на их первую основную компоненту. Если вес слова w является /( a + p (w)), причем параметр a является параметром и p (w) (оценочная) частота слов, называемая гладкой инверсной частотой. Этот метод работает значительно лучше.

Простой код для вычисления вектора предложения с использованием SIF (гладкая обратная частота) предложенный в документе метод был представлен здесь

Шаг 3: используя sklearn cosine_similarity загружают два вектора для предложений и вычисляют сходство.

Это самый простой и эффективный метод вычисления сходства предложений.

Ответ 8

Существуют расширения Word2Vec, предназначенные для решения проблемы сравнения более длинных фрагментов текста, таких как фразы или предложения. Один из них - para2vec или doc2vec.

"Распределенные представления предложений и документов" http://cs.stanford.edu/~quocle/paragraph_vector.pdf

http://rare-technologies.com/doc2vec-tutorial/

Ответ 9

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

Я думал, что должен передумать и вместо этого использовать вложение предложений, как описано в этой статье и this.

Ответ 10

Существует функция из документации принимает список слов и сравнивая их сходство.

s1 = 'This room is dirty'
s3 = 'dirty and disgusting room'

distance = model.wv.n_similarity(s1.lower().split(), s2.lower().split())

Ответ 11

Исследовательская группа Facebook выпустила новое решение под названием InferSent. Результаты и код опубликованы на Github, проверьте их репозиторий. Это довольно круто. Я планирую использовать это. https://github.com/facebookresearch/InferSent

их статья https://arxiv.org/abs/1705.02364 Аннотация: Многие современные системы НЛП используют в качестве базовых функций встраивание слов, ранее обучавшихся неконтролируемым образом в больших корпусах. Однако попытки получить вложения для больших кусков текста, таких как предложения, не были столь успешными. Несколько попыток изучения неконтролируемых представлений предложений не достигли достаточной производительности, чтобы быть широко принятыми. В этой статье мы покажем, как универсальные представления предложений, обученные с использованием контролируемых данных из наборов данных Stanford Natural Language Inference, могут последовательно превосходить неконтролируемые методы, такие как векторы SkipThought, в широком спектре задач переноса. Подобно тому, как компьютерное зрение использует ImageNet для получения функций, которые затем могут быть перенесены на другие задачи, наша работа, как правило, указывает на пригодность логического вывода для передачи обучения другим задачам НЛП. Наш кодировщик общедоступен.

Ответ 12

Gensim реализует модель под названием Doc2Vec для встраивания абзацев.

Существуют различные учебные пособия, представленные как записные книжки IPython:

Другой метод будет опираться на Word2Vec и Word Mover Distance (WMD), как показано в этом руководстве:

Альтернативным решением было бы полагаться на средние векторы:

from gensim.models import KeyedVectors
from gensim.utils import simple_preprocess    

def tidy_sentence(sentence, vocabulary):
    return [word for word in simple_preprocess(sentence) if word in vocabulary]    

def compute_sentence_similarity(sentence_1, sentence_2, model_wv):
    vocabulary = set(model_wv.index2word)    
    tokens_1 = tidy_sentence(sentence_1, vocabulary)    
    tokens_2 = tidy_sentence(sentence_2, vocabulary)    
    return model_wv.n_similarity(tokens_1, tokens_2)

wv = KeyedVectors.load('model.wv', mmap='r')
sim = compute_sentence_similarity('this is a sentence', 'this is also sentence', wv)
print(sim)

Наконец, если вы можете запустить Tensorflow, вы можете попробовать: https://tfhub.dev/google/universal-sentence-encoder/2