¿Cómo calculo la similitud estructural entre oraciones?

12

Estoy trabajando en un problema en el que necesito determinar si dos oraciones son similares o no. Implementé una solución usando el algoritmo BM25 y los sintetizadores wordnet para determinar la similitud sintáctica y semántica. La solución está funcionando adecuadamente, e incluso si el orden de las palabras en las oraciones está mezclado, mide que dos oraciones son similares. Por ejemplo

  1. Python es un buen lenguaje.
  2. El lenguaje es un buen pitón.

Mi problema es determinar que estas dos oraciones son similares.

  • ¿Cuál podría ser la posible solución para la similitud estructural?
  • ¿Cómo mantendré la estructura de las oraciones?
Shubham Tiwari
fuente
Es posible que pueda usar vectores de oraciones y compararlos.
Aiden Grossman el
Le recomiendo que use Gensim ( radimrehurek.com/gensim ) para esta tarea. Especialmente los modelos LSI y / o word2vec y fasttext
Robin

Respuestas:

2

La forma más fácil de agregar algún tipo de medida de similitud estructural es usar n-gramos; en su caso, las bigramas pueden ser suficientes.

Revisa cada oración y recoge pares de palabras, como:

  • "python es", "es un", "un buen", "buen lenguaje".

Tu otra oración tiene

  • "lenguaje a", "un buen", "buen python", "python is".

De ocho bigrams tiene dos que son iguales ("python is" y "a good"), por lo que podría decir que la similitud estructural es 2/8.

Por supuesto, también puede ser más flexible si ya sabe que dos palabras están semánticamente relacionadas. Si quiere decir que Python es un buen lenguaje es estructuralmente similar / idéntico a Java es un gran lenguaje , entonces podría agregarlo a la comparación para que procese efectivamente "[PROG_LANG] es un lenguaje [POSITIVE-ADJ]", o algo similar.

Oliver Mason
fuente
5

En primer lugar, antes de comenzar, le recomiendo que consulte preguntas similares en la red, como /datascience/25053/best-practical-algorithm-for-sentence-similarity y https: // stackoverflow. com / preguntas / 62328 / is-there-an-Algoritmo-que-dice-la-semejanza-semántica-de-dos-frases

Para determinar la similitud de las oraciones, debemos considerar qué tipo de datos tenemos. Por ejemplo, si tuviera un conjunto de datos etiquetado, es decir, oraciones similares y oraciones diferentes, entonces un enfoque directo podría haber sido utilizar un algoritmo supervisado para clasificar las oraciones.

Un enfoque que podría determinar la similitud estructural de las oraciones sería promediar los vectores de palabras generados por algoritmos de inclusión de palabras, es decir, word2vec. Estos algoritmos crean un vector para cada palabra y la similitud del coseno entre ellos representa la similitud semántica entre las palabras. (Daniel L 2017)

Usando vectores de palabras podemos usar las siguientes métricas para determinar la similitud de las palabras.

  • Distancia coseno entre las incrustaciones de palabras
  • Distancia euclidiana entre incrustaciones de palabras

La similitud del coseno es una medida de la similitud entre dos vectores distintos de cero de un espacio interno del producto que mide el coseno del ángulo entre ellos. El ángulo del coseno es la medida de superposición entre las oraciones en términos de su contenido.

La distancia euclidiana entre dos vectores de palabras proporciona un método efectivo para medir la similitud lingüística o semántica de las palabras correspondientes. (Frank D 2015)

Alternativamente, puede calcular el vector propio de las oraciones para determinar la similitud de las oraciones.

Los vectores propios son un conjunto especial de vectores asociados con un sistema lineal de ecuaciones (es decir, ecuación matricial). Aquí se genera una matriz de similitud de oración para cada grupo y se calcula el vector propio para la matriz. Puede leer más sobre el enfoque basado en Eigenvector para la clasificación de oraciones en este documento https://pdfs.semanticscholar.org/ca73/bbc99be157074d8aad17ca8535e2cd956815.pdf

Para el código fuente, Siraj Rawal tiene un cuaderno de Python para crear un conjunto de vectores de palabras. Los vectores de palabras se pueden usar para encontrar la similitud entre las palabras. El código fuente está disponible aquí https://github.com/llSourcell/word_vectors_game_of_thrones-LIVE

Otra opción es un tutorial de Oreily que utiliza la biblioteca gensin Python para determinar la similitud entre documentos. Este tutorial utiliza NLTK para simular y luego crea un modelo tf-idf (término frecuencia de documento inverso de frecuencia) a partir del corpus. El tf-idf se usa para determinar la similitud de los documentos. El tutorial está disponible aquí https://www.oreilly.com/learning/how-do-i-compare-document-similarity-using-python

Seth Simba
fuente
Gracias por proporcionar detalles valiosos para el problema. Había visto el ejemplo de gensim pero tengo una pregunta, ¿será capaz de resolver el problema que mencioné en cuestión? Aunque la solución que creé funciona bien para encontrar la similitud entre las oraciones, pero se atasca cuando se mezcla el orden de las palabras.
Shubham Tiwari
4

El mejor enfoque en este momento (2019):

El enfoque más eficiente ahora es usar Universal Sentence Encoder de Google ( paper_2018 ) que calcula la similitud semántica entre oraciones usando el producto de punto de sus incrustaciones (es decir, vectores aprendidos de 215 valores) . La similitud es un número flotante entre 0 (es decir, sin similitud) y 1 (es decir, una gran similitud).

La implementación ahora está integrada en Tensorflow Hub y se puede usar fácilmente. Aquí hay un código listo para usar para calcular la similitud entre 2 oraciones. Aquí obtendré la similitud entre "Python es un buen lenguaje" y "Language a good python is" como en su ejemplo.

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

Salida:

Similarity is 0.90007496 #Strong similarity
HLeb
fuente
Otra opción en 2019 son las incrustaciones de oraciones BERT: puede ver el código de ejemplo aquí: github.com/hanxiao/bert-as-service
Adnan S