这个问题被称为集群,是更大的重复数据删除问题的一部分(你可以决定集群的哪个成员是“正确的”),也称为merge-purge。
我曾经读过一些关于这个主题的研究论文(名字在下面),基本上,作者在一个排序的字符串列表上使用了一个有限大小的滑动窗口。他们只会比较(使用编辑距离算法)窗口内的N*N 个字符串,从而降低计算复杂度。如果任何两个字符串看起来相似,则将它们组合成一个簇(通过将一条记录插入一个单独的簇表中)。
第一次遍历列表之后是第二次遍历,其中字符串在排序之前被反转。这样,具有不同头的琴弦就有另一个机会接近到足以作为同一窗口的一部分进行评估。在第二遍中,如果一个字符串看起来与窗口中的两个(或更多)字符串足够接近,并且这些字符串已经是它们自己的集群的一部分(由第一遍找到),那么这两个集群将被合并(通过更新集群表),当前字符串将被添加到新合并的集群中。这种聚类方法称为联合查找算法。
然后,他们通过将窗口替换为前 X 个基本独特的原型列表来改进算法。每个新字符串都将与前 X 个原型中的每一个进行比较。如果 string 看起来足够接近原型之一,那么它将被添加到原型的 cluster中。如果没有一个原型看起来足够相似,则该字符串将成为一个新原型,将最旧的原型从顶部 X 列表中推出。(采用启发式逻辑来决定原型集群中的哪些字符串应该用作代表整个集群的新原型)。同样,如果字符串看起来与几个原型相似,则它们的所有集群都将被合并。
我曾经实现过这个算法用于名称/地址记录的重复数据删除,列表的大小约为 10-50 百万条记录,它运行得非常快(并且也很好地发现了重复项)。
总体而言,对于此类问题,最棘手的部分当然是找到相似阈值的正确值。这个想法是捕获所有不产生太多误报的重复数据。具有不同特征的数据往往需要不同的阈值。编辑距离算法的选择也很重要,因为一些算法更适合 OCR 错误,而另一些更适合拼写错误,而另一些则更适合语音错误(例如通过电话获取姓名时)。
一旦实现了聚类算法,测试它的一个好方法是获取一个唯一样本列表并人为地变异每个样本以产生其变化,同时保留所有变化都来自同一个父节点的事实。然后将该列表打乱并馈送到算法。将原始聚类与重复数据删除算法产生的聚类进行比较将为您提供效率分数。
参考书目:
Hernandez M. 1995,大型数据库的合并/清除问题。
Monge A. 1997,一种用于检测近似重复数据库记录的有效领域无关算法。