分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
simhash的背景
simhash广泛的用于搜索领域中,也许在面试时你会经常遇到这样的问题,如果对抓取的网页进行排重,如何对搜索结果进行排重等等。随着信息膨胀时代的来临,算法也在不断的精进,相似算法同样在不断的发展,接触过lucene的同学想必都会了解相似夹角的概念,那就是一种相似算法,通过计算两个向量的余弦值来判断两个向量的相似性,但这种方式需要两两进行计算向量的余弦夹角,计算量比较大,不能用于实时计算或是大数据量的运算,比如在做搜索结果的相似性排重时,需要对上千条结果进行相似性排重,如果两两比对的话,最少也需要进行上千次的向量余弦值计算,其中涉及到分词,特征提取,余弦值计算等,很难满足性能的需要。jaccard相似度也是一种相似算法,它的计算方式比较直观,就是sim(x,y)= (x∩y) / (x∪y),例如:
若 S={a, d}
,T={a, c, d}
则 Jaccard_Sim(S, T) = |{a, d}|/|{a, c, d}| = 2/3
也是一种需要实时生成特征向量并且进行计算的算法。
那么
什么是simhash呢?
Simhash 是一种用单个哈希函数得到文档最小哈希签名的方法,过程为:
- 将一个 f 维的向量 V 初始化为0;f 位的二进制数 S 初始化为0;
- 对每一个特征:用传统的 hash 算法对该特征产生一个 f 位的签名 b。对 i=1 到 f:
- 如果 b 的第 i 位为1,则 V 的第 i 个元素加上该特征的权重;
- 否则,V 的第 i 个元素减去该特征的权重。
- 如果 V 的第 i 个元素大于0,则 S 的第 i 位为1,否则为0;
- 输出 S 作为签名。
对两篇文档,它们的 Simhash 值之间不同位的个数越少(即海明距离越小),它们之间的 Jaccard 相似度越高。
什么是局部敏感性哈希呢?
局部敏感哈希(LSH)是指这样的哈希方法:对两篇文档,如果它们相似,则它们的哈希值有较高的概率是相同的。有了文档的最小哈希签名,我们就能实现这种哈希方法。直观的做法是,将包含 b×r 个值最小哈希签名分为 b 等份,每份 r 个,对两个文档,定义 P 为两个文档至少含有1个相同份的概率,显然,文档间的Jaccard 相似度越高,哈希签名具有相同值的位数就越多,概率 P 就越大。
如何计算simhash呢?
simhash从内部看就是特征向量hash叠加的效果,并且具有局部敏感性,普通的hash算法针对差别不大的字符串会产生截然不同的hash值,但是simhash计算出来的hash值的海明距离会很相近。
具体的算法是将doc分解为特征向量,具体可以通过分词,也可以通过bigram实现,并且可以赋予一定的权重,针对每个向量使用统一的hash函数进行hash,针对每个特征的hash值的每一位,如果是1就对simhash值的对应位加1,当然也可以使用权重,如果对应位是0,则simhash的对应位减1,对最后的simhash值如果该位大于0则该位置1,如果该位小于0,则该位置0,最后就可以得到一个真正的simhash值。
过程可以参考下面:
汉明距离的计算代码如下:
- /*************************************************************************
- > File Name: hamdistance.c
- > Author: desionwang
- > Mail: wdxin1322@qq.com
- > Created Time: Wed 20 Nov 2013 02:02:13 PM CST
- ************************************************************************/
- #include<stdio.h>
- #include<stdint.h>
- int hamdistance(uint64_t sim1, uint64_t sim2){
- uint64_t xor_val = sim1 ^ sim2;
- int distance = 0;
- while(xor_val > 0){
- xor_val = xor_val & (xor_val - 1);
- distance++;
- }
- return distance;
- }
- int main(int argc, char *argv[]){
- uint64_t sim1 = 851459198;
- uint64_t sim2 = 847263864;
- int dis = hamdistance(sim1, sim2);
- printf("hamdistance of %lu and %lu is %d", sim1, sim2, dis);
- }
输出为:
hamdistance of 851459198 and 847263864 is 4
simhash的好处?
simhash离线计算指纹,方便了大规模数据比较时的消耗,不需要在计算时提取特征进行计算,hash值的可比性很强,只需要比较汉明距离,
方便了从海量数据中发掘相似项的实现,试想一个新文档同百万级甚至千万级数据做相似夹角的情况。simhash大大减少了相似项排重的复杂度。
如何应用simhash呢,具体的应用场景?
simhash有两个比较典型的应用,一个是网页抓取的排重,一个是检索时相似doc 的排重
前者是在大集合中寻找是否具有相似项,后者是对检索的集合进行滤重。
检索集中发现