【发布时间】:2015-08-14 08:39:02
【问题描述】:
我有一个数据库表中大约一千万个文件的spamsum 复合哈希,我想找到彼此相当相似的文件。 Spamsum 哈希由两个最大 64 字节的 CTPH 哈希组成,如下所示:
384:w2mhnFnJF47jDnunEk3SlbJJ+SGfOypAYJwsn3gdqymefD4kkAGxqCfOTPi0ND:wemfOGxqCfOTPi0ND
它们可以分为三个部分(在冒号上拆分字符串):
- 块大小:
384在上面的哈希中 - 第一个签名:
w2mhnFnJF47jDnunEk3SlbJJ+SGfOypAYJwsn3gdqymefD4kkAGxqCfOTPi0ND - 二次签名:
wemfOGxqCfOTPi0ND
块大小是指第一个签名的块大小,第二个签名的块大小是第一个签名的两倍(这里:384 x 2 = 768)。每个文件都有这些复合哈希之一,这意味着每个文件都有两个具有不同块大小的签名。
只有当它们的块大小对应时,才能比较垃圾邮件签名。也就是说,上面的复合散列可以与任何其他包含块大小为 384 或 768 的签名的复合散列进行比较。对于具有相似块大小的散列,签名字符串的相似性可以作为两者之间相似性的度量。由哈希表示的文件。
如果我们有:
file1.blk2 = 768file1.sig2 = wemfOGxqCfOTPi0NDfile2.blk1 = 768file2.sig1 = LsmfOGxqCfOTPi0ND
我们可以通过计算两个签名的一些加权编辑距离(如 Levenshtein 距离)来了解两个文件的相似程度。这两个文件看起来很相似。
leven_dist(file1.sig2, file2.sig1) = 2
还可以计算两个哈希之间的归一化相似度分数(请参阅详细信息here)。
我想根据这些哈希值找到任何两个相似度超过 70% 的文件,并且我非常喜欢使用可用的软件包(或 API/SDK),尽管我不害怕编写自己的代码解决问题。
我尝试使用 Lucene (4.7.0) 分解散列并对其进行索引,但搜索似乎缓慢而乏味。下面是我尝试过的 Lucene 查询示例(对于每个单一签名——每个哈希两次并使用区分大小写的 KeywordAnalyzer):
(blk1:768 AND sig1:wemfOGxqCfOTPi0ND~0.7) OR (blk2:768 AND sig2:wemfOGxqCfOTPi0ND~0.7)
Lucene 的incredibly fast Levenshtein automata 似乎不接受高于 2 的编辑距离限制(我需要它支持高达 0.7 x 64 ≃ 19),并且它的正常编辑距离算法没有针对长搜索词进行优化(the brute force method used does not cut off calculation once the distance limit is reached .) 也就是说,可能是我的查询没有针对我想做的事情进行优化,所以请不要犹豫,纠正我。
我想知道是否可以使用 Lucene 提供的任何算法来完成我需要的工作,而不是直接计算编辑距离。我听说 BK-trees 是索引此类搜索的最佳方式,但我不知道该算法的可用实现(Lucene 是否使用这些实现?)。我还听说一个可能的解决方案是使用 n-gram 方法缩小搜索列表,但我不确定在包容性和速度方面与编辑距离计算相比如何(我很确定 Lucene 支持那个)。顺便问一下,有没有办法让 Lucene 以并行模式运行术语搜索?
鉴于我仅使用 Lucene 来预匹配哈希值,并且我稍后会使用适当的算法计算真正的相似度得分,因此我只需要一种至少与相似度得分计算中使用的 Levenshtein 距离一样具有包容性的方法 - - 也就是说,我不希望预匹配方法排除会被评分算法标记为匹配的哈希。
感谢任何帮助/理论/参考/代码或线索。
【问题讨论】:
标签: lucene levenshtein-distance fuzzy-search fuzzy-comparison