如何计算句子之间的结构相似度?

人工智能 自然语言处理 Python 相似
2021-10-23 21:35:10

我正在解决一个问题,我需要确定两个句子是否相似。我使用 BM25 算法和 wordnet synsets 实现了一个解决方案,用于确定句法和语义相似性。该解决方案运行良好,即使句子中的词序混乱,它也在衡量两个句子是否相似。例如

  1. Python 是一门很好的语言。
  2. 语言是一个好的python。

我的问题是确定这两个句子是相似的。

  • 结构相似性的可能解决方案是什么?
  • 我将如何维护句子的结构?
3个回答

首先,在我们开始之前,我建议您参考网络上的类似问题,例如https://datascience.stackexchange.com/questions/25053/best-practical-algorithm-for-sentence-similarityhttps://stackoverflow。 com/questions/62328/is-there-an-algorithm-that-tells-the-semantic-similarity-of-two-phrases

为了确定句子的相似性,我们需要考虑我们拥有什么样的数据。例如,如果您有一个标记数据集,即相似句子和不同句子,那么直接的方法可能是使用监督算法对句子进行分类。

一种可以确定句子结构相似性的方法是对由词嵌入算法(即 word2vec)生成的词向量进行平均。这些算法为每个单词创建一个向量,它们之间的余弦相似度表示单词之间的语义相似度。(丹尼尔 L 2017)

使用词向量,我们可以使用以下指标来确定词的相似度。

  • 词的词嵌入之间的余弦距离
  • 词的词嵌入之间的欧几里得距离

余弦相似度是衡量内积空间的两个非零向量之间的相似度的度量,该内积空间衡量它们之间夹角的余弦值。余弦角是句子之间在内容方面重叠的度量。

两个词向量之间的欧几里得距离为衡量对应词的语言或语义相似度提供了一种有效的方法。(弗兰克 D 2015)

或者,您可以计算句子的特征向量以确定句子相似度。

特征向量是与线性方程组(即矩阵方程)相关的一组特殊向量。这里为每个聚类生成一个句子相似度矩阵,并计算该矩阵的特征向量。您可以在本文https://pdfs.semanticscholar.org/ca73/bbc99be157074d8aad17ca8535e2cd956815.pdf上阅读更多关于基于特征向量的句子排名方法

对于源代码 Siraj Rawal 有一个 Python notebook 来创建一组词向量。然后可以使用单词向量来查找单词之间的相似性。源代码可在此处获得https://github.com/llSourcell/word_vectors_game_of_thrones-LIVE

另一种选择是 Oreily 的教程,它利用 gensin Python 库来确定文档之间的相似性。本教程使用 NLTK 进行标记,然后从语料库中创建一个 tf-idf(词频-逆文档频率)模型。然后使用 tf-idf 来确定文档的相似性。该教程可在此处获得https://www.oreilly.com/learning/how-do-i-compare-document-similarity-using-python

目前最好的方法(2019):

现在最有效的方法是使用Google 的 Universal Sentence Encoder ( paper_2018 ),它使用它们嵌入的点积(即 215 个值的学习向量)来计算句子之间的语义相似度相似度是介于 0 (即无相似性)和 1 (即强相似性)之间的浮点数。

该实现现已集成到 Tensorflow Hub 并且可以轻松使用。这是一个即用型代码,用于计算 2 个句子之间的相似度。在这里,我将在您的示例中获得“Python 是一种好语言”“一种好的 Python 语言是”之间的相似性

代码示例:

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

输出:

Similarity is 0.90007496 #Strong similarity

添加某种结构相似性度量的最简单方法是使用 n-gram;在您的情况下,二元组可能就足够了。

浏览每个句子并收集成对的单词,例如:

  • “python is”、“is a”、“a good”、“good language”。

你的另一句话有

  • “语言a”、“a 好”、“python 好”、“python 是”。

在八个二元组中有两个是相同的(“python is”和“a good”),所以你可以说结构相似性是 2/8。

当然,如果您已经知道两个词在语义上相关,您也可以更加灵活。如果您想说Python 是一门好语言,在结构上与Java 是一门好语言相似/相同,那么您可以将其添加到比较中,以便您有效地处理“[PROG_LANG] 是一种 [POSITIVE-ADJ] 语言”,或类似的东西。