位串最近邻搜索

时间:2012-03-31 21:13:20

标签: compression hash nearest-neighbor hamming-distance

我有数十万个长度为32位的稀疏位串。

我想对他们进行最近邻搜索,查找性能至关重要。我一直在阅读各种算法,但它们似乎是针对文本字符串而不是二进制字符串。我认为局部敏感的散列或光谱散列似乎是很好的候选者,或者我可以研究压缩。这些中的任何一个都能很好地解决我的位串问题吗?任何方向或指导都将不胜感激。

2 个答案:

答案 0 :(得分:3)

这是一种快速简便的方法, 然后是以更多内存为代价的更好性能的变体。

In:array Uint X [],例如1M 32位字
通缉:功能near( Uint q ) - > j小hammingdist( q, X[j] )
方法:已排序q中的二进制搜索X, 然后线性搜索周围的块。
伪代码:

def near( q, X, Blocksize=100 ):
    preprocess: sort X
    Uint* p = binsearch( q, X )  # match q in leading bits
    linear-search Blocksize words around p
    return the hamming-nearest of these.

这很快 - Binary search 1M字 +最近的汉明主义者,面积为100 采取< 10我们在我的Mac ppc。 (这是高度缓存依赖的 - 您的里程变化。)

这有多接近找到真正最近的X [j]? 我只能试验,不能做数学:
1M随机单词中的1M随机查询, 最近的匹配平均距离为4-5位, 对于真实最接近的距离为3(线性扫描全部为1M):

near32  N 1048576  Nquery 1048576  Blocksize 100 
binary search, then nearest +- 50
7 usec
distance distribution: 0 4481 38137 185212  443211 337321 39979 235  0

near32  N 1048576  Nquery 100  Blocksize 1048576 
linear scan all 1048576
38701 usec
distance distribution: 0 0 7 58  35 0

使用块大小50和100来运行数据 看看比赛距离是如何下降的。

<小时/> 为了更接近,以两倍的记忆为代价,
制作Xswap X的副本,其中上/下半字交换, 然后返回

near( q, X, Blocksize )
near( swap q, Xswap, Blocksize )

拥有大量内存,可以使用X的更多位洗牌副本, 例如32次旋转 我不知道Nshuffle和Blocksize的性能如何变化 - LSH理论家的一个问题。

<小时/> (已添加):近似匹配320位,10个字的位串, 制作10个指针数组,按字0,字1排序...... 并使用上述binsearch搜索块:

nearest( query word 0, Sortedarray0, 100 ) -> min Hammingdist e.g. 42 of 320
nearest( query word 1, Sortedarray1, 100 ) -> min Hammingdist 37
nearest( query word 2, Sortedarray2, 100 ) -> min Hammingdist 50
...
-> e.g. the 37.

这当然会错过近似的比赛,没有一个单词接近, 但它很简单,排序和binsearch快速 。 指针数组占用与数据位完全相同的空间。 100个字,3200位将以完全相同的方式工作 但是:只有当0位和1位的数量大致相等时才有效, 不是99%0位。

答案 1 :(得分:1)

我刚刚发现了一篇解决这个问题的论文。

  

Randomized algorithms and NLP: using locality sensitive hash function for high speed noun clustering(Ravichandran等,2005)

基本思想类似于丹尼斯的答案(按字母顺序排列不同的位排列),但它包含了一些额外的想法和关于该主题的文章的进一步参考。

它实际上是在我发现它的https://github.com/soundcloud/cosine-lsh-join-spark中实现的。