[英]SequenceMatcher - finding the two most similar elements of two or more lists of data
我试图将一组字符串与已定义的字符串集进行比较。 例如,您想要找到一个字母的收件人,该文本通过OCR进行数字化。
有一系列地址,以字典为元素。 每个元素都是唯一的,包含ID,名称,街道,邮政编码和城市。 此列表将长达1000个条目。
由于OCR扫描文本可能不准确,我们需要找到包含地址的列表中最匹配的字符串候选项。
该文字长750字。 我们通过使用适当的过滤函数减少单词数量,首先按空格分割,从每个元素中删除更多的空格,删除少于5个字符的所有单词并删除重复项; 结果列表长200字。
由于每个收件人有4个字符串(名称街,邮政编码和城市),剩下的字母长200字,我的比较必须运行4 * 1000 * 200 = 800'000次。
我使用python中等成功。 已正确找到匹配项。 但是,该算法需要很长时间才能处理大量字母(每1500个字母最多50个小时)。 列表理解已被应用。 有没有办法正确(而不是uzelary)实现多线程? 如果此应用程序需要在低规格服务器上运行怎么办? 我的6核CPU并没有抱怨这样的任务,但是,我不知道在一个小型AWS实例上处理大量文档需要多少时间。
>> len(addressees)
1000
>> addressees[0]
{"Name": "John Doe", "Zip": 12345, "Street": "Boulevard of broken dreams 2", "City": "Stockholm"}
>> letter[:5] # already filtered
["Insurance", "Taxation", "Identification", "1592212", "St0ckhlm", "Mozart"]
>> from difflib import SequenceMatcher
>> def get_similarity_per_element(addressees, letter):
"""compare the similarity of each word in the letter with the addressees"""
ratios = []
for l in letter:
for a in addressee.items():
ratios.append(int(100 * SequenceMatcher(None, a, l).ratio())) # using ints for faster arithmatic
return max(ratios)
>> get_similarity_per_element(addressees[0], letter[:5]) # percentage of the most matching word in the letter with anything from the addressee
82
>> # then use this method to find all addressents with the max matching ratio
>> # if only one is greater then the others -> Done
>> # if more then one, but less then 3 are equal -> Interactive Promt -> Done
>> # else -> mark as not sortable -> Done.
我希望每个文档的处理速度更快。 (最多1分钟),而不是每1500字母50小时。 我确信这是瓶颈,因为其他任务工作快速而且完美无缺。
有更好(更快)的方法吗?
您想要识别与字典单词类似的输入,例如“St0ckholm” - >“Stockholm”。 应该处理换位拼写错误。 好。
可能你更喜欢设置autojunk=False
。 但是如果你赶时间的话,二次或三次算法听起来就像麻烦一样。
考虑Anagram问题,在那里你被问到输入词和字典词是否是彼此的字谜。 直接的解决方案是比较排序的字符串是否相等。 让我们看看我们是否可以将这个想法调整为适合您问题的数据结构。
将您的字典单词预处理为易于查找的规范键,并将每个键的一个或多个单词列表挂起。 使用排序来形成密钥。 例如,我们将:
'dgo' -> ['dog', 'god']
按键排序存储此地图。
给定输入词,您想知道词典中是否出现该词,或者词典中是否出现编辑距离有限的版本。 对输入词进行排序并探测第一个大于或等于该条目的地图。 检索(非常短的)候选词列表并评估它们与输入词之间的距离。 输出最佳匹配。 这很快就会发生。
对于模糊匹配,使用第1和第2个条目>=
target,加上前面的条目,因此您有一个更大的候选集。 此外,到目前为止,由于升序排序,这种方法对删除“小”字母(如“a”或“b”)很敏感。 因此,另外形成具有降序排序的键,并探测两种类型键的映射。
如果您愿意使用pip安装包,请考虑import soundex
,它故意丢弃文字中的信息,或import fuzzywuzzy
。
一些快速提示:
1)让我知道做quick_ratio()或real_quick_ratio()而不是ratio()需要多长时间
2)反转循环的顺序并使用set_seq2和set_seq1,以便SequenceMatcher重用信息
for a in addressee.items():
s = SequenceMatcher()
s.set_seq2(a)
for l in letter:
s.set_seq1(l)
ratios.append(int(100 * s.ratio()))
但是更好的解决方案就像@J_H描述的那样
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.