SimHash
google对于网页去重使用的是simhash,他们每天需要处理的文档在亿级别,大大超过了我们现在文档的水平。
该章节参考大牛博客《Similarity estimation techniques from rounding algorithms》),其通过hash算法让文本变为一系列由0-1构成的哈希值,并通过单词重要性加权获得simhash值。
simhash算法,将句子转化为hash码,去重。与一般hash算法,不同,simhash还可以比较文本的相似性。
为了便于理解尽量不使用数学公式,分为这几步:
1、分词,把需要判断文本分词形成这个文章的特征单词。最后形成去掉噪音词的单词序列并为每个词加上权重,我们假设权重分为5个级别(1~5)。比如:“ 美国“51区”雇员称内部有9架飞碟,曾看见灰色外星人 ” ==> 分词后为 “ 美国(4) 51区(5) 雇员(3) 称(1) 内部(2) 有(1) 9架(3) 飞碟(5) 曾(1) 看见(3) 灰色(4) 外星人(5)”,括号里是代表单词在整个句子里重要程度,数字越大越重要。
2、hash,通过hash算法把每个词变成hash值,比如“美国”通过hash算法计算为 100101,“51区”通过hash算法计算为 101011。这样我们的字符串就变成了一串串数字,还记得文章开头说过的吗,要把文章变为数字计算才能提高相似度计算性能,现在是降维过程进行时。
3、加权,通过 2步骤的hash生成结果,需要按照单词的权重形成加权数字串,比如“美国”的hash值为“100101”,通过加权计算为“4 -4 -4 4 -4 4”;“51区”的hash值为“101011”,通过加权计算为 “ 5 -5 5 -5 5 5”。
4、合并,把上面各个单词算出来的序列值累加,变成只有一个序列串。比如 “美国”的 “4 -4 -4 4 -4 4”,“51区”的 “ 5 -5 5 -5 5 5”, 把每一位进行累加, “4+5 -4+-5 -4+5 4+-5 -4+5 4+5” ==》 “9 -9 1 -1 1 9”。这里作为示例只算了两个单词的,真实计算需要把所有单词的序列串累加。
5、降维,把4步算出来的 “9 -9 1 -1 1 9” 变成 0 1 串,形成我们最终的simhash签名。 如果每一位大于0 记为 1,小于0 记为 0。最后算出结果为:“1 0 1 0 1 1”。
过大量测试,simhash用于比较大文本,比如500字以上效果都还蛮好,距离小于3的基本都是相似,误判率也比较低。但是如果我们处理的是微博信息,最多也就140个字,使用simhash的效果并不那么理想。
R中的jiebaR包可以方便处理simHash算法。
> library("jiebaR")
> simhasher = worker("simhash",topn=2)
> simhasher <= "江州市长江大桥参加了长江大桥的通车仪式"
$simhash
[1] "12882166450308878002"
$keyword
22.3853 8.69667
"长江大桥" "江州"
> simhasher <= "你妈妈喊你回家吃饭哦,回家罗回家罗"
$simhash
[1] "9184284471008831268"
$keyword
18.5768 6.55531
"回家" "妈妈"
> distance("江州市长江大桥参加了长江大桥的通车仪式" , "你妈妈喊你回家吃饭哦,回家罗回家罗" , simhasher)
$distance
[1] "30"
$lhs
22.3853 8.69667
"长江大桥" "江州"
$rhs
18.5768 6.55531
"回家" "妈妈"
LSH
那LSH究竟是如何做的呢?先一句话总结一下它的思想吧:它是用hash的方法把数据从原空间哈希到一个新的空间中,使得在原始空间的相似的数据,在新的空间中也相似的概率很大,而在原始空间的不相似的数据,在新的空间中相似的概率很小。
重点文章参考LSH详解文章,和这篇文章。
R语言中textreuse包可以实现LSH功能,具体参见文章。
区别
- simhash与Minhash的区别:
– simhash和minhash可以做到两个文档Hash之后仍然相似,但是simhash计算相似的方法是海明距离;而minhash计算距离的方式是Jaccard距离。
Hamming Distance(海明距离),Hamming Distance可以用来度量两个串(通常是二进制串)的距离,其定义为这两个二进制串对应的位有几个不一样,那么海明距离就是几,值越小越相似。例如x=1010,y=1011,那么x和y的海明距离就是1。又如x=1000,y=1111,那么x和y的海明距离就是3。
Jaccard Coefficient用来度量两个集合S1、S2的相似度,其值为(S1∩S2) / (S1∪S2), 例如S1={A,B,C},S2={B,D},则J(s1,s2)=1/4。
- 局部敏感哈希与simhash、minhash的区别。
– 局部敏感哈希可以在这两者基础上更快的找到相似、可匹配的对象,而且继承了simhash/minhash的优点,相似文档LSH计算之后还是保持相似的。