局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介绍

局部敏感哈希(Locality Sensitive Hashing)

    计算item之间的相似项,计算item的top M最相似item,协同过滤计算(user based或item based)等等计算中,涉及大量两两相似项计算,计算复杂度为o(n2k),其中n为item量级,k为元素维度量级。即使hadoop和mpi使得模型可在多个机器或处理器协同计算,在处理o(n),nlog(n)复杂度问题时,如鱼得水。但是不说指数级的复杂度,对于m≥2的多项式级复杂度,都是一种对机器的亵渎,也成为了不是一般人或公司能玩得起的东东。

    局部敏感哈希(Locality Sensitive Hashing, LSH)通过哈希方法,缩小两两相似(top)计算的范围,或缩小计算中item的维数,从而达到快速计算相似度的方法。使复杂度变为o(nml),其中n为item的量级,m<<n为新的搜索空间,类似于分支限界中的分支,l<<k,类似于降维处理。

    由于笔者常关注于个性化推荐的top M服务,本文所述也主要用于此,但不限于此。

1 Jaccard相似度

    Jaccard相似度计算十分便于计算离散集合之间的相似度,在个性化推荐中应用极广。Jaccard的相似度计算如图1所示,其中S和T的相似度为J(S,T)=3/8。

局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介绍_第1张图片图1 Jaccard相似度计算

    PS:大量连续的相似度计算,也可以转成Jaccard相似度计算,在此不述。

2 Simhash

    Simhash主要做用是使复杂度o(nml)中,使m<<n,即大幅减小搜索空间的作用。例如计算item a的近临(top M)时,只搜索一个特定的近临空间m,而非整个庞大的n空间。

    Simhash是通过设计一个hash方法,使要内容相近item生的hash签名也相近,hash签名的相近程度,也能反映出item间的相似程度。

    Simhash算法如下:

假设item={item1,item2,…},取hash函数,将item的每一个元素hash成一个M位的int签名值,将int值按二进制表示,0处全表示为-1,记为H,将所有按位相加,最后加正的位为1,为负的位值为0,这就是item最后的simhash结果。这样就可以使相似的item有相近的hash值。

    举例说明如下,假设item a ={1,2,3,4}, item b={1,2,3,5}, h(x)=x%8,M=3,有如图2中的结果,item a的sim hash值为(0,0,1,0),item b的sim hash值为(0,0,1,1),可见两者的sim hash值相似,通过两者的汉明码计算,便可以用汉明码来衡量两者的相似程度。

局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介绍_第2张图片图2 simhash计算

    从降维的脚度看,通过将item预处理为simhash值后,通过计算两者的汉明距离计算相似度。可惜汉明距离并不能完全表征两者的实际相似程度,因而simhash常用于缩小搜索空间,计算item a的top M相似item时,搜索限为汉明距离最近的空间中。例如假设hash在64位,共将有264个hash桶,将所有item预先按hash桶建好索引后,计算item a的top M或满足某域值的相似item时,可从最近的hash桶中搜索,最近的桶为本桶中的其它item,其次为1位不同的其它hash桶,共64个,再次为2位不同的桶,共64*64个…

3 Minhash  

    Minhash主要做用是使复杂度o(nml)中,使l<<k,即减小计算两两相似度计算的维数。

    由第1节可知,计算J(S,T)的关键在于计算S∩T或S∪T。直接求S∩T或S∪T,在有序的归并方法中,复杂度也是k的级别。Minhash的目的是降维,主要原理是两集合经随机转换后得到的两个最小hash值相等的概率等于两集合的Jaccard的相似度!(可以枚举出相应结果)。

     由于只取一个hash函数时,只有相等与不等两个结果,对应于原理,也就只有相似与不相似不个结果。取一系列hash函数后,便可以概率性地统计出结果,而取hash函数的个数据,决定将k降维后的维数l,l越大,相似结果与实际相似度越相近,一般10个左右就已经能满足工程需求。

     这样数据预处理完后,计算两item间的复杂度,就等于计算最小Minhash相同的概率了。

    PS:在工程中,不容易找一系列的hash函数,由hash母函数生成的一系列hash函数可能相关,将降低Minhash的经度。

4 优势与局限性

    Simhash和Minhash都有明显的应用局限性:

1、集合中的item要比较多;

2、所求的相关项要比较相似;

    优势:

1、简化复杂相似项计算;

2、原理易于理解,点破后,给人显而易见的感觉。

  

参考:

Similarity estimation techniques from rounding algorithms;

Mining of Massive Datasets;



本文主要介绍一种用于海量高维数据的近似最近邻快速查找技术——局部敏感哈希(Locality-Sensitive Hashing, LSH),内容包括了LSH的原理、LSH哈希函数集、以及LSH的一些参考资料。


一、局部敏感哈希LSH

在很多应用领域中,我们面对和需要处理的数据往往是海量并且具有很高的维度,怎样快速地从海量的高维数据集合中找到与某个数据最相似(距离最近)的一个数据或多个数据成为了一个难点和问题。如果是低维的小数据集,我们通过线性查找(Linear Search)就可以容易解决,但如果是对一个海量的高维数据集采用线性查找匹配的话,会非常耗时,因此,为了解决该问题,我们需要采用一些类似索引的技术来加快查找过程,通常这类技术称为最近邻查找(Nearest  Neighbor,AN),例如K-d tree;或近似最近邻查找(Approximate Nearest  Neighbor, ANN),例如K-d tree with BBF, Randomized Kd-trees, Hierarchical K-means Tree。而LSH是ANN中的一类方法。


我们知道,通过建立Hash Table的方式我们能够得到O(1)的查找时间性能,其中关键在于选取一个hash function,将原始数据映射到相对应的桶内(bucket, hash bin),例如对数据求模:h = x mod w,w通常为一个素数。在对数据集进行hash 的过程中,会发生不同的数据被映射到了同一个桶中(即发生了冲突collision),这一般通过再次哈希将数据映射到其他空桶内来解决。这是普通Hash方法或者叫传统Hash方法,其与LSH有些不同之处。


局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介绍_第3张图片

局部敏感哈希示意图(from: Piotr Indyk)


LSH的基本思想是:将原始数据空间中的两个相邻数据点通过相同的映射或投影变换(projection)后,这两个数据点在新的数据空间中仍然相邻的概率很大,而不相邻的数据点被映射到同一个桶的概率很小。也就是说,如果我们对原始数据进行一些hash映射后,我们希望原先相邻的两个数据能够被hash到相同的桶内,具有相同的桶号。对原始数据集合中所有的数据都进行hash映射后,我们就得到了一个hash table,这些原始数据集被分散到了hash table的桶内,每个桶会落入一些原始数据,属于同一个桶内的数据就有很大可能是相邻的,当然也存在不相邻的数据被hash到了同一个桶内。因此,如果我们能够找到这样一些hash functions,使得经过它们的哈希映射变换后,原始空间中相邻的数据落入相同的桶内的话,那么我们在该数据集合中进行近邻查找就变得容易了,我们只需要将查询数据进行哈希映射得到其桶号,然后取出该桶号对应桶内的所有数据,再进行线性匹配即可查找到与查询数据相邻的数据。换句话说,我们通过hash function映射变换操作,将原始数据集合分成了多个子集合,而每个子集合中的数据间是相邻的且该子集合中的元素个数较小,因此将一个在超大集合内查找相邻元素的问题转化为了在一个很小的集合内查找相邻元素的问题,显然计算量下降了很多。


那具有怎样特点的hash functions才能够使得原本相邻的两个数据点经过hash变换后会落入相同的桶内?这些hash function需要满足以下两个条件:

1)如果d(x,y) ≤ d1, 则h(x) = h(y)的概率至少为p1;

2)如果d(x,y) ≥ d2, 则h(x) = h(y)的概率至多为p2;

其中d(x,y)表示x和y之间的距离,d1 < d2, h(x)和h(y)分别表示对x和y进行hash变换。

满足以上两个条件的hash functions称为(d1,d2,p1,p2)-sensitive。而通过一个或多个(d1,d2,p1,p2)-sensitive的hash function对原始数据集合进行hashing生成一个或多个hash table的过程称为Locality-sensitive Hashing。



使用LSH进行对海量数据建立索引(Hash table)并通过索引来进行近似最近邻查找的过程如下:

1. 离线建立索引

(1)选取满足(d1,d2,p1,p2)-sensitive的LSH hash functions;

(2)根据对查找结果的准确率(即相邻的数据被查找到的概率)确定hash table的个数L,每个table内的hash functions的个数K,以及跟LSH hash function自身有关的参数;

(3)将所有数据经过LSH hash function哈希到相应的桶内,构成了一个或多个hash table;

2. 在线查找

(1)将查询数据经过LSH hash function哈希得到相应的桶号;

(2)将桶号中对应的数据取出;(为了保证查找速度,通常只需要取出前2L个数据即可);

(3)计算查询数据与这2L个数据之间的相似度或距离,返回最近邻的数据;


LSH在线查找时间由两个部分组成: (1)通过LSH hash functions计算hash值(桶号)的时间;(2)将查询数据与桶内的数据进行比较计算的时间。因此,LSH的查找时间至少是一个sublinear时间。为什么是“至少”?因为我们可以通过对桶内的属于建立索引来加快匹配速度,这时第(2)部分的耗时就从O(N)变成了O(logN)或O(1)(取决于采用的索引方法)。


LSH为我们提供了一种在海量的高维数据集中查找与查询数据点(query data point)近似最相邻的某个或某些数据点。需要注意的是,LSH并不能保证一定能够查找到与query data point最相邻的数据,而是减少需要匹配的数据点个数的同时保证查找到最近邻的数据点的概率很大。




二、LSH的应用


LSH的应用场景很多,凡是需要进行大量数据之间的相似度(或距离)计算的地方都可以使用LSH来加快查找匹配速度,下面列举一些应用:

(1)查找网络上的重复网页

互联网上由于各式各样的原因(例如转载、抄袭等)会存在很多重复的网页,因此为了提高搜索引擎的检索质量或避免重复建立索引,需要查找出重复的网页,以便进行一些处理。其大致的过程如下:将互联网的文档用一个集合或词袋向量来表征,然后通过一些hash运算来判断两篇文档之间的相似度,常用的有minhash+LSH、simhash。

(2)查找相似新闻网页或文章

与查找重复网页类似,可以通过hash的方法来判断两篇新闻网页或文章是否相似,只不过在表达新闻网页或文章时利用了它们的特点来建立表征该文档的集合。

(3)图像检索

在图像检索领域,每张图片可以由一个或多个特征向量来表达,为了检索出与查询图片相似的图片集合,我们可以对图片数据库中的所有特征向量建立LSH索引,然后通过查找LSH索引来加快检索速度。目前图像检索技术在最近几年得到了较大的发展,有兴趣的读者可以查看基于内容的图像检索引擎的相关介绍。

(4)音乐检索

对于一段音乐或音频信息,我们提取其音频指纹(Audio Fingerprint)来表征该音频片段,采用音频指纹的好处在于其能够保持对音频发生的一些改变的鲁棒性,例如压缩,不同的歌手录制的同一条歌曲等。为了快速检索到与查询音频或歌曲相似的歌曲,我们可以对数据库中的所有歌曲的音频指纹建立LSH索引,然后通过该索引来加快检索速度。

(5)指纹匹配

一个手指指纹通常由一些细节来表征,通过对比较两个手指指纹的细节的相似度就可以确定两个指纹是否相同或相似。类似于图片和音乐检索,我们可以对这些细节特征建立LSH索引,加快指纹的匹配速度。



三、LSH family

我们在第一节介绍了LSH的原理和LSH hash function需要满足的条件,回顾一下:

满足以下两个条件的hash functions称为(d1,d2,p1,p2)-sensitive:

1)如果d(x,y) ≤ d1, 则h(x) = h(y)的概率至少为p1;

2)如果d(x,y) ≥ d2, 则h(x) = h(y)的概率至多为p2;


d(x,y)是x和y之间的一个距离度量(distance measure),需要说明的是,并不是所有的距离度量都能够找到满足locality-sensitive的hash functions。


下面我们介绍一些满足不同距离度量方式下的locality-sensitive的hash functions:

1. Jaccard distance

Jaccard distance: (1 - Jaccard similarity),而Jaccard similarity = (A intersection B) / (A union B),Jaccard similarity通常用来判断两个集合的相似性。


Jaccard distance对应的LSH hash function为:minhash,其是(d1,d2,1-d1,1-d2)-sensitive的。


2. Hamming distance

Hamming distance: 两个具有相同长度的向量中对应位置处值不同的次数。


Hamming distance对应的LSH hash function为:H(V) = 向量V的第i位上的值,其是(d1,d2,1-d1/d,1-d2/d)-sensitive

的。


3. Cosine distance 

Cosine distance:cos(theta) = A·B / |A||B| ,常用来判断两个向量之间的夹角,夹角越小,表示它们越相似。


Cosine distance对应的LSH hash function为:H(V) = sign(V·R),R是一个随机向量。V·R可以看做是将V向R上进行投影操作。其是(d1,d2,(180-d1)180,(180-d2)/180)-sensitive的。


理解:利用随机的超平面(random hyperplane)将原始数据空间进行划分,每一个数据被投影后会落入超平面的某一侧,经过多个随机的超平面划分后,原始空间被划分为了很多cell,而位于每个cell内的数据被认为具有很大可能是相邻的(即原始数据之间的cosine distance很小)。


4. normal Euclidean distance

Euclidean distance是衡量D维空间中两个点之间的距离的一种距离度量方式


Euclidean distance对应的LSH hash function为:H(V) = |V·R + b| / a,R是一个随机向量,a是桶宽,b是一个在[0,a]之间均匀分布的随机变量。V·R可以看做是将V向R上进行投影操作。其是(a/2,2a,1/2,1/3)-sensitive的。

理解:将原始数据空间中的数据投影到一条随机的直线(random line)上,并且该直线由很多长度等于a的线段组成,每一个数据被投影后会落入该直线上的某一个线段上(对应的桶内),将所有数据都投影到直线上后,位于同一个线段内的数据将被认为具有很大可能是相邻的(即原始数据之间的Euclidean distance很小)。



四、增强LSH(Amplifying LSH


通过LSH hash functions我们能够得到一个或多个hash table,每个桶内的数据之间是近邻的可能性很大。我们希望原本相邻的数据经过LSH hash后,都能够落入到相同的桶内,而不相邻的数据经过LSH hash后,都能够落入到不同的桶中。如果相邻的数据被投影到了不同的桶内,我们称为false negtive;如果不相邻的数据被投影到了相同的桶内,我们称为false positive。因此,我们在使用LSH中,我们希望能够尽量降低false negtive rate和false positive rate。


通常,为了能够增强LSH,即使得false negtive rate和/或false positive rate降低,我们有两个途径来实现:1)在一个hash table内使用更多的LSH hash function;2)建立多个hash table。


下面介绍一些常用的增强LSH的方法:


1. 使用多个独立的hash table

每个hash table由k个LSH hash function创建,每次选用k个LSH hash function(同属于一个LSH function family)就得到了一个hash table,重复多次,即可创建多个hash table。多个hash table的好处在于能够降低false positive rate。


2. AND 与操作

从同一个LSH function family中挑选出k个LSH function,H(X) = H(Y)有且仅当这k个Hi(X) = Hi(Y)都满足。也就是说只有当两个数据的这k个hash值都对应相同时,才会被投影到相同的桶内,只要有一个不满足就不会被投影到同一个桶内。


AND与操作能够使得找到近邻数据的p1概率保持高概率的同时降低p2概率,即降低了falsenegtiverate。


3. OR 或操作

从同一个LSH function family中挑选出k个LSH function,H(X) = H(Y)有且仅当存在一个以上的Hi(X) = Hi(Y)。也就是说只要两个数据的这k个hash值中有一对以上相同时,就会被投影到相同的桶内,只有当这k个hash值都不相同时才不被投影到同一个桶内。


OR或操作能够使得找到近邻数据的p1概率变的更大(越接近1)的同时保持p2概率较小,即降低了false positive rate。


4. AND和OR的级联

将与操作和或操作级联在一起,产生更多的hahs table,这样的好处在于能够使得p1更接近1,而p2更接近0。



除了上面介绍的增强LSH的方法外,有时候我们希望将多个LSH hash function得到的hash值组合起来,在此基础上得到新的hash值,这样做的好处在于减少了存储hash table的空间。下面介绍一些常用方法:

1. 求模运算

new hash value = old hash value % N


2. 随机投影

假设通过k个LSH hash function得到了k个hash值:h1, h2..., hk。那么新的hash值采用如下公式求得:

new hash value = h1*r1 + h2*r2 + ... + hk*rk,其中r1, r2, ..., rk是一些随机数。


3. XOR异或

假设通过k个LSH hash function得到了k个hash值:h1, h2..., hk。那么新的hash值采用如下公式求得:

new hash value = h1 XOR h2 XOR h3 ... XOR hk




五、相关参考资料


Website:

[1] http://people.csail.mit.edu/indyk/ (LSH原作者)

[2]  http://www.mit.edu/~andoni/LSH/ (E2LSH)


Paper:

[1] Approximate nearest neighbor: towards removing the curse of dimensionality

[2] Similarity search in high dimensions via hashing

[3] Locality-sensitive hashing scheme based on p-stable distributions 

[4] MultiProbe LSH Efficient Indexing for HighDimensional Similarity Search

[5] Near-Optimal Hashing Algorithms for Approximate Nearest Neighbor in High Dimensions

Tutorial:

[1] Locality-Sensitive Hashing for Finding Nearest Neighbors

[2] Approximate Proximity Problems in High Dimensions via Locality-Sensitive Hashing

[3] Similarity Search in High Dimensions


Book:

[1] Mining of Massive Datasets
[2] Nearest Neighbor Methods in Learning and Vision: Theory and Practice


Cdoe:

[1] http://sourceforge.net/projects/lshkit/?source=directory

[2] http://tarsos.0110.be/releases/TarsosLSH/TarsosLSH-0.5/TarsosLSH-0.5-Readme.html 

[3] http://www.cse.ohio-state.edu/~kulis/klsh/klsh.htm 

[4] http://code.google.com/p/likelike/ 

[5] https://github.com/yahoo/Optimal-LSH

[6] OpenCV LSH(分别位于legacy module和flann module中)

你可能感兴趣的:(局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介绍)