WedX - журнал о программировании и компьютерных науках

Как рассчитать схожесть предложений с использованием word2vec модели gensim с Python

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

e.g.

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

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

02.03.2014

  • Эта проблема обсуждается (среди прочего) в руководстве по ACL: youtube.com/ смотреть? v = _ASOqXiWBVo & feature = youtu.be 04.08.2014
  • Теперь вы можете использовать doc2vec от gensim и получать схожесть предложений из того же модуля 21.08.2015
  • @kampta. Привет, не могли бы вы предложить какой-нибудь пост, показывающий реализацию? 02.08.2018
  • Оформить заказ red-technologies.com/doc2vec-tutorial 06.08.2018

Ответы:


1

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

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

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

02.03.2014
  • Я думаю, вы правы. Самый простой способ - собрать все векторы слов в одном предложении и найти разницу между суммами. Кстати, будет ли этот простой метод влиять на подсчет слов? Потому что чем больше слов в одном предложении, тем больше будет суммировано гистограмма. 03.03.2014
  • @zhfkt, скорее всего, да. Таким образом, вам может потребоваться разделить на количество слов или что-то подобное, чтобы попытаться вычленить это. В любом случае, любая подобная эвристика будет иметь серьезные недостатки. 04.03.2014
  • См. Также datascience.stackexchange.com/questions/23969/ 10.08.2019

  • 2

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

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

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

    GoogleNews-vectors-negative300.bin.gz (ссылка на ссылку в Google Code)

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

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

    1. semantics of the words
    
    2. rules for how these words interact and combine into phrases
    

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

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

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

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

    2015 - Tree LSTM

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

    Еще не работал с Tree LSTM, но он кажется очень многообещающим!

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

    14.07.2015
  • У вас есть дополнительная информация о том, как инициализировать модель doc2vec с предварительно обученными значениями word2vec? 09.05.2018

  • 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
    
    29.01.2016
  • Не могли бы вы дать больше объяснений по index2word_set и model.index2word? Спасибо. 19.04.2017
  • Обратите внимание, что вычисление среднего вектора - это такой же произвольный выбор, как и не вычисление его вообще. 16.08.2017
  • Я удивлен, почему это не лучший ответ, он работает достаточно хорошо и не имеет проблемы с последовательностью, как у метода усреднения. 05.09.2019
  • Это ответ, который я искал. Моя проблема решена. Спасибо за решение 02.12.2019

  • 4

    вы можете использовать алгоритм Word Mover's Distance. вот простое описание ОМУ.

    #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
    
    02.10.2017
  • Раньше я использовал WMD, он работает тихо, но при этом подавится большим корпусом. Попробуйте SoftCosineSimilarity. Также найдено в gensim (twitter.com/gensim_py/status/963382840934195200) 18.06.2018
  • Однако WMD не очень быстр, когда вы хотите запросить корпус. 10.01.2019

  • 5

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

    05.05.2014
  • не могли бы вы предоставить немного псевдокода о том, как это сделать (я не использую gensim / python) 02.09.2018

  • 6

    В документации есть функция, которая собирает список слов и сравнивает их сходство.

    s1 = 'This room is dirty'
    s2 = 'dirty and disgusting room' #corrected variable name
    
    distance = model.wv.n_similarity(s1.lower().split(), s2.lower().split())
    
    22.05.2018

    7

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

    Шаг 1:

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

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

    Раньше вычисление семантического сходства между предложениями было затруднительным, но недавно появилась статья под названием «ПРОСТАЯ, НО ТРУДНАЯ БАЗА FOR SENTENCE EMBEDDINGS », который предлагает простой подход, заключающийся в вычислении средневзвешенного значения векторов слов в предложении и последующем удалении проекций средних векторов на их первый главный компонент. Здесь вес слова w равен / (a + p (w)), где a является параметром, а p (w) - (оценочной) частотой слов, называемой сглаженной обратной частотой. Этот метод работает значительно лучше.

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

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

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

    06.06.2017
  • очень хорошая бумага. примечание: ссылка на реализацию SIF требует написания метода get_word_frequency (), который можно легко выполнить, используя Python Counter () и вернув dict с ключами: уникальные слова w, значения: # w / # total doc len 25.07.2017

  • 8

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

    08.10.2014
  • В чем разница между взятием среднего значений векторов и их сложением для создания вектора предложения? 01.07.2015
  • Разница в том, что размер вектора фиксирован для всех предложений. 13.08.2015
  • Нет никакой разницы, пока вы используете косинусное подобие. @lechatpito Ничего общего с размером вектора. Векторы суммируются, а не объединяются. 02.02.2019

  • 9

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

    «Распределенное представление приговоров и документов» https://cs.stanford.edu/~quocle/paragraph_vector.pdf

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

    24.08.2015
  • Вкратце стоит упомянуть, как работает представленный алгоритм. По сути, вы добавляете уникальный токен к каждому высказыванию и вычисляете векторы word2vec. В конце вы получите векторы слов для каждого вашего слова в корпусе (при условии, что вы запрашиваете все слова, а также уникальные). Каждый уникальный знак в высказывании будет представлять это высказывание. Есть некоторые разногласия по поводу результатов, представленных в документе, но это уже другая история. 28.01.2016

  • 10

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

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

    Другой метод будет полагаться на Word2Vec и Word Mover's 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 a sentence', wv)
    print(sim)
    

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

    23.01.2019

    11

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

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

    18.11.2016

    12

    Если вы не используете Word2Vec, у нас есть другая модель, чтобы найти ее, используя BERT для встраивания. Ниже приведена справочная ссылка https://github.com/UKPLab/sentence-transformers

    pip install -U sentence-transformers
    
    from sentence_transformers import SentenceTransformer
    import scipy.spatial
    
    embedder = SentenceTransformer('bert-base-nli-mean-tokens')
    
    # Corpus with example sentences
    corpus = ['A man is eating a food.',
              'A man is eating a piece of bread.',
              'The girl is carrying a baby.',
              'A man is riding a horse.',
              'A woman is playing violin.',
              'Two men pushed carts through the woods.',
              'A man is riding a white horse on an enclosed ground.',
              'A monkey is playing drums.',
              'A cheetah is running behind its prey.'
              ]
    corpus_embeddings = embedder.encode(corpus)
    
    # Query sentences:
    queries = ['A man is eating pasta.', 'Someone in a gorilla costume is playing a set of drums.', 'A cheetah chases prey on across a field.']
    query_embeddings = embedder.encode(queries)
    
    # Find the closest 5 sentences of the corpus for each query sentence based on cosine similarity
    closest_n = 5
    for query, query_embedding in zip(queries, query_embeddings):
        distances = scipy.spatial.distance.cdist([query_embedding], corpus_embeddings, "cosine")[0]
    
        results = zip(range(len(distances)), distances)
        results = sorted(results, key=lambda x: x[1])
    
        print("\n\n======================\n\n")
        print("Query:", query)
        print("\nTop 5 most similar sentences in corpus:")
    
        for idx, distance in results[0:closest_n]:
            print(corpus[idx].strip(), "(Score: %.4f)" % (1-distance))
    

    Другая ссылка для подписки на https://github.com/hanxiao/bert-as-service

    08.01.2020

    13

    Группа Facebook Research выпустила новое решение под названием InferSent Results, и код опубликован на Github, проверьте их репо. Это довольно круто. Планирую использовать. https://github.com/facebookresearch/InferSent

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

    14.09.2018

    14

    Вы можете просто сложить векторы слов одного предложения вместе. Затем посчитайте косинусное сходство вектора двух предложений как сходство двух предложений. Думаю, это самый простой способ.

    26.10.2020
    Новые материалы

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

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


    Для любых предложений по сайту: [email protected]