这篇文章想给大家介绍一个神奇的东东:LSH首先看看它有什么用先~它可以快速地找出海量数据中的相似数据点,听着有点抽象?那我们来举个实际的例子,比如说你有海量的网页(这里的网页是指你拥有的本地数据,不是指互联网上的),你现在想找和一个特定网页相似的其它网页,就比如你想在海量的网页中找出和我这篇博文相似的网页~最naive的方法就是去遍历整个数据集,一个一个页面去比较,看看哪一个页面和我的这个页面最相似,当然所谓的相似需要你自己去定义,可以用Cosine Similarity、Jaccard Coefficient等去衡量(可以参考我的另一篇博文:常用相似性、相关性度量指标),至于特征向量的构造,那就有很多方法了,如使用分词后的各词的TF-IDF值,这里就不展开了。
现在假设你已经对各个页面提取好了特征,那下面的事情就是:给定一个特征,如何快速地从海量的特征中找到和这个特征相似的一些特征?这时候LSH就闪亮登场了(鼓掌ing...),先看看它的名字,Locality Sensitive Hashing,局部敏感哈希。哈希大家应该都知道,它的查找时间复杂度是O(1),有着极高的查找性能,那什么叫“局部敏感”的哈希?它的意思就是:如果原来的数据相似,那么hash以后的数据也保持一定的相似性,这玩意就叫局部敏感哈希。
来看看我们通常的哈希,比如有一个hash function: f(x)=(x*7)%10,有两个数据x1=123,x2=124,现在用f(x)把它们hash一下,f(x1)=1,f(x2)=8,这想说明什么呢?看看原来的数据,是不是很相似?(假设用欧氏距离度量)再看hash后的数据,那就差得远了,说明这个hash它并没有保持相似性,那么这种就不是局部敏感哈希。
那么LSH就是一种在hash之后能保持一定的相似性神奇玩意儿,这里为什么说是“保持一定的相似性”?因为我们知道,hash函数的值域一般都是有限的,但是要哈希的数据却是无法预知的,可能数据大大超过其值域,那么就不可能避免地会出现一个以上的数据点拥有相同的hash值,这有什么影响呢?假设有一个很好的hash function,好到可以在hash之后很好地保持原始数据的相似性,假设它的不同取值数是10个,然后现在我有11个截然不相似的数据点,想用这个hash function来hash一下,因为这个hash function的不同取值数是10个,所以必然会出现一个hash桶中有1个以上的数据点,那刚才不是说11个截然不相似的数据点吗?它们应该有不同的hash值才对啊。没错,的确希望它是这样,但实际上很难,只能在hash之后保持一定的相似性。其根本原因就是在做相似性度量的时候,hash function通常是把高维数据映射到低维空间上,为什么映射到低维空间上?因为高维空间上计算复杂度太高。
降维会对相似性度量造成什么影响?数据的维数在某种程度上能反映其信息量,一般来说维数越多,其反映的信息量就越大,比如说对于一个人,假设有一个一维数据:(姓名),有一个三维数据(姓名,身高,体重),那么这个三维数据反映的信息是不是要比一维的多?如果我们知道的信息越多,是不是就能越准确地判定两个东西的相似性?所以,降维就在某种程度上造成的信息的丢失,在降维后的低维空间中就很难100%保持原始数据空间中的相似性,所以刚才是说“保持一定的相似性”。
好家伙,一方面想把数据降维,一方面又希望降维后不丢失信息,这是不可能的,那么就要做一个妥协了,双方都让一步,那么就可以实现在损失一点相似性度量准确性的基础上,把数据降维,通常来说,这是值得的。说了这么多,那LSH究竟是如何做的呢?先一句话总结一下它的思想吧:它是用hash的方法把数据从原空间哈希到一个新的空间中,使得在原始空间的相似的数据,在新的空间中也相似的概率很大,而在原始空间的不相似的数据,在新的空间中相似的概率很小。
其实在用LSH前通常会进行一些降维操作,我们先看看下面这张图:
先说说整个流程,一般的步骤是先把数据点(可以是原始数据,或者提取到的特征向量)组成矩阵,然后通过第一步的hash functions(有多个哈希函数,是从某个哈希函数族中选出来的)哈希成一个叫“签名矩阵(Signature Matrix)”的东西,这个矩阵可以直接理解为是降维后的数据,然后再通过LSH把Signature Matrix哈希一下,就得到了每个数据点最终被hash到了哪个bucket里,如果新来一个数据点,假如是一个网页的特征向量,我想找和这个网页相似的网页,那么把这个网页对应的特征向量hash一下,看看它到哪个桶里了,于是bucket里的网页就是和它相似的一些候选网页,这样就大大减少了要比对的网页数,极大的提高了效率。注意上句为什么说是“候选网页”,也就是说,在那个bucket里,也有可能存在和被hash到这个bucket的那个网页不相似的网页,原因请回忆前面讲的“降维”问题。。但LSH的巧妙之处在于可以控制这种情况发生的概率,这一点实在是太牛了,下面会介绍。
由于采用不同的相似性度量时,第一步所用的hash functions是不一样的,并没有通用的hash functions,因此下面主要介绍两种情况:(1)用Jaccard相似性度量时,(2)用Cosine相似性度量时。在第一步之后得到了Signature Matrix后,第二步就都一样了。
先来看看用Jaccard相似性度量时第一步的hash functions。
假设现在有4个网页(看成是document),页面中词项的出现情况用以下矩阵来表示,1表示对应词项出现,0则表示不出现,这里并不用去count出现了几次,因为是用Jaccard去度量的嘛,原因就不用解释了吧。
好,接下来我们就要去找一种hash function,使得在hash后尽量还能保持这些documents之间的Jaccard相似度
目标就是找到这样一种哈希函数h(),如果原来documents的Jaccard相似度高,那么它们的hash值相同的概率高,如果原来documents的Jaccard相似度低,那么它们的hash值不相同的概率高。这玩意叫Min-Hashing。
Min-Hashing是怎么做的呢?请看下图:
首先生成一堆随机置换,把Signature Matrix的每一行进行置换,然后hash function就定义为把一个列C hash成一个这样的值:就是在置换后的列C上,第一个值为1的行的行号。呼,听上去好抽象,下面看列子:
图中展示了三个置换,就是彩色的那三个,我现在解释其中的一个,另外两个同理。比如现在看蓝色的那个置换,置换后的Signature Matrix为:
然后看第一列的第一个是1的行是第几行,是第2行,同理再看二三四列,分别是1,2,1,因此这四列(四个document)在这个置换下,被哈希成了2,1,2,1,就是右图中的蓝色部分,也就相当于每个document现在是1维。再通过另外两个置换然后再hash,又得到右边的另外两行,于是最终结果是每个document从7维降到了3维。我们来看看降维后的相似度情况,就是右下角那个表,给出了降维后的document两两之间的相似性。可以看出,还是挺准确的,回想一下刚刚说的:希望原来documents的Jaccard相似度高,那么它们的hash值相同的概率高,如果原来documents的Jaccard相似度低,那么它们的hash值不相同的概率高,如何进行概率上的保证?Min-Hashing有个惊人的性质:
就是说,对于两个document,在Min-Hashing方法中,它们hash值相等的概率等于它们降维前的Jaccard相似度。下面来看看这个性质的Proof:
设有一个词项x(就是Signature Matrix中的行),它满足下式:
就是说,词项x被置换之后的位置,和C1,C2两列并起来(就是把两列对应位置的值求或)的结果的置换中第一个是1的行的位置相同。那么有下面的式子成立:
就是说x这个词项要么出现在C1中(就是说C1中对应行的值为1),要么出现在C2中,或者都出现。这个应该很好理解,因为那个1肯定是从C1,C2中来的。
那么词项x同时出现在C1,C2中(就是C1,C2中词项x对应的行处的值是1)的概率,就等于x属于C1与C2的交集的概率,这也很好理解,属于它们的交集,就是同时出现了嘛。那么现在问题是:已知x属于C1与C2的并集,那么x属于C1与C2的交集的概率是多少?其实也很好算,就是看看它的交集有多大,并集有多大,那么x属于并集的概率就是交集的大小比上并集的大小,而交集的大小比上并集的大小,不就是Jaccard相似度吗?于是有下式:
又因为当初我们的hash function就是
往上面一代,不就是下式了吗?
这就证完了,这标志着我们找到了第一步中所需要的hash function,再注意一下,现在这个hash function只适用于Jaccard相似度,并没有一个万能的hash function。有了hash functions,就可以求Signature Matrix了,求得Signature Matrix之后,就要进行LSH了。
首先将Signature Matrix分成一些bands,每个bands包含一些rows,如下图所示:
然后把每个band哈希到一些bucket中,如下图所示:
注意bucket的数量要足够多,使得两个不一样的bands被哈希到不同的bucket中,这样一来就有:如果两个document的bands中,至少有一个share了同一个bucket,那这两个document就是candidate pair,也就是很有可能是相似的。
下面来看看一个例子,来算一下概率,假设有两个document,它们的相似性是80%,它们对应的Signature Matrix矩阵的列分别为C1,C2,又假设把Signature Matrix分成20个bands,每个bands有5行,那么C1中的一个band与C2中的一个band完全一样的概率就是0.8^5=0.328,那么C1与C2在20个bands上都没有相同的band的概率是(1-0.328)^20=0.00035,这个0.00035概率表示什么?它表示,如果这两个document是80%相似的话,LSH中判定它们不相似的概率是0.00035,多么小的概率啊!
再看先一个例子,假设有两个document,它们的相似性是30%,它们对应的Signature Matrix矩阵的列分别为C1,C2,Signature Matrix还是分成20个bands,每个bands有5行,那么C1中的一个band与C2中的一个band完全一样的概率就是0.3^5=0.00243,那么C1与C2在20个bands至少C1的一个band和C2的一个band一样的概率是1-(1-0.00243)……20=0.0474,换句话说就是,如果这两个document是30%相似的话,LSH中判定它们相似的概率是0.0474,也就是几乎不会认为它们相似,多么神奇。
更为神奇的是,这些概率是可以通过选取不同的band数量以及每个band中的row的数量来控制的:
除此之外,还可以通过AND和OR操作来控制,就不展开了。
呼,LSH的核心内容算是介绍完了,下面再简单补充一下当相似性度量是Cosine相似性的时候,第一步的hash function是什么。它是用了一个叫随机超平面(Random Hyperplanes)的东西,就是说随机生成一些超平面,哈希方法是看一个特征向量对应的点,它是在平台的哪一侧:
这个可以直观地想象一下,假设有两个相交的超平面,把空间分成了4个区域,如果两个特征向量所对应的点在同一域中,那么这两个向量是不是挨得比较近?因此夹角就小,Cosine相似度就高。对比一下前面用Jaccard相似度时Signature Matrix的生成方法,那里是用了三个转换,在这里对应就是用三个随机超平面,生成方法是:对于一个列C(这里因为是用Cosine相似度,所以列的值就不一定只是0,1了,可以是其它值,一个列就对应一个特征向量),算出该列对应的特征向量的那个点,它是在超平面的哪个侧,从而对于每个超平面,就得到+1或者-1,对于三个超平面,就得到三个值,就相当于把原来7维的数据降到三维,和前面用Jaccard相似度时的情况是不是很像?得到Signature Matrix后,就进行LSH,步骤是一样的~~~~~~~
参考:Stanford CS246课程PPT关于Locality Sensitive Hashing的章节,http://cs246.stanford.edu
---------------------
作者:Kenney_Qin
来源:CSDN
原文:https://blog.csdn.net/OrthocenterChocolate/article/details/38943491
版权声明:本文为博主原创文章,转载请附上博文链接!