如何检测两个句子是否相似?

Sah*_*oft 22 nlp similarity stanford-nlp opennlp

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

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

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

mas*_*iga 30

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

从这个例子中,不可能理解你是否真的对释义检测,文本蕴涵或句子相似性感兴趣,这是一个更广泛和更模糊的问题.例如,"人们吃的食物"更类似于"人们吃面包"还是"男人吃的食物"?

释义检测和文本相似性都是自然语言处理中的复杂,开放的研究问题,有大量活跃的研究人员社区.目前尚不清楚您对这一主题的兴趣程度如何,但考虑到尽管许多优秀的研究人员花费并花费了他们的整个职业生涯来试图破解它,但我们仍然远远没有找到一般工作的合理解决方案.

除非你对一个非常肤浅的解决方案感兴趣,这个解决方案只适用于特定情况并且不能捕获语法交替(如本例所示),我建议你更深入地研究文本相似性的问题.一个很好的起点是"统计自然语言处理基础"一书,它提供了大多数统计自然语言处理主题的组织良好的表述.一旦你明确了你的要求(例如,你的方法应该在什么条件下起作用?你追求什么级别的精确度/召回?你可以安全地忽略什么样的现象,以及你需要考虑哪些?)你可以通过深入研究最近的研究工作,开始研究具体方法.在这里,一个好的起点是计算语言学协会(ACL)在线档案,该协会是该领域大多数研究成果的出版商.

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

  • 但余弦相似会显示这些句子"我喝牛奶,但我不喝酒精饮料"和"我不喝牛奶,但我喝酒精饮料"! (2认同)

Tza*_*ach 6

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

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)}%")
Run Code Online (Sandbox Code Playgroud)