预选择近似字符串匹配的概率

Preselection of probability for approximate string matching

本文关键字:串匹配 概率 字符串 字符 选择      更新时间:2023-10-16

我最近的任务是开发一种算法,用于检查数据库中的重复客户记录。DB布局非常简单:数以万计的行包含FullName、Street、City、ZIP、Phone等字段…

先介绍一下背景:

我对算法做了一些广泛的研究,并决定每个领域都应该以一定的数量进行权衡使用不同的算法,因为并非所有算法在所有情况下都表现得同样好。例如,LastName的权重因子为0.50。当我评估时,我会选择使用哪些算法,以及它们对最终决策的影响:
系数0.25:JaroWinkler
系数0.60:余弦2-克相似性
系数0.15:DamerauLevenstein

一切都很好,经过一点调整,我检测到了积极的一面,几乎没有错误。到目前为止还不错。然而,正如你所能想象的,当处理成千上万的记录时,运行时间为O(n^2)——或者实际上是E形式的i=0到i=n——并不是很有效。不用说,积极优化,使用编译器优化速度、多线程等,只是权宜之计,因为真正的问题是复杂性。

从本质上讲,我正在寻找一种预过滤潜在匹配的方法,现在已经对此进行了三天的研究。我发现了一些关于R-树、R*-树、KD树、欧氏向量、minhashing等的有价值的信息。然而,关于所有这些的大多数信息都是高度学术性的。我发现的最有价值的资源是"挖掘海量数据集",第3章。

现在来谈谈我真正的问题:

我已经阅读了所有这些信息,但我不知道如何把它们放在一起。

我在考虑在树或图数据结构中进行某种索引,在这种索引中,我可以输入一个字符串,然后说"找到所有匹配概率>0.20的字符串"。这个算法应该非常快。然后,当我得到一个潜在(>0.20)匹配的列表时,我可以用我的"昂贵"但有选择性的算法来比较这几个项目。我相信,这应该会将运行时间缩短到一个非常合理的值。

我一直在努力寻找某种参考代码来做我上面想做的事情,但除了学术文章,我似乎什么都没想到。我确实找到了"simstring",它实际上是经过编译的,但似乎与7条测试记录不太匹配。。有人能给我指正确的方向吗?肯定有人以前遇到过这种情况,并找到了解决方案。。。

提前非常感谢!

附言:我是用C++做这件事的,但用C#/C/Java/PHP做任何示例都可以。

作为第一步,我只需选择那些足够接近相同长度的字符串,它们可以在给定的概率内匹配。这不是很有选择性的,但(除非指定非常宽松的公差)可能会很快消除很大比例的不可能匹配。(例如,使用像Levenstein这样的编辑度量,将插入计数为1次操作,如果您从长度为5的字符串开始,并且需要在5次操作内匹配,那么您可以消除所有长度超过10的字符串,而无需进一步检查)。

这是否具有足够的选择性,可以直接进行昂贵的比较,这是一个悬而未决的问题——显然,这将取决于你匹配的字符串长度的可变性。

我终于通过以下操作成功地实现了预选:1.使用客户记录的某些字段构建2Grams2.将具有6个Minhash函数家族的2Grams转换为192位签名3.使用boost::geometry库的rtree实现在签名上创建6维空间索引4.为我正在比较的记录选择最接近的k条(在我的情况下为30条)记录,并对这些候选者进行原始的"昂贵"比较5.这将复杂性从E(i,i=n,i=1)降低到大约30n+m,其中m是建立索引所需的时间(令人惊讶的是,几乎可以忽略不计)。

我现在可以在60秒内以高精度运行15000次比较,这是在单线程测试中完成的。多线程到4或8核,这将运行得更快。