我想计算两个任意句子彼此之间的相似程度。例如:
- 数学家找到了解决问题的方法。
- 这个问题是由一位年轻的数学家解决的。
醇>
我可以使用标记器,词干分析器和解析器,但我不知道如何检测这些句子是否相似。
答案 0 :(得分:30)
这两个句子不仅相似,它们几乎是paraphrases,即两种表达相同含义的替代方式。这也是一个非常简单的释义案例,其中两个话语都使用相同的词语,唯一的例外是一个词语处于活动状态,而另一个词语是被动的。 (这两个句子并不完全是释义,因为在第二句中,数学家是“年轻的”。这些附加信息使得两个句子之间的语义关系不对称。在这些情况下,你会说第二句话"entails"第一个,或换句话说第一个可以从第二个推断出来。)
从这个例子来看,无法理解你是否真的对释义检测,文本蕴涵或句子相似性感兴趣,这是一个更广泛和更模糊的问题。例如,“人们吃的食物”更类似于“人们吃面包”还是“男人吃的食物”?
自然语言处理中的释义检测和文本相似性都是复杂的,开放的研究问题,有大量活跃的研究人员在研究它们。目前尚不清楚您对这一主题的兴趣程度如何,但考虑到尽管许多优秀的研究人员花费并花费了他们的整个职业生涯来试图破解它,但我们仍然远远没有找到一般工作的合理解决方案。
除非你对一个非常肤浅的解决方案感兴趣,这个解决方案只适用于特定情况并且不能捕获语法交替(如本例所示),我建议你更深入地研究文本相似性的问题。一个很好的出发点是书"Foundations of Statistical Natural Language Processing",它提供了大多数统计自然语言处理主题的组织良好的表达。一旦你明确了你的要求(例如,你的方法应该在什么条件下工作?你经历了什么级别的精确/召回?你可以安全地忽略什么样的现象,以及你需要考虑哪些?)你可以通过深入研究最近的研究工作,开始研究具体方法。在这里,一个好的起点是online archives of the Association for Computational Linguistics (ACL),它是该领域大多数研究成果的出版商。
为了给你一些实用的东西,句子相似性的一个非常粗略的基线将是两个二进制向量之间的cosine similarity,表示句子作为词袋。一个单词是一个非常简化的文本表示,通常用于信息检索,在这种情况下,你完全忽略语法,只将一个句子表示为一个矢量,其大小是词汇量的大小(即语言中的单词数量)如果词汇中位置“i”的单词出现在句子中,则其组成部分“i”的值为“1”,否则为“0”。
答案 1 :(得分:1)
在某些情况下,可以自动将句子转换为代表其含义的discourse representation structures。如果两个句子产生相同的话语表达结构,那么它们可能具有相似的含义。
答案 2 :(得分:0)
我不完全确定你的问题是什么,但你可以使用Levenshtein Edit Distance alghoritm来计算符号序列(在这种情况下是单词)的相似性
答案 3 :(得分:0)
更现代的方法(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)}%")