文章目录

  • 参考
  • 局部敏感哈希(LSH)基本原理介绍
  • 背景
  • LSH 的基本思想
  • LSH 的哈希函数族(Hash Family)
  • LSH 的查找过程
  • LSH 常见的 Hash Function


参考

LSH(Locality Sensitive Hashing)原理与实现。

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

局部敏感哈希(LSH)基本原理介绍

背景

  • 这是一种用于海量高维数据的近似最近邻快速查找技术。
  • 也可以用来发现最相似的集合(集合中元素个数很多,而且有很多集合需要判断,说到集合相似性,这就需要用到 Jaccard距离 和 MinHash)。

在很多应用领域中,我们面对和需要处理的数据往往是海量并且具有很高的维度,怎样快速地从海量的高维数据集合中找到与某个数据最相似(距离最近)的一个数据或多个数据成为了一个难点和问题。如果是低维的小数据集,我们通过线性查找(Linear Search)就可以容易解决,但如果是对一个海量的高维数据集采用线性查找匹配的话,会非常耗时。

因此,为了解决该问题,我们需要采用一些类似索引的技术来加快查找过程,通常这类技术称为最近邻查找(Nearest Neighbor,NN),例如K-d tree;或近似最近邻查找(Approximate Nearest Neighbor, ANN),例如K-d tree with BBF, Randomized Kd-trees, Hierarchical K-means Tree。

而 locality-sensitive hashing(LSH,局部敏感哈希) 是ANN中的一类方法。

LSH 的基本思想

LSH 与传统 hash 的基本思想不同:

  • 传统 hash 将原始数据映射到对应的桶内(bucket 或 hash bin),例如对数据求模:h = x mod w,w 通常为一个素数。在对数据集进行hash 的过程中,会发生不同的数据被映射到了同一个桶中(即发生了冲突,collision),我们要尽量避免冲突,可以通过再次哈希将数据映射到其他空桶内来解决。
  • LSH 将原始数据空间中的两个相邻数据点通过相同的映射或投影变换(projection)后,这两个数据点在新的数据空间中仍然相邻的概率很大,而不相邻的数据点被映射到同一个桶的概率很小。也就是说,如果我们对原始数据进行一些hash映射后,我们希望原先相邻的两个数据能够被hash到相同的桶内,具有相同的桶号

做法:对原始数据集合中所有的数据都进行 hash 映射后,我们就得到了一个 hash table,这些原始数据集被分散到了hash table的桶内,每个桶会落入一些原始数据,属于同一个桶内的数据就有很大可能是相邻的,当然也存在不相邻的数据被hash到了同一个桶内。因此,如果我们能够找到这样一些 hash functions,使得经过它们的哈希映射变换后,原始空间中相邻的数据落入相同的桶内的话,那么我们在该数据集合中进行近邻查找就变得容易了,我们只需要将查询数据进行哈希映射得到其桶号,然后取出该桶号对应桶内的所有数据,再进行线性匹配即可查找到与查询数据相邻的数据

换句话说,我们通过 hash function 映射变换操作,将原始数据集合分成了多个子集合,而每个子集合中的数据间是相邻的且该子集合中的元素个数较小,因此将一个在超大集合内查找相邻元素的问题转化为了在一个很小的集合内查找相邻元素的问题,显然计算量下降了很多。

其实说白了,就是将高维数据转化为低维数据,同时还能在一定程度上保持原始数据的相似性。但 LSH 是不确定的,是概率性的,也就是说有可能将两个原本很相似的数据映射成两个不同的 hash 值,或者原本不相似的数据映射成同一 hash 值。这是高维数据降维过程中所不能避免的(因为降维势必会造成某种程度上数据的失真),不过好在LSH的设计能够通过相应的参数控制出现这种错误的概率,这也是LSH为什么被广泛应用的原因。

LSH 的哈希函数族(Hash Family)

那具有怎样特点的 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。

满足(d1,d2,p1,p2)-sensitive的哈希函数构成了 LSH 的哈希函数族

LSH 的查找过程

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

  • 离线建立索引
  • (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
  • 在线查找
  • (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 常见的 Hash Function

对数据集当中的元素,采用不同的距离函数来进行度量时,对应着不同的 LSH 哈希函数,但并不是所有的距离度量都能够找到满足 locality-sensitive 的 hash functions,下面我们介绍一些满足不同距离度量方式下的locality-sensitive的hash functions:

  1. Jaccard distance
    Jaccard distance = 1 - Jaccard similarity。
    Jaccard similarity:通过计算交集的相对大小来获得集合之间的相似度,也称为 Jaccard 相似度。
    lucene索引读取工具 lsh索引_lucene索引读取工具
    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很小)。