• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Vpegasus
E-mail: pegasus.wenjia@foxmail.com
博客园    首页    新随笔    联系   管理    订阅  订阅
近似最近邻搜索 (三) 局部敏感哈希 LSH

LSH

目录
  • LSH

locality sensitive hashing(LSH) 是哈希算法中,比较重要的方法。LSH方法是将相似的数据以较高的概率哈希到同一个桶里面,从而达到近似邻检索的目的,另外,待测数据维度非常大时,lsh也可用于降维。

LSH族[1]

LSH族 \(\mathcal H = \{h: S\rightarrow U\}\) 称为\((r1,r2,p1,p2)\)对于测度\(D\)是局部敏感的,如果 \(\forall v,q\in S\)有

如果\(v\in B(q,r_1)\) , 那么有 \(Pr_{\mathcal H}[h(q)=h)(v)]\ge p_1\),

如果\(v\notin B(q,r_2)\),那么有\(Pr_{\mathcal H}[h(q)=h)(v)]\le p_2\).

其中,(\(B(v, r)=\{q \in X \mid d(v, q) \leq r\}\) 表示以v为中心,r为半径的球体)

上面的不等式还需要满足两个条件,即\(p_1>p_2\)以及\(r_1<r_2\). 在近似最近邻中,也即\((R,c)\)-NN问题中,可设\(r_1 = R\)以及\(r_2 = c\cdot R\).

已知一啥希族满足上述定义,可以通过使用多种不同的哈希函数来扩大p1与p2之间的距离,这样检索的效果也会更好。比如, 我们选了k个哈希函数,可以定义一个函数族\(\mathcal G = \{g: S\rightarrow U^k\}\),使得\(\mathcal g(v) = \{h_1(v),h_2(v2),...,h_k(v)\}\),其中\(h_i(v)\in\mathcal H\). 然后我们创建L个\(g_i(v), i \in \{1,2,...,L\}\).\(g_i(v)\)之间是相互独立的。

LSH是一种思想,或者说是一种框架,只要定好哈希函数以及距离测度D即可。

有几个比如有代表性的工作:minhash,simhash,p-stable hash等。这些基本区别是使用不同的hash以及不同的距离(或相似)方法。

MinHash特别适用于数据比较稀疏的情形, 比如新闻去重等等。在讲minhash之前需要讲一个滑动窗口切词法(shingling).

比如:'today is a sunny day',使用宽度为3的滑窗,会生成如字符片断:

'tod', 'oda','day','ay ', 'y a',...

这样将每个片段one-hot编码,这样此句话就会变成类似如下这种只包括0,1两个值的长向量:

[0,0,0,1,0,0,0,0,1,....]

此过程类似分词后构建词表过程。只不过,使用shingle的操作一定程度上保留了文章的词序性(特别是滑窗较宽时,比如10或20时,比一般的词长一些,类似n-grams). 此类操作在对网页去重等,有比较不错的效果,操作也简单,只需要计算两网页one hot编码向量的jaccard距离即可。但当两个向量很大时,计算jaccard距离会很耗资源,耗时. 如果可以找一种简单快速地计算Jaccard距离的方法,那么对于高维数据的相似性评估就会很方便。经观察,如果将集合A与B合并成一个集合C, 并从集合C中随机抽取一个元素X,那么此元素X既属于A也属于B的概率为|\(A\cap B\)|/\(|A\cup B|\),即Jaccard相似度 . 基于此逻辑,我们可以将所有元素找到构成一个词典列表。然后我们有放回地每次从中随机抽取一个元素,判断其是否在某两个集合中(比如仍是A,B两集合),经过多次重复,然后统计取出元素同时在集合A,B中的频率,即可近似等于两者的(Jaccard)相似度。

将集合\(\mathbb U\) (可理解为语料)中的元素(如语料中的某篇访问)用onehot的方式表示,那么对于集合:

\[S = \{S_1,S_2,...,S_n\}, S_k\in \mathbb U,k \in \{1,2,...,n\},n\in \mathbb R, \]

其可以其表示成一个二元(共现)矩阵,类似如下(仅为一示例),其中\(s_k\) (k列) 为第k个文章按上述处理得到的onehot表示。

Index \(S_1\) \(S_2\) ... \(S_n\)
0 0 1 ... 0
1 0 0 ... 0
2 1 0 ... 1
... ... ... ... ...
m 1 0 ... 0

将这二元矩阵按行重新排列,那么某一集合\(S_k\)的minhash值为即为排列后的第一个“1”所在行号。那么

\[P\{minhash(S_{k_1})=minhash(S_{k_2})\}= Jaccard(S_{k_1},S_{k_2}) \]

如何理解呢?这里有一个关键点要记在心里,即按行进行重新排列的,那么每行的元素是一起同时变动的。那么从第一行开始往下找,在第\(S_{k_1}\)列与第\(S_{k_2}\)列同时出现一的概率就是其jaccard相似度。这样,可以让\(n = k\times L\),即可以执LSH操作。

simhash

首先将数据如网页文本转化成一组特征(如基本的nlp操作,如分词,去停用词,tdidf等等),然后,将特征哈希成一个f维的二元特征向量(比如f=64),然后将其转化成示性向量(具体做法是将其中的0变成-1,而1还是1), 然后乘以此特征权重(比如词频),然后,再将所有物征相加,最后再进行转化成二元特征向量(元素为正变为1, 其他变为0), 这样的再拼接成一个哈希值,即是此文本的哈希特征值。

比如: 假设在一网页中处理后只有三个词" simhash","simlarity", " algorithm",对应的词频分别为3,1,5。使用哈希函数{‘simhash': '101101','simlarity': '110010,,'algorithm':'100001'}, 然后转化成特征向量化{'simhash':[1,0,1,1,0,1],'simlarity':[1,1,0,0,1,0],'algorithm':[1,0,0,0,0,1]},再转化成示性向量{'simhash':[1,-1,1,1,-1,1],'simlarity':[1,1,-1,-1,1,-1],'algorithm':[1,-1,-1,-1,-1,1]}。接着,将特征的特征向量与其权重(即词频)相乘:{'simhash':[3,-3,3,3,-3,3],'simlarity':[1,1,-1,-1,1,-1],'alogrithm':[5,-5,-5,-5,-5,5]},再将向量相加:[9, -7,-3,-3,-7,7], 再转化成二元向量[1,0,0,0,0,1],最后生成文本哈希特征值:'100001'.

根据经验,如果两个网页的汉明距离不大于3的话,那么它们是重复的,基于此,可以将64位的哈希值平均分成四份,根据抽屉原理,至少有一个片断是相等的。


  1. 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. 2004: 253-262. ↩︎

posted on 2021-12-06 13:12  Vpegasus  阅读(538)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3