【问题标题】:How to detect that two sentences are similar?如何检测两个句子是否相似?
【发布时间】:2021-05-18 19:34:23
【问题描述】:

我想计算两个任意句子彼此之间的相似程度。例如:

  1. 一位数学家找到了解决问题的方法。
  2. 这个问题由一位年轻的数学家解决了。

我可以使用标注器、词干分析器和解析器,但我不知道如何检测这些句子是否相似。

【问题讨论】:

  • 您是否考虑过在 Linguistics.SE 提出此类问题?我发现 NLP 问题往往在那里得到更好的处理。
  • @tchrist 但它是一个基于编程/算法的问题!

标签: nlp similarity stanford-nlp opennlp


【解决方案1】:

这两个句子不仅相似,而且几乎是paraphrases,即两种表达相同含义的替代方式。这也是一个非常简单的释义案例,其中两个话语都使用相同的词,唯一的例外是一个是主动形式,另一个是被动形式。 (这两个句子并不完全是释义,因为在第二个句子中,数学家是“年轻的”。这些附加信息使两个句子之间的语义关系不对称。在这些情况下,你会说第二个话语"entails"第一个一个,或者换句话说,第一个可以从第二个推断出来)。

从示例中无法了解您是否真的对释义检测、文本蕴涵或一般句子相似性感兴趣,这是一个更广泛和更模糊的问题。例如,“人吃食物”更类似于“人吃面包”还是“男人吃食物”?

释义检测和文本相似性都是自然语言处理中复杂的开放性研究问题,有大量活跃的研究人员社区致力于解决这些问题。目前尚不清楚您对这个主题的兴趣程度如何,但请考虑到尽管许多杰出的研究人员已经花费了整个职业生涯来试图破解它,但我们距离找到普遍适用的合理解决方案还有很长的路要走。

除非您对仅在特定情况下有效且无法捕捉句法交替(如本例)的非常肤浅的解决方案感兴趣,否则我建议您更深入地研究文本相似性问题。一个很好的起点是本书"Foundations of Statistical Natural Language Processing",它对大多数统计自然语言处理主题进行了非常有条理的介绍。一旦你明确了你的要求(例如,你的方法应该在什么条件下工作?你追求什么样的精度/召回水平?你可以安全地忽略什么样的现象,你需要考虑哪些现象?)你可以通过深入研究最近的研究工作开始研究具体方法。在这里,一个很好的起点是online archives of the Association for Computational Linguistics (ACL),它是该领域大多数研究成果的出版商。

只是为了给你一些实用的东西,一个非常粗略的句子相似性基线将是两个二进制向量之间的cosine similarity,将句子表示为词袋。词袋是文本的一种非常简化的表示,通常用于信息检索,其中您完全忽略语法,只将句子表示为一个向量,其大小是词汇表的大小(即语言中的词数) ),如果词汇表中位置“i”的单词出现在句子中,则其分量“i”的值为“1”,否则为“0”。

【讨论】:

  • 但余弦相似度将显示这些句子相同 I drink milk but I dont drink alcohalic drinksI dont drink milk but I drink alcohlic drinks
  • @RavinderPayal,这就是自然语言理解下要解决的问题。
  • @amit_kumar 是的,这个具体问题可以通过动词与名词的映射和分词来解决
  • 不同意。那只是只处理语法的 NLP 和 POS 标记。 NLU 是关于语义和语用学的。 NLU 引擎是最先进的作品,但我们仍然没有可以泛化所有领域的解决方案。
【解决方案2】:

一种更现代的方法(2021 年)是使用机器学习 NLP 模型。有专门针对此任务的预训练模型,其中许多源自BERT,因此您不必训练自己的模型(如果您愿意,可以)。 这是一个代码示例,它使用了优秀的 Huggingface Transformers 库和 PyTorch。它基于this example

from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch

model_name = "bert-base-cased-finetuned-mrpc"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name)

sequence_0 = "A mathematician found a solution to the problem."
sequence_1 = "The problem was solved by a young mathematician."

tokens = tokenizer.encode_plus(sequence_0, sequence_1, return_tensors="pt")
classification_logits = model(**tokens)[0]
results = torch.softmax(classification_logits, dim=1).tolist()[0]

classes = ["not paraphrase", "is paraphrase"]
for i in range(len(classes)):
    print(f"{classes[i]}: {round(results[i] * 100)}%")

【讨论】:

  • 对于两个相同的句子,它仍然会产生差异。例如,sequence_0 =“口服一片” sequence_1 =“口服一片”它给出了 94% 的相似度。为什么?
  • 此外,这种方法也有Ravinder在上面指出的同样的缺点——即它在结构意图方面做得不好,比如“我喜欢馅饼胜过蛋糕”和“我喜欢蛋糕” more than pie" 据说可以相互解释,尽管具有相反的含义。
【解决方案3】:

在某些情况下,可以自动将句子转换为代表其含义的discourse representation structures。如果两个句子产生相同的话语表征结构,那么它们很可能具有相似的含义。

【讨论】:

    猜你喜欢
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-15
    • 1970-01-01
    • 2018-08-12
    • 1970-01-01
    相关资源
    最近更新 更多