1.介绍
哈希是一种常用的数据摘要方法,可以把大段的数据映射成固定长度的字符串。在查找某个文档的时候,我们不希望每一次都比较大段的数据,以此来确定文档的位置,这样太过浪费生命了。只要实现计算好文档的哈希值,就可以只通过比较两个文档的哈希,查出匹配的文档,从而大大减少检索的时间。
传统的hash方法,比如md5,其设计的目的是为了让整个分布尽可能地均匀,输入内容哪怕只有轻微变化,hash值就会发生很大的变化,这跟它本来是为了跟哈希表配合有关的。但是由于搜索引擎的发展,我们很容易遇到这种情景,即我们为了加快搜索的效率会利用索引,但是索引本身如果直接使用哈希,可无法找到内容相近的,而只能找到完全匹配的,这在现实中是很难满足的。
现实中很多查找问题都是寻找相似集,而非完美匹配集。
这种问题最后是在高维空间里查找,例如:1.两篇有相似单词的文章;2. 两个消费了相似物品的顾客;3.两张有相似特征的图片。
2. LSH的作用
我们需要采用一些类似索引的技术来加快查找过程,通常这类技术称为最近邻查找(Nearest Neighbor,AN),例如K-d tree;或近似最近邻查找(Approximate Nearest Neighbor, ANN),例如K-d tree with BBF, Randomized Kd-trees, Hierarchical K-means Tree。而LSH是ANN中的一类方法。
LSH的基本思想是:将原始数据空间中的两个相邻数据点通过相同的映射或投影变换(projection)后,这两个数据点在新的数据空间中仍然相邻的概率很大,而不相邻的数据点被映射到同一个桶的概率很小。
3. 实现
实现Locality Sensitive Hashing的重要工具只有三个。
Jaccard距离、Min-Hashing函数、桶映射
算法流程是:Documents -> Shingle -> Min-hashing产生签名(摘要)->检索.其中Shingle解释如下:
Shingling
shingling是一种文本的预处理方式。对文档分别进行Shingling(将待查询的字符串集进行映射,映射到一个集合里,如字符串"abcdeeee", 映射到集合"(a,b,c,d,e)", 注意集合中元素是无重复的,这一步骤就叫做Shingling, 意即构建文档中的短字符串集合,即shingle集合。类比倒排索引,我们可以得到类似的矩阵:
3.2 度量和函数
A. C1和C2的Jaccard 距离:
B. 重要的哈希函数 Min-Hashing
输入值是一个矩阵:shingle(文本单元)x文档矩阵,值(i,j)表示词si在文档dj中出现与否。
这样文档的哈希值长度是我们设定的置换个数。在下面的例子中,文档1,2,3,4的哈希值分别是221,112,241,112
找到一个哈希函数,如果sim(C1,C2) 很高, 那么很高概率h(C1) = h(C2)
如果sim(C1,C2)低,那么很高概率h(C1) ≠h(C2)。
Min-hashing函数: hπ(C), 表示在经过π置换的C列中为1的方格的第一个下标。 注:π置换(a1,a2,…)会将向量X中的xi置换到位置ai(i=1,2,3…)
根据这种定义,有如下性质:选择一个随机π,则Pr[hπ(C1) = hπ(C2)] = sim(C1,C2)
证明: 设y∈X, 因为Pr[π(y) = min(π(X)) ] = 1/|X|,(这个性质下面没有用到)
若 π(y) = min(π(C1∪C2)), (即y在置换后是新向量里的最小为1下标),
则 要么π(y) = min(π(C1) 且 y∈C1, 要么π(y) = min(π(C1) 且y∈ C2。
这两种情况同时成立的概率为
Pr[min(π(C1) = min(π(C2)] = |C1 ∩C2| / |C1∪C2| = sim(C1, C2)
这个概率反映的是随机置换的结果。
Min-Hash Signature
用sig(C)表示文档编码C的签名, 则sig(C)[i] = min(πi(C)), 如100个随机置换得到的签名需要100 个byte。
C. LSH算法
1. 先看产生签名的实现方法:
for each column C and hash-func ki keep a slot of the min-hash value sig(C)[i] = ∞ Scan rows looking for 1 Suppose row j has 1 in column C 即: C[j][i] = 1 Then for each ki: if ki(j) < sig(C)[i], then sig(C)[i] <- ki(j) // 用每个置换的下
上面是签名算法,而LSH 算法是检索的算法,给定一个相似度值s和文档,找出相似文档。
由于检索的方法是很naïve的,下面我们只需要验证LSH的性质,并且给出实现方法即可。
问题:
给定s和n x m矩阵M, 先在矩阵M (shingle * document)中找出候选对
n = |shingle|, m = |document|
把矩阵分割成b个band(条带),每个带有整数个数 r = M / b
样例:
假设有100,000个文档, 每个签名是100个整数(100 bytes)
签名占了40 Mb。
b = 20, a = 5, s=0.8.
相似度s >= 0.8的时候, 验算至少有一个band是相同的概率:
sim(C1, C2) = 0.8, (0.8)^5 = 0.328,
1 – (0.328)^20 = 0.00035, 即sim(C1, C2) = 0.8 的时候至少有一个band相同的概率是99.965%。
同样地, 计算sim(C1,C2) = 0.3的时候可以验算得到其概率很低。
4. 参考:
J. Leskovec, A. Rajaraman, J. Ullman: Mining of Massive Datasets,http://www.mmds.org/mmds/v2.1/ch03-lsh.pdf