模糊字符串比较

我正在努力完成的是一个程序,在一个文件阅读,并将比较每个句子根据原来的句子。与原句完全匹配的句子将得到1分,与原句完全相反的句子将得到0分。所有其他模糊的句子将获得1到0之间的分数。

我不确定要使用哪个操作才能在 Python3中完成这项工作。

我已经包含了示例文本,其中 Text 1是原始文本,其他前面的字符串是比较文本。

文本: 样本

短信1: 那是一个黑暗而狂风暴雨的夜晚。我独自一人坐在红色的椅子上。我并不是完全一个人,因为我有三只猫。

短信20: 那是一个阴暗的暴风雨之夜。我独自一人坐在深红色的椅子上。我并不是完全一个人,因为我有三只猫 //应该得高分,但不是1分

短信21: 那是一个阴暗而狂暴的夜晚。我独自一人坐在深红色的教堂上。我并不是完全一个人,因为我有三只猫 //应该得分低于文本20

短信22: 我独自一人坐在深红色的教堂上。我并不是完全一个人,因为我有三只猫。那是一个阴暗而狂暴的夜晚。 //应该得分低于文本21,但不是0

短信24: 那是一个黑暗而狂风暴雨的夜晚。我不是一个人。我没有坐在红色的椅子上。我养了三只猫。 应该得0分!

99454 次浏览

在标准库中有一个模块(称为 difflib) ,它可以比较字符串并根据它们的相似性返回一个分数。SequenceMatcher类应该能够满足您的需要。

Python 提示中的一个小例子:

>>> from difflib import SequenceMatcher as SM
>>> s1 = ' It was a dark and stormy night. I was all alone sitting on a red chair. I was not completely alone as I had three cats.'
>>> s2 = ' It was a murky and stormy night. I was all alone sitting on a crimson chair. I was not completely alone as I had three felines.'
>>> SM(None, s1, s2).ratio()
0.9112903225806451

有一个称为 fuzzywuzzy的软件包。通过 pip 安装:

pip install fuzzywuzzy

简单用法:

>>> from fuzzywuzzy import fuzz
>>> fuzz.ratio("this is a test", "this is a test!")
96

该软件包构建在 difflib之上。你会问,为什么不利用这一点呢?除了比较简单之外,它还有许多不同的匹配方法(比如令牌顺序不敏感,部分字符串匹配) ,这使得它在实践中更加强大。process.extract函数特别有用: 从集合中找到最匹配的字符串和比率。来自他们的自述:

部分比率

>>> fuzz.partial_ratio("this is a test", "this is a test!")
100

令牌排序比率

>>> fuzz.ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
90
>>> fuzz.token_sort_ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
100

令牌组合比率

>>> fuzz.token_sort_ratio("fuzzy was a bear", "fuzzy fuzzy was a bear")
84
>>> fuzz.token_set_ratio("fuzzy was a bear", "fuzzy fuzzy was a bear")
100

过程

>>> choices = ["Atlanta Falcons", "New York Jets", "New York Giants", "Dallas Cowboys"]
>>> process.extract("new york jets", choices, limit=2)
[('New York Jets', 100), ('New York Giants', 78)]
>>> process.extractOne("cowboys", choices)
("Dallas Cowboys", 90)

在索引和搜索方面,fuzzyset fuzzywuzzy(difflib)快得多。

from fuzzyset import FuzzySet
corpus = """It was a murky and stormy night. I was all alone sitting on a crimson chair. I was not completely alone as I had three felines
It was a murky and tempestuous night. I was all alone sitting on a crimson cathedra. I was not completely alone as I had three felines
I was all alone sitting on a crimson cathedra. I was not completely alone as I had three felines. It was a murky and tempestuous night.
It was a dark and stormy night. I was not alone. I was not sitting on a red chair. I had three cats."""
corpus = [line.lstrip() for line in corpus.split("\n")]
fs = FuzzySet(corpus)
query = "It was a dark and stormy night. I was all alone sitting on a red chair. I was not completely alone as I had three cats."
fs.get(query)
# [(0.873015873015873, 'It was a murky and stormy night. I was all alone sitting on a crimson chair. I was not completely alone as I had three felines')]

警告: 小心不要混合 unicodebytes在您的模糊集。

这项任务被称为 释义识别,是自然语言处理领域的一个活跃的研究领域。我已经链接了几篇最先进的论文,其中很多都可以在 GitHub 上找到开源代码。

请注意,所有回答的问题都假设两个句子之间有一些字符串/表面的相似性,而实际上两个字符串相似性很小的句子在语义上是相似的。

如果您对这种相似性感兴趣,可以使用 跳过-想法。 根据 GitHub 指南安装软件,然后转到自述文件中的释义检测部分:

import skipthoughts
model = skipthoughts.load_model()
vectors = skipthoughts.encode(model, X_sentences)

这将把你的句子(X _ 句子)转换成向量,然后你可以通过以下方法找到两个向量的相似性:

similarity = 1 - scipy.spatial.distance.cosine(vectors[0], vectors[1])

我们假设向量[0]和向量 1是 X _ 句子[0]和 X _ 句子 1的对应向量你想找到它们的分数。

还有其他的模型可以将一个句子转换成向量,你可以找到 给你

一旦你把句子转换成向量,相似性就只是找到这些向量之间的余弦距离。

2020年更新 Google 基于一个叫做 Tensorflow 的深度学习框架发布了一个叫做 BERT的新模型。还有一个实现,许多人发现更容易使用称为 变形金刚。这些程序所做的是,它们接受两个短语或句子,并且它们能够被训练说出这两个短语或句子是否相同。为了训练它们,你需要一些带有标签1或0的句子(如果它们有相同的意思或者没有)。您使用您的训练数据(已经标记的数据)训练这些模型,然后您将能够使用训练的模型来预测一对新的短语/句子。您可以在相应的 github 页面或许多其他地方(比如 这个)找到如何训练(他们称之为微调)这些模型。

此外,还有一种被称为 MRPC (微软释义识别语料库)的英文培训数据。请注意,BERT 也存在多语言或特定语言版本,因此该模型也可以在其他语言中进行扩展(例如,经过训练的)。

还有一个由 MIT 授权的快速而准确的模糊比较库: Https://github.com/maxbachmann/rapidfuzz