Como computo a semelhança estrutural entre sentenças?

12

Estou trabalhando em um problema em que preciso determinar se duas frases são semelhantes ou não. Eu implementei uma solução usando o algoritmo BM25 e os synsets do wordnet para determinar a similaridade sintática e semântica. A solução está funcionando adequadamente e, mesmo que a ordem das palavras nas frases seja confusa, está medindo que duas frases são semelhantes. Por exemplo

  1. Python é uma boa linguagem.
  2. Linguagem é um bom python.

Meu problema é determinar que essas duas frases são semelhantes.

  • Qual poderia ser a solução possível para a similaridade estrutural?
  • Como vou manter a estrutura das frases?
Shubham Tiwari
fonte
Você pode usar vetores de frases e compará-los.
Aiden Grossman
Eu sugiro que você use o Gensim ( radimrehurek.com/gensim ) para esta tarefa. Especialmente os modelos LSI e / ou word2vec e fasttext
Robin

Respostas:

2

A maneira mais fácil de adicionar algum tipo de medida de similaridade estrutural é usar n-gramas; no seu caso, os bigrams podem ser suficientes.

Percorra cada frase e colete pares de palavras, como:

  • "python é", "é um", "um bom", "bom idioma".

Sua outra frase tem

  • "idioma a", "um bom", "bom python", "python é".

Dos oito bigrams, você tem dois iguais ("python é" e "um bom"); portanto, você pode dizer que a semelhança estrutural é 2/8.

Claro que você também pode ser mais flexível se já souber que duas palavras estão relacionadas semanticamente. Se você quiser dizer que Python é uma boa linguagem, é estruturalmente semelhante / idêntico a Java é uma ótima linguagem , adicione-a à comparação para processar efetivamente "[PROG_LANG] é uma linguagem [POSITIVE-ADJ]", ou algo semelhante.

Oliver Mason
fonte
5

Antes de começar, recomendo que você consulte perguntas semelhantes na rede, como /datascience/25053/best-practical-algorithm-for-sentence-similarity e https: // stackoverflow. com / questions / 62328 / existe um algoritmo que diz a semelhança semântica de duas frases

Para determinar a semelhança das sentenças, precisamos considerar que tipo de dados temos. Por exemplo, se você tivesse um conjunto de dados rotulado, isto é, sentenças semelhantes e sentenças diferentes, uma abordagem direta poderia ser usar um algoritmo supervisionado para classificar as sentenças.

Uma abordagem que poderia determinar a similaridade estrutural das sentenças seria calcular a média dos vetores de palavras gerados pelos algoritmos de incorporação de palavras, ou seja, word2vec. Esses algoritmos criam um vetor para cada palavra e a semelhança de cosseno entre elas representa semelhança semântica entre as palavras. (Daniel L 2017)

Usando vetores de palavras, podemos usar as seguintes métricas para determinar a similaridade das palavras.

  • Distância cosseno entre incorporação de palavras das palavras
  • Distância euclidiana entre incorporação de palavras das palavras

A similaridade de cosseno é uma medida da semelhança entre dois vetores diferentes de zero de um espaço interno do produto que mede o cosseno do ângulo entre eles. O ângulo do cosseno é a medida de sobreposição entre as sentenças em termos de seu conteúdo.

A distância euclidiana entre dois vetores de palavras fornece um método eficaz para medir a similaridade linguística ou semântica das palavras correspondentes. (Frank D 2015)

Como alternativa, você pode calcular o vetor próprio das frases para determinar a similaridade das frases.

Os autovetores são um conjunto especial de vetores associados a um sistema linear de equações (isto é, equação da matriz). Aqui, uma matriz de similaridade de sentenças é gerada para cada cluster e o vetor próprio da matriz é calculado. Você pode ler mais sobre a abordagem baseada no Eigenvector para a classificação de frases neste artigo https://pdfs.semanticscholar.org/ca73/bbc99be157074d8aad17ca8535e2cd956815.pdf

Para o código fonte, Siraj Rawal possui um bloco de notas Python para criar um conjunto de vetores de palavras. Os vetores de palavras podem ser usados ​​para encontrar a semelhança entre as palavras. O código fonte está disponível aqui https://github.com/llSourcell/word_vectors_game_of_thrones-LIVE

Outra opção é um tutorial da Oreily que utiliza a biblioteca gensin Python para determinar a semelhança entre os documentos. Este tutorial usa o NLTK para tokenizar e, em seguida, cria um modelo tf-idf (termo frequência de documento inverso de frequência) do corpus. O tf-idf é então usado para determinar a semelhança dos documentos. O tutorial está disponível aqui https://www.oreilly.com/learning/how-do-i-compare-document-similarity-using-python

Seth Simba
fonte
Obrigado por fornecer detalhes valiosos para o problema. Eu já tinha visto o exemplo do gensim, mas tenho uma dúvida: será capaz de resolver o problema que mencionei em questão. Embora a solução que eu criei esteja funcionando bem em encontrar a semelhança entre as frases, ela fica presa quando a ordem das palavras é confusa.
Shubham Tiwari
4

A melhor abordagem no momento (2019):

A abordagem mais eficiente agora é usar o Universal Sentença Encoder do Google ( paper_2018 ), que calcula a similaridade semântica entre as frases usando o produto escalar de suas incorporações (ou seja, vetores aprendidos de 215 valores) . A similaridade é um número flutuante entre 0 (ou seja, sem similaridade) e 1 (ou seja, forte similaridade).

A implementação agora está integrada ao Tensorflow Hub e pode ser facilmente usada. Aqui está um código pronto para usar para calcular a semelhança entre duas frases. Aqui vou obter a semelhança entre "Python é uma boa linguagem" e "Linguagem é uma boa python" como no seu exemplo.

Exemplo de código:

#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)

Resultado:

Similarity is 0.90007496 #Strong similarity
HLeb
fonte
Outra opção em 2019 é a incorporação de frases do BERT - você pode ver o código de exemplo aqui - github.com/hanxiao/bert-as-service
Adnan S