局部敏感哈希算法的实现

近来由于工作需要,需要将字符串的相似度的计算速度进行提升。之前曾采用最长公共子序列、编辑距离等算法实现过,但总满足不了实时比较的性能及速度需求。前些天由同事推荐局部敏感哈希算法,便尝试了一把,结果发现速度还不错,本着记录与分享的精神,简单总结下实现的过程及思路。

【Shingle】

将待查询的字符串集进行映射,映射到一个集合里,如字符串“abcdeeeefg", 映射到集合”(a,b,c,d,e,f,g)", 注意集合中元素是无重复的。这一步骤其实叫Shingling, 意即构建文档中的短字符串集合,即shingle集合。

这是最简单的映射,直接以一个字符进行切分了,也可以映射到更复杂的集合,如(ab, bc, de, ef ,fg),(abc, bcd, def, efg)等

字符串集映射的集合,可以进行一步哈希,如a hash到1, b hash 到2,c hash到1  等等, 映射到桶有个很大的好处,是可以减少数据量, 映射到桶之后,我们便可以将字符串用桶编号来进行表示了

【特征矩阵】

假设有k个桶,根据字符串进行shingling之后,是否映射到桶,我们可以得到一个矩阵,可以称之为特征矩阵,这个矩阵以桶对应的hash值为行,以文档字符串集为列,矩阵中的元素为0或1,表示是否可以映射到相应桶中,举例来说:


字符串1字符串2字符串3字符串4
桶10111
桶21001
桶30000
桶41010
桶50101

矩阵中为1指对应列字符串的shingle集合有元素可以映射到对应桶, 为0代表没有无素映射到对应桶

由《大数据互联网大规模数据挖掘与分布式处理》一书可以得知字符串之间本身的相似度可以用它们映射到的桶相间的相似度来度量,如字符串1和字符串2的相似度可以用(0 1 0 1 0)及(1 0 0 0 1)的相似度来进行表示

【排列转换】

但shingle集合一般都非常大,即使将每个shingle都哈希到4个字节(即上表中的桶),很可能也不能把字符串的shingle集合全部放入内存中,那我们有什么 办法可以避免大数据量呢?试想我们将该特征矩阵映射到更小维度、规模更小的签名,用签名来代替特征矩阵,岂不是更好? 

为了对特征矩阵每列所表示的集合进行最小哈希计算,首先选择行的一个排列转换。任意一列的最小哈希值是在排列转换后的行排列次序下第一个列值为1的行的行号,仍然举例来说,我们把以上表中的桶顺序打乱


字符串1字符串2字符串3字符串4
桶21001
桶30000
桶10111
桶41010

5
0101

对于字符串1,其在第一行就已经可以遇到到桶2,那就把字符串1的哈希签名h设为桶2对应的hash值,即h(字符串1)=桶2 hash; 同理,h(字符串2)=桶1 hash; h(字符串3)=桶1 hash; h(字符串4)=桶2 hash;

【最小哈希签名矩阵的计算】

假如我们选择n个排列转换用于以上特征矩阵的处理,对于特征矩阵的列,分别调用这些排列转换所决定的最小哈希函数h1, h2...., hn, 就可以构建特征矩阵的最小哈希签名矩阵

假设SIG为最终得到的最小哈希签名矩阵,SIG(i, c)为签名矩阵中第i个哈希函数在第c列上的元素,刚开始时,矩阵元素设为无穷大。然后对于每一行r, 进行如下处理

(1). 计算h1(r), h2(r), .... hn(r)

(2). 对每一列c进行如下处理

   (a) 如果特征矩阵中第c列第r行为0, 什么也不做

   (b) 如果特征矩阵中第c列第r行为1,将SIG(i, c)设为原来的SIG(i, c)和hi(r)的最小值

为了简便计算,我们可以这样做,对于特征矩阵中每一列,我们集中该列中所有为1的行,对这些行应用哈希函数hi,取最小的哈希值,即可得到哈希函数hi对应的该列的签名,应用所有哈希函数,即可得到该列的签名向量。

最后,得到n行的签名矩阵,这比特征矩阵,远小了很多。

到这时,两个字符串的相似度的计算,又可转换成为对应的签名向量的相似度计算,如何度量向量的相似度呢,我们采用jaccard相似度

【jaccard相似度】

jaccard相似度用于计算两个集合之间的相似情况,也就是两个集合的交集与并集大小之间的比率

利用jaccard相似度,我们可以计算出字符串对应的签名向量的相似度,但如果字符串的数量太多,两两比较签名向量,也是很耗时的工作,实际中我们往往只需要得到那些最相似或者相似度大于某一阀值的字符串对,如果我们能首先将这些候选的字符串对找出来,再运用jaccard相似度,岂不是可以极大地减少计算量?

【行条化策略】

很显然,如果两个字符串相似,那么它们对应的签名向量应该也相似,在局部某个范围内极有可能相同, 相同,如果采用哈希的话,就可以映射到同一个桶。

设想我们对签名矩阵划分若干个行条,每一个行条里有数列,如果两个字符串相似,那猜测肯定在某个行条里,这两个字符串对应的签名向量应该相等,它们会映射到同一个桶里。

对每一个行条,我们设置一个大桶,对行条中的每一列计算其hash值,相同hash值的列会映射到同一个hash桶。在hash桶里的列,就组成了候选对。

对最后得到的候选对再计算jaccard相似度

【需要注意的问题】

1. 最小哈希函数族是性能的关键,哈希函数之间一定要独立,不出现一个哈希函数在同样的参数条件下,都比另一个哈希函数大或者小的情况,最好是乱七八糟,毫不相干

2. 最小哈希函数映射到的value范围不宜过小,太小了容易产生冲突

3.行条化采用的哈希函数映射到的Value范围也不宜过小,太小了同样容易冲突,后期要查询的候选对太多会影响速度

4. 注意大素数的应用,构造hash函数,大素数相当有用

注:原理及部分表述取自《大数据互联网大规模数据挖掘与分布式处理》第三

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
本课程适合具有一定深度学习基础,希望发展为深度学习之计算机视觉方向的算法工程师和研发人员的同学们。基于深度学习的计算机视觉是目前人工智能最活跃的领域,应用非常广泛,如人脸识别和无人驾驶中的机器视觉等。该领域的发展日新月异,网络模型和算法层出不穷。如何快速入门并达到可以从事研发的高度对新手和中级水平的学生而言面临不少的挑战。精心准备的本课程希望帮助大家尽快掌握基于深度学习的计算机视觉的基本原理、核心算法和当前的领先技术,从而有望成为深度学习之计算机视觉方向的算法工程师和研发人员。本课程系统全面地讲述基于深度学习的计算机视觉技术的原理并进行项目实践。课程涵盖计算机视觉的七大任务,包括图像分类、目标检测、图像分割(语义分割、实例分割、全景分割)、人脸识别、图像描述、图像检索、图像生成(利用生成对抗网络)。本课程注重原理和实践相结合,逐篇深入解读经典和前沿论文70余篇,图文并茂破译算法难点, 使用思维导图梳理技术要点。项目实践使用Keras框架(后端为Tensorflow),学员可快速上手。通过本课程的学习,学员可把握基于深度学习的计算机视觉的技术发展脉络,掌握相关技术原理和算法,有助于开展该领域的研究与开发实战工作。另外,深度学习之计算机视觉方向的知识结构及学习建议请参见本人CSDN博客。本课程提供课程资料的课件PPT(pdf格式)和项目实践代码,方便学员学习和复习。本课程分为上下两部分,其中上部包含课程的前五章(课程介绍、深度学习基础、图像分类、目标检测、图像分割),下部包含课程的后四章(人脸识别、图像描述、图像检索、图像生成)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值