局部敏感哈希简介

上一年记录的东西,整理下...

LSH,是Locality Sensitive Hashing的缩写,也翻译为局部敏感哈希,是一种通过设计满足特殊性质即局部敏感的哈希函数,提高相似查询效率的方法。

虽然从正式提出距今不过十余年,由于其局部敏感的特殊性质,以及在高维数据上相当于k-d树等方法的优越性,LSH被广泛地运用于各种检索(包括并不仅限于文本、音频、图片、视频、基因等)领域。

一.哈希检索概述

1.1 检索分类

在检索技术中,索引一直需要研究的核心技术。当下,索引技术主要分为三类:基于树的索引技术(tree-based index)、基于哈希的索引技术(hashing-based index)与基于词的倒排索引(visual words based inverted index)。

在检索中,需要解决的问题是给定一个查询样本query,返回与此query相似的样本,线性搜索耗时耗力,不能承担此等重任,要想快速找到结果,必须有一种方法可以将搜索空间控制到一个可以接受的范围,哈希在检索中就是承担这样的任务,因而,这些哈希方法一般都是局部敏感(Locality-sensitive)的,即样本越相似,经过哈希后的值越有可能一样。所以,本文中介绍的技术都是局部敏感哈希(Locality Sensitive Hashing,LSH),与hashmap、hashtable等数据结构中的哈希函数有所不同。

1.2 分层法与哈希码法

对于哈希技术,可以按照不同的维度对齐进行划分。
按照其在检索技术中的应用方法来划分,可以分为分层法和哈希码法:

分层法即为在数据查询过程中使用哈希技术在中间添加一层,将数据划分到桶中;在查询时,先对query计算桶标号,找到与query处于同一个桶的所有样本,然后按照样本之间的相似度计算方法(比如欧氏距离、余弦距离等)使用原始数据计算相似度,按照相似度的顺序返回结果,在该方法中,通常是一组或一个哈希函数形成一个表,表内有若干个桶,可以使用多个表来提高查询的准确率,但通常这是以时间为代价的。
分层法的代表算法为E2LSH。

哈希码法则是使用哈希码来代替原始数据进行存储,在分层法中,原始数据仍然需要以在第二层被用来计算相似度,而哈希码法不需要,它使用LSH函数直接将原始数据转换为哈希码,在计算相似度的时候使用hamming距离来衡量。转换为哈希码之后的相似度计算非常之快,比如,可以使用64bit整数来存储哈希码,计算相似度只要使用同或操作就可以得到,唰唰唰,非常之快,忍不住用拟声词来表达我对这种速度的难言之喜,还望各位读者海涵。哈希码法的代表算法有很多,比如KLSH、Semantic Hashing、KSH等。

1.3 分层法与哈希码法区别

以我看来,两者的区别在于如下几点:

在对哈希函数的要求上,哈希码方法对哈希函数的要求更高,因为在分层法中,即便哈希没有计算的精确,后面还有原始数据直接计算相似度来保底,得到的结果总不会太差,而哈希码没有后备保底的,胜则胜败则败。
在查询的时间复杂度上,分层法的时间复杂度主要在找到桶后的样本原始数据之间的相似度计算,而哈希码则主要在query的哈希码与所有样本的哈希码之间的hamming距离的相似计算。哈希码法没有太多其他的需要,但分层法中的各个桶之间相对较均衡方能使复杂度降到最低。按照我的经验,在100W的5000维数据中,KSH比E2LSH要快一个数量级。
在哈希函数的使用上,两者使用的哈希函数往往可以互通,E2LSH使用的p-stable LSH函数可以用到哈希码方法上,而KSH等哈希方法也可以用到分层法上去。
上述的区别分析是我自己分析的,如果有其他意见欢迎讨论。
按照哈希函数来划分,可以分为无监督和有监督两种:

无监督,哈希函数是基于某种概率理论的,可以达到局部敏感效果。如E2LSH等。
有监督,哈希函数是从数据中学习出来的,如KSH、Semantic Hashing等。
一般来说,有监督算法比无监督算法更加精确,因而也更常用于哈希码法中。
本文中,主要对无监督的哈希算法进行介绍。

二.常用LSH

2.1 原始LSH

Origin LSH在哈希之前,首先要先将数据从L1准则下的欧几里得空间嵌入到Hamming空间。
在做此embedding时,有一个假设就是原始点在L1准则下的效果与在L2准则下的效果相差不大,
即欧氏距离和曼哈顿距离的差别不大,因为L2准则下的欧几里得空间没有直接的方法嵌入到hamming空间。

Embedding算法如下:
找到所有点的所有坐标值中的最大值C;
对于一个点P来说,P=(x1,x2,…,xd),d是数据的维度;
将每一维xi转换为一个长度为C的0/1序列,其中序列的前xi个值为1,剩余的为0.
然后将d个长度为C的序列连接起来,形成一个长度为Cd的序列.
这就是embedding方法。注意,在实际运算过程中,通过一些策略可以无需将embedding值预先计算出来。

Algorithm of Origin LSH
在Origin LSH中,每个哈希函数的定义如下:

即输入是一个01序列,输出是该序列中的某一位上的值。于是,hash函数簇内就有Cd个函数(有Cd中可能,只不过选k个)。

在将数据映射到桶中时,选择k个上述哈希函数,组成一个哈希映射,如下:


再细化,LSH的算法步骤如下:
从[0,Cd]内取L个数,形成集合G,即组成了一个桶哈希函数g。
对于一个向量P,得到一个L维哈希值,即P|G,其中L维中的每一维都对应一个哈希函数h。
由于直接以上步中得到的L维哈希值做桶标号不方便,因而再进行第二步哈希,
第二步哈希就是普通的哈希,将一个向量映射成一个实数。


其中,a是从[0,M-1]中随机抽选的数字。

这样,就把一个向量映射到一个桶中了。

笔者注:这种嵌入方法下,海明距离恰好是曼哈顿距离,那为什么不直接算曼哈顿距离呢?

其实是这样的,先哈希,找到一些位,然后算海明距离,这不是曼哈顿距离,而且这样的曼哈顿距离毫无意义。

2.1 LSH based on p-stable distribution

E2LSH
基于p-stable分布,并以‘哈希技术分类’中的分层法为使用方法,就产生了E2LSH算法。

E2LSH中的哈希函数定义如下:

其中,v为d维原始数据,a为随机变量,由正态分布产生; w为宽度值,因为a?v+b得到的是一个实数,如果不加以处理,那么起不到桶的效果,w是E2LSH中最重要的参数,调得过大,数据就被划分到一个桶中去了,过小就起不到局部敏感的效果。b使用均匀分布随机产生,均匀分布的范围在[0,w]。

与Origin LSH类似,选取k个上述的哈希函数,组成一个哈希映射。

但是这样,得到的结果是(N1,N2,…,Nk),其中N1,N2,…,Nk在整数域而不是只有0,1两个值,这样的k元组就代表一个桶。但将k元组直接当做桶标号存入哈希表,占用内存且不便于查找,为了方便存储,设计者又将其分层,使用数组+链表的方式,如下图

对每个形式为k元组的桶标号,使用如下h1函数和h2函数计算得到两个值,其中h1的结果是数组中的位置,数组的大小也相当于哈希表的大小,h2的结果值作为k元组的代表,链接到对应数组的h1位置上的链表中。在下面的公式中,r为[0,prime-1]中依据均匀分布随机产生。

经过上述组织后,查询过程如下:
  • 对于查询点query,
  • 使用k个哈希函数计算桶标号的k元组;
  • 对k元组计算h1和h2值,
  • 获取哈希表的h1位置的链表,
  • 在链表中查找h2值,
  • 获取h2值位置上存储的样本
  • Query与上述样本计算精确的相似度,并排序
  • 按照顺序返回结果。

E2LSH方法存在两方面的不足:首先是典型的基于概率模型生成索引编码的结果并不稳定。虽然编码位数增加,但是查询准确率的提高确十分缓慢;其次是需要大量的存储空间,不适合于大规模数据的索引。E2LSH方法的目标是保证查询结果的准确率和查全率,并不关注索引结构需要的存储空间的大小。E2LSH使用多个索引空间以及多次哈希表查询,生成的索引文件的大小是原始数据大小的数十倍甚至数百倍。

2.3 Hashcode of p-stable distribution

E2LSH可以说是分层法基于p-stable distribution的应用。另一种当然是转换成hashcode,则定义哈希函数如下:

其中,a和v都是d维向量,a由正态分布产生。同上,选择k个上述的哈希函数,得到一个k位的hamming码,按照”哈希技术分类”中描述的技术即可使用该算法。

四.疑难点

1.疑问:欧式距离映射到海明空间?
不同的哈希函数可以选择不同的a和b,选择多个哈希函数进行映射增加了冲突概率?

答:并不是增加冲突概率,说的就是与构建,是拉大p1^k和p2^k的差距,但是二者都变小了,或构建又同时拉大二者。

2.编辑距离

编辑距离d(x,y) = |x| + |y| - 2|LCS(x,y)|,其中LCS是longest common subsequence,最长公共子序列。?没验证过

[1]. Ai L, Yu J, He Y, et al. High-dimensional indexing technologies for large scale content-based image retrieval: a review[J]. Journal of Zhejiang University SCIENCE C, 2013, 14(7): 505-520.

[2]. Datar M, Immorlica N, Indyk P, et al. Locality-sensitive hashing scheme based on p-stable distributions[C]//Proceedings of the twentieth annual symposium on Computational geometry. ACM, 2004: 253-262.

[3]. Kulis B, Grauman K. Kernelized locality-sensitive hashing[J]. Pattern Analysis and Machine Intelligence, IEEE Transactions on, 2012, 34(6): 1092-1104.

[4]. Salakhutdinov R, Hinton G. Semantic hashing[J]. International Journal of Approximate Reasoning, 2009, 50(7): 969-978.

[5]. Liu W, Wang J, Ji R, et al. Supervised hashing with kernels[C]//Computer Vision and Pattern Recognition (CVPR), 2012 IEEE Conference on. IEEE, 2012: 2074-2081.

[6]. Gionis A, Indyk P, Motwani R. Similarity search in high dimensions via hashing[C]//VLDB. 1999, 99: 518-529.

[7]. http://web.mit.edu/andoni/www/LSH/

[8]. http://blog.csdn.net/jasonding1354/article/details/38237353

[9]. http://dataunion.org/12912.html

时间: 2024-08-05 06:16:10

局部敏感哈希简介的相关文章

局部敏感哈希LSH

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

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

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

为什么要用局部敏感哈希

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

基于局部敏感哈希的协同过滤算法之simHash算法

搜集了快一个月的资料,虽然不完全懂,但还是先慢慢写着吧,说不定就有思路了呢. 开源的最大好处是会让作者对脏乱臭的代码有羞耻感. 当一个做推荐系统的部门开始重视[数据清理,数据标柱,效果评测,数据统计,数据分析]这些所谓的脏活累活,这样的推荐系统才会有救. 求教GitHub的使用. 简单不等于傻逼. 我为什么说累:我又是一个习惯在聊天中思考前因后果的人,所以整个大脑高负荷运转.不过这样真不好,学习学成傻逼了. 研一的最大收获是让我明白原来以前仰慕的各种国家自然基金项目,原来都是可以浑水摸鱼忽悠过去

局部敏感哈希(Locality Sensitive Hashing)

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

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

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

【常用算法】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分布的哈希方

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

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