我有一个包含 350,000
字符串的数据库,平均长度约为 500
。字符串不是由单词组成,它们基本上是字符的随机组合。
我需要确保没有两个字符串过于相似,相似度定义为编辑距离除以字符串的平均长度。划分是因为较小的编辑距离更适合较小的字符串。 如果出于性能原因使用不同的指标,这很好,但编辑距离是首选的基线指标。
天真地,我们计算edit distance使用运行时 O(a*b)
,其中 a,b
是两个字符串的长度。我们对所有 n^2
对执行此操作,这给出了 O(n^2*a*b)
的总体运行时间,对于 n= 显然太大了350,000,a,b=500
。
数据库采用从 csv 文件读取的 Python 列表形式。如果可能的话,我想以 Pythonic 的方式处理它。
如何加快速度?我不确定朴素算法需要多长时间才能完成(大约数周),但理想情况下运行时间应该少于一天。
最佳答案
我用 python 编写了一个简单的局部敏感哈希算法的非常简短的原型(prototype)。然而,有一些注意事项,您可能还想优化一些部分。当我们看到它们时,我会提到它们。
假设所有字符串都存储在 strings
中。
import random
from collections import Counter
MAX_LENGTH = 500
SAMPLING_LENGTH = 10
def bit_sampling(string, indices):
return ''.join([string[i] if i<len(string) else ' ' for i in indices])
indices = random.sample(range(MAX_LENGTH),SAMPLING_LENGTH)
hashes = [bit_sampling(string, indices) for string in strings]
counter = Counter(hashes)
most_common, count = counter.most_common()[0]
while count > 1:
dup_indices = [i for i, x in enumerate(hashes) if x == most_common]
# You can use dup_indices to check the edit distance for original groups here.
counter.pop(most_common)
most_common, count = counter.most_common()[0]
首先,这是比特采样的一个微小变体,最适合一般的汉明距离。理想情况下,如果所有字符串的长度都相同,这可以给出汉明距离的理论概率界限。当两个字符串之间的汉明距离很小时,它们不太可能有不同的哈希值。这可以通过参数 SAMPLING_LENGTH
指定。较大的 SAMPLING_LENGTH
将更有可能将相似的字符串散列为不同的散列,但也会降低将不太相似的字符串散列为相同散列的可能性。对于汉明距离,您可以轻松计算出这种权衡。
多次运行此代码段可以增加您对没有相似字符串的信心,因为每次您都会在不同的地方采样。
为了满足您比较不同长度字符串的目的,一种可能的方法是在较短的字符串上留出填充空间并复制它们。
虽然此代码段中的所有操作都是线性的 (O(n)),但它仍可能消耗大量内存和运行时间,并且有可能减少常数因子。
您可能还想考虑使用更复杂的局部敏感哈希算法,例如此处调查:https://arxiv.org/pdf/1408.2927.pdf
关于python - 快速检查大型数据库的编辑距离相似性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48819439/