日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

simhash算法

發(fā)布時(shí)間:2024/3/26 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 simhash算法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

simhash算法

方法介紹

背景

如果某一天,面試官問你如何設(shè)計(jì)一個(gè)比較兩篇文章相似度的算法?可能你會(huì)回答幾個(gè)比較傳統(tǒng)點(diǎn)的思路:

  • 一種方案是先將兩篇文章分別進(jìn)行分詞,得到一系列特征向量,然后計(jì)算特征向量之間的距離(可以計(jì)算它們之間的歐氏距離、海明距離或者夾角余弦等等),從而通過距離的大小來(lái)判斷兩篇文章的相似度。
  • 另外一種方案是傳統(tǒng)hash,我們考慮為每一個(gè)web文檔通過hash的方式生成一個(gè)指紋(finger print)。

下面,我們來(lái)分析下這兩種方法。

  • 采取第一種方法,若是只比較兩篇文章的相似性還好,但如果是海量數(shù)據(jù)呢,有著數(shù)以百萬(wàn)甚至億萬(wàn)的網(wǎng)頁(yè),要求你計(jì)算這些網(wǎng)頁(yè)的相似度。你還會(huì)去計(jì)算任意兩個(gè)網(wǎng)頁(yè)之間的距離或夾角余弦么?想必你不會(huì)了。
  • 而第二種方案中所說(shuō)的傳統(tǒng)加密方式md5,其設(shè)計(jì)的目的是為了讓整個(gè)分布盡可能地均勻,但如果輸入內(nèi)容一旦出現(xiàn)哪怕輕微的變化,hash值就會(huì)發(fā)生很大的變化。

舉個(gè)例子,我們假設(shè)有以下三段文本:

  • the cat sat on the mat
  • the cat sat on a mat
  • we all scream for ice cream

使用傳統(tǒng)hash可能會(huì)得到如下的結(jié)果:

  • irb(main):006:0> p1 = 'the cat sat on the mat'
    • irb(main):007:0> p1.hash => 415542861
  • irb(main):005:0> p2 = 'the cat sat on a mat'
    • irb(main):007:0> p2.hash => 668720516
  • irb(main):007:0> p3 = 'we all scream for ice cream'
    • irb(main):007:0> p3.hash => 767429688 "

可理想當(dāng)中的hash函數(shù),需要對(duì)幾乎相同的輸入內(nèi)容,產(chǎn)生相同或者相近的hash值,換言之,hash值的相似程度要能直接反映輸入內(nèi)容的相似程度,故md5等傳統(tǒng)hash方法也無(wú)法滿足我們的需求。

出世

車到山前必有路,來(lái)自于GoogleMoses Charikar發(fā)表的一篇論文“detecting near-duplicates for web crawling”中提出了simhash算法,專門用來(lái)解決億萬(wàn)級(jí)別的網(wǎng)頁(yè)的去重任務(wù)。

simhash作為locality sensitive hash(局部敏感哈希)的一種:

  • 其主要思想是降維,將高維的特征向量映射成低維的特征向量,通過兩個(gè)向量的Hamming Distance來(lái)確定文章是否重復(fù)或者高度近似。
    • 其中,Hamming Distance,又稱漢明距離,在信息論中,兩個(gè)等長(zhǎng)字符串之間的漢明距離是兩個(gè)字符串對(duì)應(yīng)位置的不同字符的個(gè)數(shù)。也就是說(shuō),它就是將一個(gè)字符串變換成另外一個(gè)字符串所需要替換的字符個(gè)數(shù)。例如:1011101 與 1001001 之間的漢明距離是 2。至于我們常說(shuō)的字符串編輯距離則是一般形式的漢明距離。

如此,通過比較多個(gè)文檔的simHash值的海明距離,可以獲取它們的相似度。

流程

simhash算法分為5個(gè)步驟:分詞、hash、加權(quán)、合并、降維,具體過程如下所述:

  • 分詞
    • 給定一段語(yǔ)句,進(jìn)行分詞,得到有效的特征向量,然后為每一個(gè)特征向量設(shè)置1-5等5個(gè)級(jí)別的權(quán)重(如果是給定一個(gè)文本,那么特征向量可以是文本中的詞,其權(quán)重可以是這個(gè)詞出現(xiàn)的次數(shù))。例如給定一段語(yǔ)句:“CSDN博客結(jié)構(gòu)之法算法之道的作者July”,分詞后為:“CSDN 博客 結(jié)構(gòu) 之 法 算法 之 道 的 作者 July”,然后為每個(gè)特征向量賦予權(quán)值:CSDN(4) 博客(5) 結(jié)構(gòu)(3) 之(1) 法(2) 算法(3) 之(1) 道(2) 的(1) 作者(5) July(5),其中括號(hào)里的數(shù)字代表這個(gè)單詞在整條語(yǔ)句中的重要程度,數(shù)字越大代表越重要。
  • hash
    • 通過hash函數(shù)計(jì)算各個(gè)特征向量的hash值,hash值為二進(jìn)制數(shù)01組成的n-bit簽名。比如“CSDN”的hash值Hash(CSDN)為100101,“博客”的hash值Hash(博客)為“101011”。就這樣,字符串就變成了一系列數(shù)字。
  • 加權(quán)
    • 在hash值的基礎(chǔ)上,給所有特征向量進(jìn)行加權(quán),即W = Hash * weight,且遇到1則hash值和權(quán)值正相乘,遇到0則hash值和權(quán)值負(fù)相乘。例如給“CSDN”的hash值“100101”加權(quán)得到:W(CSDN) = 100101*4 = 4 -4 -4 4 -4 4,給“博客”的hash值“101011”加權(quán)得到:W(博客)=101011*5 = 5 -5 5 -5 5 5,其余特征向量類似此般操作。
  • 合并
    • 將上述各個(gè)特征向量的加權(quán)結(jié)果累加,變成只有一個(gè)序列串。拿前兩個(gè)特征向量舉例,例如“CSDN”的“4 -4 -4 4 -4 4”和“博客”的“5 -5 5 -5 5 5”進(jìn)行累加,得到“4+5 -4+-5 -4+5 4+-5 -4+5 4+5”,得到“9 -9 1 -1 1”。
  • 降維
    • 對(duì)于n-bit簽名的累加結(jié)果,如果大于0則置1,否則置0,從而得到該語(yǔ)句的simhash值,最后我們便可以根據(jù)不同語(yǔ)句simhash的海明距離來(lái)判斷它們的相似度。例如把上面計(jì)算出來(lái)的“9 -9 1 -1 1 9”降維(某位大于0記為1,小于0記為0),得到的01串為:“1 0 1 0 1 1”,從而形成它們的simhash簽名。

其流程如下圖所示:?

應(yīng)用

  • 每篇文檔得到SimHash簽名值后,接著計(jì)算兩個(gè)簽名的海明距離即可。根據(jù)經(jīng)驗(yàn)值,對(duì)64位的 SimHash值,海明距離在3以內(nèi)的可認(rèn)為相似度比較高。
    • 海明距離的求法:異或時(shí),只有在兩個(gè)比較的位不同時(shí)其結(jié)果是1 ,否則結(jié)果為0,兩個(gè)二進(jìn)制“異或”后得到1的個(gè)數(shù)即為海明距離的大小。

舉個(gè)例子,上面我們計(jì)算到的“CSDN博客”的simhash簽名值為“1 0 1 0 1 1”,假定我們計(jì)算出另外一個(gè)短語(yǔ)的簽名值為“1 0 1 0 0 0”,那么根據(jù)異或規(guī)則,我們可以計(jì)算出這兩個(gè)簽名的海明距離為2,從而判定這兩個(gè)短語(yǔ)的相似度是比較高的。

換言之,現(xiàn)在問題轉(zhuǎn)換為:對(duì)于64位的SimHash值,我們只要找到海明距離在3以內(nèi)的所有簽名,即可找出所有相似的短語(yǔ)。

但關(guān)鍵是,如何將其擴(kuò)展到海量數(shù)據(jù)呢?譬如如何在海量的樣本庫(kù)中查詢與其海明距離在3以內(nèi)的記錄呢?

  • 一種方案是查找待查詢文本的64位simhash code的所有3位以內(nèi)變化的組合
    • 大約需要四萬(wàn)多次的查詢。
  • 另一種方案是預(yù)生成庫(kù)中所有樣本simhash code的3位變化以內(nèi)的組合
    • 大約需要占據(jù)4萬(wàn)多倍的原始空間。

這兩種方案,要么時(shí)間復(fù)雜度高,要么空間復(fù)雜度復(fù)雜,能否有一種方案可以達(dá)到時(shí)空復(fù)雜度的絕佳平衡呢?答案是肯定的:

  • 我們可以把 64 位的二進(jìn)制simhash簽名均分成4塊,每塊16位。根據(jù)鴿巢原理(也稱抽屜原理),如果兩個(gè)簽名的海明距離在 3 以內(nèi),它們必有一塊完全相同。如下圖所示:?
  • 然后把分成的4 塊中的每一個(gè)塊分別作為前16位來(lái)進(jìn)行查找,建倒排索引。

具體如下圖所示:

如此,如果樣本庫(kù)中存有2^34(差不多10億)的simhash簽名,則每個(gè)table返回2^(34-16)=262144個(gè)候選結(jié)果,大大減少了海明距離的計(jì)算成本。

  • 假設(shè)數(shù)據(jù)是均勻分布,16位的數(shù)據(jù),產(chǎn)生的像限為2^16個(gè),則平均每個(gè)像限分布的文檔數(shù)則為2^34/2^16 = 2^(34-16)) ,四個(gè)塊返回的總結(jié)果數(shù)為 4* 262144 (大概 100 萬(wàn))。
    • 這樣,原本需要比較10億次,經(jīng)過索引后,大概只需要處理100萬(wàn)次。

(部分內(nèi)容及圖片參考自:http://grunt1223.iteye.com/blog/964564?,后續(xù)圖片會(huì)全部重畫)

來(lái)源:https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/06.03.md

總結(jié)

以上是生活随笔為你收集整理的simhash算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。