我想计算两个任意句子彼此的相似程度。例如:
- 一位数学家找到了解决这个问题的方法。
- 这个问题被一位年轻的数学家解决了。
我可以使用标注器、词干分析器和解析器,但我不知道如何检测这些句子是否相似。
我想计算两个任意句子彼此的相似程度。例如:
- 一位数学家找到了解决这个问题的方法。
- 这个问题被一位年轻的数学家解决了。
我可以使用标注器、词干分析器和解析器,但我不知道如何检测这些句子是否相似。
这两个句子不仅相似,而且几乎是释义,即表达相同含义的两种替代方式。这也是一个非常简单的释义案例,其中两个话语都使用相同的词,唯一的例外是一个是主动形式,另一个是被动形式。(这两个句子并不完全是释义,因为在第二个句子中,数学家是“年轻的”。这些附加信息使两个句子之间的语义关系不对称。在这些情况下,您会说第二个话语“包含”第一个一个,或者换句话说,第一个可以从第二个推断出来)。
从这个例子中,你无法理解你是否真的对释义检测、文本蕴涵或句子相似性感兴趣,这是一个更广泛、更模糊的问题。例如,“人吃食物”更类似于“人吃面包”还是“男人吃食物”?
释义检测和文本相似性都是自然语言处理中复杂的、开放的研究问题,有一个庞大而活跃的研究人员社区致力于这些问题。目前尚不清楚您对这个主题的兴趣程度如何,但请考虑到尽管许多杰出的研究人员已经花费了整个职业生涯来试图破解它,但我们距离找到普遍适用的合理解决方案还有很长的路要走。
除非您对仅在特定情况下有效且无法捕获句法交替(如本例中)的非常肤浅的解决方案感兴趣,否则我建议您更深入地研究文本相似性问题。一个很好的起点是“统计自然语言处理基础”一书,它对大多数统计自然语言处理主题进行了非常有条理的介绍。一旦你明确了你的要求(例如,你的方法应该在什么条件下工作?你追求什么样的精度/召回水平?你可以安全地忽略什么样的现象,你需要考虑哪些现象?)你可以通过深入研究最近的研究工作开始研究具体方法。在这里,一个很好的起点将是计算语言学协会 (ACL) 的在线档案,该协会是该领域大多数研究成果的出版商。
只是为了给你一些实用的东西,一个非常粗略的句子相似度基线是两个二进制向量之间的余弦相似度,将句子表示为词袋。一袋词是文本的一种非常简化的表示,常用于信息检索,其中你完全不考虑语法,只将一个句子表示为一个向量,其大小是词汇量的大小(即语言中的词数) 并且如果词汇表中位置“i”的单词出现在句子中,则其分量“i”的值为“1”,否则为“0”。
一种更现代的方法(2021 年)是使用机器学习 NLP 模型。有专门针对此任务的预训练模型,其中许多是从BERT派生的,因此您不必训练自己的模型(如果您愿意,可以)。这是一个使用 PyTorch 的优秀Huggingface Transformers库的代码示例。它基于这个例子:
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)}%")
在某些情况下,可以自动将句子转换为表达其含义的话语表示结构。如果两个句子产生相同的话语表征结构,那么它们很可能具有相似的含义。