快速且可扩展的相似性检测

时间:2012-12-04 11:13:14

标签: data-mining inverted-index minhash

我有大的postgresql数据库,包含文件。每个文档表示为表中的一行。当新文档添加到数据库时,我需要检查重复项。但我不能只使用select来找到完全匹配。两个文档可能略有不同,仍然可以视为重复文件,例如,如果某些次要字段不同而所有其他字段相同。

我研究这个问题并找到解决这个问题的方法。可以为每个文档计算MinHash签名并构造反向索引,以查询数据库中的类似文档。但我无法理解如何将MinHash映射到关系数据库。

据我所知,MinHash签名是N个哈希的列表,其中N是多个属性。相似度计算如下:

# Given 2 signatures Sa and Sb containing N hashes.
# Calculate number of equal hashes Neq.
number_of_equal_hashes = 0
for ix in range(0, N):
    if Sa[ix] == Sb[ix]:
        number_of_equal_hashes += 1
similarity = float(number_of_equal_hashes)/N

如果您已经有两个签名,这很简单,问题是在数据库中找到相似度小于或等于某个值的所有文档(带有相应的签名)。

例如,我可以创建包含多个列的表,如下所示:

| minhash0 | minhash1 | minhash3 | docid |

每个minhashX列对应于文档属性之一的minhash,docid是文档的标识符。 我可以这样查询类似的记录:

select * from invidx
where ((case when minhash0=minhash2search0 then 1 else 0 end) +
       (case when minhash1=minhash2search1 then 1 else 0 end) +
       (case when minhash2=minhash2search2 then 1 else 0 end))/N > THRESHOLD

其中minhash2searchX是新文档的最小值,而THRESHOLD是最小的相似度。但这种方法需要全面扫描。有加速算法的方法吗?

2 个答案:

答案 0 :(得分:2)

为了利用倒排索引的使用优势,我建议您使用全文搜索引擎,例如: LuceneSolr(基于Lucene)

您可以构建“文档”(根据Lucene),其中包含与文档的MinHashes相关联的字段(db记录)。请注意,您也可以索引数字字段(您只需要在方案中描述字段类型)。此外,您必须存储每个文档的主键,以将Lucene“文档”映射到数据库中的记录。

索引整个文档集。

要查找与给定文档类似的文档 - 您必须为每个字段计算MinHashes,并为query文档计算similar Lucene:

field1:MinHash1 OR field2:MinHash2 OR ...

随着更多字段与文​​档匹配 - 它具有更高的排名。因此,您可以选择排名最高的文档,并做出决定 - 如果它们在您的情况下非常相似

此外,boosting字段可能对您有用

答案 1 :(得分:1)

您的哈希表应包含两列:

| minhash | docid |

应该在minhash上建立索引。

当新文档到达时,您依次搜索其每个散列,查询表以查找共享该散列的先前文档。您可以计算出这些先前文档共享的小抄总数,然后丢弃所有少于(例如)共享小抄的50%的小抄。这样可以有效地产生一组至少(估计)相似度为50%的所有文档。

最后,为新文档的每个哈希插入新行。

使用Lucene或Solr是一个糟糕的解决方案。这将需要更多的存储空间,实现起来会更加复杂,并且效率会大大降低。是的,您可以让Lucene为您的小错误建立索引,并按照stemm的建议运行查询。这将返回甚至共享一个minhash的每个文档,该哈希可能为数万或数十万,具体取决于您的数据大小。然后,您必须使用“相似性”功能将这些中的每一个分别与传入文档进行比较,这将非常慢。

Lucene确实提供了“ MoreLikeThis”功能来查找共享某些关键字的文档,但这会遗漏minhash方法可以找到的许多相似文档。