Jak obliczyć strukturalne podobieństwo zdań?

12

Pracuję nad problemem, w którym muszę ustalić, czy dwa zdania są podobne, czy nie. Zaimplementowałem rozwiązanie wykorzystujące algorytm BM25 i zestawy słowników do określania podobieństwa składniowego i semantycznego. Rozwiązanie działa poprawnie i nawet jeśli kolejność słów w zdaniach jest pomieszana, to mierzy się, że dwa zdania są podobne. Na przykład

  1. Python to dobry język.
  2. Język to dobry python.

Moim problemem jest ustalenie, czy te dwa zdania są podobne.

  • Jakie może być możliwe rozwiązanie podobieństwa strukturalnego?
  • Jak utrzymam strukturę zdań?
Shubham Tiwari
źródło
Możesz użyć wektorów zdań i porównać je.
Aiden Grossman
Gorąco sugeruję, aby użyć do tego zadania Gensim ( radimrehurek.com/gensim ). Szczególnie modele LSI i / lub word2vec i fasttext
Robin

Odpowiedzi:

2

Najłatwiejszym sposobem dodania pewnego rodzaju podobieństwa strukturalnego jest użycie n-gramów; w twoim przypadku bigramy mogą być wystarczające.

Przejrzyj każde zdanie i zbierz pary słów, takie jak:

  • „python jest”, „to”, „dobry”, „dobry język”.

Twoje drugie zdanie ma

  • „język a”, „dobry”, „dobry python”, „python is”.

Z ośmiu bigramów masz dwa takie same („python jest” i „dobry”), więc można powiedzieć, że podobieństwo strukturalne wynosi 2/8.

Oczywiście możesz być bardziej elastyczny, jeśli wiesz, że dwa słowa są semantycznie powiązane. Jeśli chcesz powiedzieć, że Python jest dobrym językiem jest strukturalnie podobny / identyczny z Javą jest świetnym językiem , możesz dodać to do porównania, aby skutecznie przetwarzać „[PROG_LANG] jest językiem [POSITIVE-ADJ]”, lub coś podobnego.

Oliver Mason
źródło
5

Po pierwsze, zanim zaczniemy, polecam zapoznać się z podobnymi pytaniami w sieci, takimi jak /datascience/25053/best-practical-algorithm-for-sentence-similarity i https: // stackoverflow. com / pytania / 62328 / is-there-an-algorytm-that-tells-the-semantic-podobieństwo-dwóch-fraz

Aby określić podobieństwo zdań, musimy rozważyć, jakie mamy dane. Na przykład, jeśli posiadasz oznaczony zestaw danych, tj. Podobne zdania i zdania niepodobne, wówczas prostym podejściem mogłoby być użycie nadzorowanego algorytmu do klasyfikacji zdań.

Podejściem, które mogłoby określić strukturalne podobieństwo zdań, byłoby uśrednienie wektorów słów generowanych przez algorytmy osadzania słów, tj. Word2vec. Algorytmy te tworzą wektor dla każdego słowa, a podobieństwo cosinusowe reprezentuje podobieństwo semantyczne między słowami. (Daniel L 2017)

Korzystając z wektorów słów, możemy użyć następujących wskaźników do określenia podobieństwa słów.

  • Odległość cosinusowa między osadzaniem słów
  • Euklidesowa odległość między osadzeniami słów

Podobieństwo cosinus jest miarą podobieństwa między dwoma niezerowymi wektorami wewnętrznej przestrzeni produktu, która mierzy cosinus kąta między nimi. Kąt cosinus jest miarą nakładania się zdań pod względem ich zawartości.

Odległość euklidesowa między dwoma wektorami słów zapewnia skuteczną metodę pomiaru podobieństwa językowego lub semantycznego odpowiednich słów. (Frank D 2015)

Alternatywnie można obliczyć wektor własny zdań, aby określić podobieństwo zdań.

Wektory własne to specjalny zestaw wektorów związanych z liniowym układem równań (tj. Równanie macierzowe). Tutaj generowana jest macierz podobieństwa zdań dla każdego skupienia i obliczany jest wektor własny macierzy. Więcej informacji na temat podejścia do rankingu zdań opartego na oprogramowaniu Eigenvector można znaleźć w tym dokumencie https://pdfs.semanticscholar.org/ca73/bbc99be157074d8aad17ca8535e2cd956815.pdf

Dla kodu źródłowego Siraj Rawal ma notatnik w języku Python do tworzenia zestawu wektorów słów. Wektory słów można następnie wykorzystać do znalezienia podobieństwa między wyrazami. Kod źródłowy jest dostępny tutaj https://github.com/llSourcell/word_vectors_game_of_thrones-LIVE

Inną opcją jest samouczek od Oreily, który wykorzystuje bibliotekę gensin Python do określania podobieństwa między dokumentami. Ten samouczek używa NLTK do tokenizacji, a następnie tworzy z korpusu model tf-idf (termin częstotliwość-odwrotna częstotliwość dokumentów). Następnie tf-idf służy do określenia podobieństwa dokumentów. Samouczek jest dostępny tutaj https://www.oreilly.com/learning/how-do-i-compare-document-similarity-using-python

Seth Simba
źródło
Dziękujemy za podanie cennych szczegółów dotyczących problemu. Widziałem przykład gensim, ale mam pytanie, czy będzie w stanie rozwiązać problem, o którym wspominałem. Chociaż rozwiązanie, które stworzyłem, działa dobrze w znajdowaniu podobieństwa między zdaniami, ale utknie, gdy kolejność słów jest pomieszana.
Shubham Tiwari,
4

Najlepsze podejście w tym czasie (2019):

Najbardziej efektywnym podejściem jest teraz użycie Universal Google Sentence Encoder firmy Google ( paper_2018 ), która oblicza podobieństwo semantyczne między zdaniami przy użyciu iloczynu ich osadzania (tj. Wyuczonych wektorów 215 wartości) . Podobieństwo jest liczbą zmiennoprzecinkową między 0 (tj. Bez podobieństwa) a 1 (tj. Silne podobieństwo).

Implementacja jest teraz zintegrowana z Tensorflow Hub i może być łatwo używana. Oto gotowy do użycia kod do obliczenia podobieństwa między dwoma zdaniami. Tutaj uzyskam podobieństwo między „Python jest dobrym językiem” i „Językiem dobrym pythonem”, jak w twoim przykładzie.

Przykład kodu:

#Requirements: Tensorflow>=1.7 tensorflow-hub numpy

import tensorflow as tf
import tensorflow_hub as hub
import numpy as np

module_url = "https://tfhub.dev/google/universal-sentence-encoder-large/3" 
embed = hub.Module(module_url)
sentences = ["Python is a good language","Language a good python is"]

similarity_input_placeholder = tf.placeholder(tf.string, shape=(None))
similarity_sentences_encodings = embed(similarity_input_placeholder)

with tf.Session() as session:
  session.run(tf.global_variables_initializer())
  session.run(tf.tables_initializer())
  sentences_embeddings = session.run(similarity_sentences_encodings, feed_dict={similarity_input_placeholder: sentences})
  similarity = np.inner(sentences_embeddings[0], sentences_embeddings[1])
  print("Similarity is %s" % similarity)

Wynik:

Similarity is 0.90007496 #Strong similarity
HLeb
źródło
Inną opcją w 2019 r. Jest osadzanie zdań BERT - możesz zobaczyć przykładowy kod tutaj - github.com/hanxiao/bert-as-service
Adnan S