繁体   English   中英

SequenceMatcher - 查找两个或多个数据列表中两个最相似的元素

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM