局部敏感哈希(Locality Sensitive Hashing)

比较不同的文章、图片啊什么的是否相似,如果一对一的比较,数据量大的话,以O(n2)的时间复杂度来看,计算量相当惊人。所以如果是找相同就好了,直接扔到一个hashmap中即可。这样就是O(n)的复杂度了。
不过相同的字符串一定会得到相同的hash,而不同的字符串,哪怕只有一点点不同,也极可能得到完全不同hash。很自然的想到,要是相似的object能够得到相似的hash就好了。局部敏感哈希就是这样的hash,实现了相似的object的hash也是相似的。


定义相似

要找相似,首先是要定义什么事相似。对于高位空间中的相似,一般认为距离越近越相似。一般用Jaccard distance/similarity来描述:
sim(C1,C2)=|C1∩C2|/|C1∪C2|,d(C1,C2)=1?|C1∩C2|/|C1∪C2|

例如,该图sim=4/11, d=1 - 4/11=7/11


寻找相似的关键三步

  1. Shingling:把文档转化为集合
  2. MinHashing:把较大的集合转换为较短的签名,同时保留相似性
  3. Locality-sensitive-hashing:找出相似的signature,对应的pair既是要找的相似pair

Shingling

直接举例子说明:
k=2,D1=abcab,那么2-shingles set:S(D1)={ab, bc, ca}
对于较长的shingle,可以将其hash,所以得到:h(D1)={1,5,7},
设C1=D1,那么对于D2,他们的相似性为:sim(C1,C2)=|C1∩C2|/|C1∪C2|
一般来讲,k越大,相似性判断的就越准确,不过这样来判断相似性依旧效率低下,时间复杂度还是O(n2)(因为没有做任何的简化)

MinHashing

相似矩阵

在使用MinHashing之前,首先要将shingle set写成矩阵形式,看例子:
有5个document:

  1. S1 abcabc
  2. S2 cbacba
  3. S3 acbaba
  4. S4 bcacab
  5. S5 bacbca

那么他们的shingle set:

  1. abcabc = {ab, bc, ca, ab, bc},
  2. cbacba = {cb, ba, ac, cb, ba},
  3. acbaba = {ac, cb, ba, ab, ba},
  4. bcacab = {bc, ca, ac, ca, ab},
  5. bacbca = {ba, ac, cb, bc, ca}

将集合中出现过的shingle放入一个集合,并将其编号,由此可以得到一个矩阵。这个矩阵的行是shingle元素,列是文档

shingle C1 C2 C3 C4 C5
0 (ab) 1 0 1 1 0
1 (ac) 0 1 1 1 1
2 (ba) 0 1 1 0 1
3 (bc) 1 0 0 1 1
4 (ca) 1 0 0 1 1
5 (cb) 0 1 1 0 1

实际上,真正的matrix会相当稀疏,不过有sim的公式可以知道,我们关注的是非零项,因此矩阵只保留那些非全零行。

MinHashing

虽然将shingle set转换成了matrix,但实际上,运算量并没有减少
如果存在一个能够hash document,使每一列的C成为一个较小的signature h(C)。并且满足以下两个条件:

  1. h(c)足够小,使得可以放在RAM中
  2. sim(C1,C2) =P(h(C1)=h(C2))
    即在进行hash时,我们将最相似的对象hash到同一个bucket中

因此,我们的目标是找到这样一个hash函数,使得

  1. 如果sim(C1,C2)很大,则h(C1)=h(C2)
  2. 如果sim(C1,C2)很小,则h(C1)≠h(C2)

很显然,hash function取决于我们如何选取相似的尺度。对于Jaccard similarity,这个hash function就是MinHashing
MinHashing定义:特征矩阵按行进行一个随机的排列后,第一个列值为1的行的行号
我们还是用接着上述的例子来说明,如果我们使用三个hash函数来生成随机排列:

  • h1 = (2x + 1) mod 6 -> 1 3 5 1 3 5
  • h2 = (3x + 2) mod 6 -> 2 5 2 5 2 5
  • h3 = (5x + 2) mod 6 -> 2 1 0 5 4 3

x是shingle,hash后我们得到了新的排列。不过我们看到,如果hash函数选得不好,有些shingle就会无法出现。这里只有h3才是真正的重新排列(没有缺失)
根据这个重新的排列,我们按照定义找出每一个hash函数对应的最小hash值(特征矩阵按行进行一个随机的排列后,第一个列值为1的行的行号),我们可以得到一个hash的matrix:

根据random hash中的重新排序,我们可以找到对应的第一行为1的数值(MinHashing value),填入MinHashing这个表格中,我们得到了最小hash签名(MinHashing signature)
这里要注意的就是,由于random hash选取不够好,会使得出现重复的元素,这种情况情况下,按照从小到大来看即可。即h2只有2和5,先把2检查完,若没有1,才继续看5.

但是,我们为什么可以这样做?为什么MinHash保留了相似性呢?因为两列的最小hash值就是这两列的Jaccard相似度的一个估计,换句话说,两列最小hash值同等的概率与其相似度相等,即P(h(Si)=h(Sj)) = sim(Si,Sj)简单证明下:
对于任意i, j两列,他们可能:

  • 都是1——有A行
  • 既有1,又有0——有B行
  • 都是0——有C行

对于i, j的Jaccard similarity:
sim = A/B
那么对于MinHash来说, 由于是随机排列后:
两个最小hash值相等的概率是A/B
所以,算出了MinHash,并得到signature,原先的相似性也保留在了signature当中

为什么我们需要MinHashing Signature呢?因为中心极限定理。一次hash只是偶然,多次hash才能接近概率。这也是为什么我们用了h1,h2,h3三个hash函数。在实际应用中,会使用更多的hash函数

可以发现,原先一个可能非常大的文章,被我们摘要成了一个签名矩阵,同时不同文章之间的相似性却保留下来了。

Locality Sensitive Hashing

我们的目标是:找到那些相似度至少为S的文档。一般来讲,会用一个hash function(x, y)来指出x和y是否相似

思路是,对于最小哈希尺度

  • 签名矩阵的列被hash到很多buckets中
  • 进入相同bucket的一对说明他们是candidate(备选)的,是否是相似还需要未来进一步检查

具体措施:将签名矩阵分为 b组,每组有r行,然后对每一组进行hash,如果两列的某一组的hash相同,则将其hash到同一个bucket,一般会有k个buckets(k 尽可能的大)。这些进入同一个bucket的列就是candidate pair(尽管可能只有一个组相同)。但是那些完全没有相同的组,一定是不相似的,基于此,进行剪枝。

对于候选相似项我们知道对于某一具体的行,两个签名相同的概率p =两列的相似度= sim(S1,S2),那么我们可以计算:

  • 在某个组中所有行的两个签名值都相等概率是pr;
  • 在某个组中至少有一对签名不相等的概率是1?pr;
  • 在每一组中至少有一对签名不相等的概率是(1?pr)b;
  • 至少有一个组的所有对的签名相等的概率是1?(1?pr)b;

举例来说明:

  • 假设有10w个文档,M = 100000
  • 签名有100个integers组成(100个random hash 函数),合计40Mb=100*10w*4byte
  • b=20,r=5
  • 寻找那些相似性至少在0.8以上的文档

sim(C1,C2) = 0.8意味着任意一组中每行两列(C1,C2)相同的概率是0.8,r=5,那么这一组完全相同的概率是:0.85=0.328
那么对于所有的组b=20来说,两列不相似的概率是:(1?0.328)20=0.00035,所以可以说两列99.965%都是相似的
同理也可证明,相似度为30%的是真的不相似,它们相似的概率只有0.0475

因此我们看到,如果80%的组都被hash到同一个bucket中,那这两列的相似度为0.8,而真正可能相似的概率则为99.965%。这就是局部敏感hash,保证了相似的文档始终会被hash到同一个bucket中。

另外就是,b和r的取值会导致相似曲线的变化,理想中的相似曲线应该是:

可以想象一下,如果b和r都取1,那么红线应该是一条斜率为1的直线
这根红线实际上是至少有一个组的所有对的签名相等的概率:1?(1?tr)b,t是相似度

时间: 2024-11-05 02:43:44

局部敏感哈希(Locality Sensitive Hashing)的相关文章

局部敏感哈希 Kernelized Locality-Sensitive Hashing Page

Kernelized Locality-Sensitive Hashing Page   Brian Kulis (1) and Kristen Grauman (2)(1) UC Berkeley EECS and ICSI, Berkeley, CA(2) University of Texas, Department of Computer Sciences, Austin, TX Introduction Fast indexing and search for large databa

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

局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介绍 本文主要介绍一种用于海量高维数据的近似最近邻快速查找技术--局部敏感哈希(Locality-Sensitive Hashing, LSH),内容包括了LSH的原理.LSH哈希函数集.以及LSH的一些参考资料. 一.局部敏感哈希LSH 在很多应用领域中,我们面对和需要处理的数据往往是海量并且具有很高的维度,怎样快速地从海量的高维数据集合中找到与某个数据最相似(距离最近)的一个数据或多个数据成为了一个难点和问题.

局部敏感哈希(Locality-Sensitive Hashing, LSH)

转自局部敏感哈希(Locality-Sensitive Hashing, LSH) 一.局部敏感哈希LSH 在很多应用领域中,我们面对和需要处理的数据往往是海量并且具有很高的维度,怎样快速地从海量的高维数据集合中找到与某个数据最相似(距离最近)的一个数据或多个数据成为了一个难点和问题.如果是低维的小数据集,我们通过线性查找(Linear Search)就可以容易解决,但如果是对一个海量的高维数据集采用线性查找匹配的话,会非常耗时,因此,为了解决该问题,我们需要采用一些类似索引的技术来加快查找过程

局部敏感哈希简介

上一年记录的东西,整理下... LSH,是Locality Sensitive Hashing的缩写,也翻译为局部敏感哈希,是一种通过设计满足特殊性质即局部敏感的哈希函数,提高相似查询效率的方法. 虽然从正式提出距今不过十余年,由于其局部敏感的特殊性质,以及在高维数据上相当于k-d树等方法的优越性,LSH被广泛地运用于各种检索(包括并不仅限于文本.音频.图片.视频.基因等)领域. 一.哈希检索概述 1.1 检索分类 在检索技术中,索引一直需要研究的核心技术.当下,索引技术主要分为三类:基于树的索

局部敏感哈希LSH

之前介绍了Annoy,Annoy是一种高维空间寻找近似最近邻的算法(ANN)的一种,接下来再讨论一种ANN算法,LSH局部敏感哈希. LSH的基本思想是: 原始空间中相邻的数据点通过映射或投影变换后,在新空间中仍然相邻的概率很大,而不相邻的数据点映射后相邻的概率比较小. 也就是说,我们对原始空间中的数据进行hash映射后,希望相邻的数据能够映射到Hash的同一个桶内. 对所有的原始数据进行hash映射后,就会得到一个hashtable,这个hashtable同一个桶内的数据在原始空间中相邻的概率

【常用算法】KDTree,局部敏感哈希LSH,在基于最近邻的算法中,当N特别大的时候(TODO)

基于最近邻的算法,在各种情况下经常使用, 比如10万个用户,对每一个用户分别查找最相似的用户, 当N特别大的时候,效率就不是很高,比如当N=10^5,时已经不太好算了,因为暴力法时间复杂度为O(N^2). 故需要特殊的手段,这里有两个常用的方法, 一个是KDT树(还有Ball Tree),一个是局部敏感哈希(近似算法,得到得是满足一定置信区间的结果) KDT: O(N*longN) 局部敏感哈希(LSH):跟桶大小有关 1#  K-Dimensional Tree,KDT, https://en

局部敏感哈希之KSH

核函数Kernel Function 流程 分析 监督信息Supervised Information 内积法计算相似度Code Inner Product 目标函数Objective Function 贪心算法求解Greedy Optimization 频谱化宽松Spectral Relaxation Sigmoid平滑Sigmoid Smoothing 最终算法 参考文献 在局部敏感哈希文中,分析了局部敏感哈希方法是如何应用在检索过程中的,以及原始的哈希方法和基于p-stable分布的哈希方

R语言实现︱局部敏感哈希算法(LSH)解决文本机械相似性的问题(二,textreuse介绍)

上一篇(R语言实现︱局部敏感哈希算法(LSH)解决文本机械相似性的问题(一,基本原理))讲解了LSH的基本原理,笔者在想这么牛气冲天的方法在R语言中能不能实现得了呢? 于是在网上搜索了一下,真的发现了一个叫textreuse的包可以实现这样的功能,而且该包较为完整,可以很好地满足要求. 现在的版本是 0.1.3,最近的更新的时间为 2016-03-28. 国内貌似比较少的用这个包来实现这个功能,毕竟R语言在运行大规模数据的性能比较差,而LSH又是处理大规模数据的办法,所以可能国内比较少的用R来执

为什么要用局部敏感哈希

一.题外话 虽然是科普,不过笔者个人认为大道至简,也就是说越简单的东西很可能越值得探讨,或者另外一种说法越简单的东西越不好讲解:其实笔者认为这就是<编程之美>所要传递的——大道至简. 软件构建老师给我推荐的<走出软件作坊>还没看呢. 二.概述 高维数据检索(high-dimentional retrieval)是一个有挑战的任务.对于给定的待检索数据(query),对数据库中的数据逐一进行相似度比较是不现实的,它将耗费大量的时间和空间.这里我们面对的问题主要有两个,第一,两个高维向