1. 程式人生 > >海量資料相似度計算之simhash和海明距離

海量資料相似度計算之simhash和海明距離

通過 採集系統 我們採集了大量文字資料,但是文字中有很多重複資料影響我們對於結果的分析。分析前我們需要對這些資料去除重複,如何選擇和設計文字的去重演算法?常見的有餘弦夾角演算法、歐式距離、Jaccard相似度、最長公共子串、編輯距離等。這些演算法對於待比較的文字資料不多時還比較好用,如果我們的爬蟲每天採集的資料以千萬計算,我們如何對於這些海量千萬級的資料進行高效的合併去重。最簡單的做法是拿著待比較的文字和資料庫中所有的文字比較一遍如果是重複的資料就標示為重複。看起來很簡單,我們來做個測試,就拿最簡單的兩個資料使用Apache提供的 Levenshtein for 迴圈100w次計算這兩個資料的相似度。程式碼結果如下:

            String s1 = "你媽媽喊你回家吃飯哦,回家羅回家羅" ;
            String s2 = "你媽媽叫你回家吃飯啦,回家羅回家羅" ;

            long t1 = System.currentTimeMillis();

            for (int i = 0; i < 1000000; i++) {
                   int dis = StringUtils .getLevenshteinDistance(s1, s2);
            }

            long t2 = System
.currentTimeMillis();

            Systemout .println(" 耗費時間: " + (t2 - t1) + "  ms ");

耗費時間: 4266 ms

大跌眼鏡,居然計算耗費4秒。假設我們一天需要比較100w次,光是比較100w次的資料是否重複就需要4s,就算4s一個文件,單執行緒一分鐘才處理15個文件,一個小時才900個,一天也才21600個文件,這個數字和一天100w相差甚遠,需要多少機器和資源才能解決。

為此我們需要一種應對於海量資料場景的去重方案,經過研究發現有種叫 local sensitive hash 區域性敏感雜湊 的東西,據說這玩意可以把文件降維到hash數字,數字兩兩計算運算量要小很多。查詢很多文件後看到google對於網頁去重使用的是simhash,他們每天需要處理的文件在億級別,大大超過了我們現在文件的水平。既然老大哥也有類似的應用,我們也趕緊嘗試下。simhash是由 Charikar 在2002年提出來的,參考 

《Similarity estimation techniques from rounding algorithms》 。 介紹下這個演算法主要原理,為了便於理解儘量不使用數學公式,分為這幾步:

  • 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計算過程圖

大家可能會有疑問,經過這麼多步驟搞這麼麻煩,不就是為了得到個 0 1 字串嗎?我直接把這個文字作為字串輸入,用hash函式生成 0 1 值更簡單。其實不是這樣的,傳統hash函式解決的是生成唯一值,比如 md5、hashmap等。md5是用於生成唯一簽名串,只要稍微多加一個字元md5的兩個數字看起來相差甚遠;hashmap也是用於鍵值對查詢,便於快速插入和查詢的資料結構。不過我們主要解決的是文字相似度計算,要比較的是兩個文章是否相識,當然我們降維生成了hashcode也是用於這個目的。看到這裡估計大家就明白了,我們使用的simhash就算把文章中的字串變成 01 串也還是可以用於計算相似度的,而傳統的hashcode卻不行。我們可以來做個測試,兩個相差只有一個字元的文字串,“你媽媽喊你回家吃飯哦,回家羅回家羅” 和 “你媽媽叫你回家吃飯啦,回家羅回家羅”。

通過simhash計算結果為:

1000010010101101111111100000101011010001001111100001001011001011

1000010010101101011111100000101011010001001111100001101010001011

通過 hashcode計算為:

1111111111111111111111111111111110001000001100110100111011011110

1010010001111111110010110011101

大家可以看得出來,相似的文字只有部分 01 串變化了,而普通的hashcode卻不能做到,這個就是區域性敏感雜湊的魅力。目前Broder提出的shingling演算法和Charikar的simhash演算法應該算是業界公認比較好的演算法。在simhash的發明人Charikar的論文中並沒有給出具體的simhash演算法和證明,“量子圖靈”得出的證明simhash是由隨機超平面hash演算法演變而來的

現在通過這樣的轉換,我們把庫裡的文字都轉換為simhash 程式碼,並轉換為long型別儲存,空間大大減少。現在我們雖然解決了空間,但是如何計算兩個simhash的相似度呢?難道是比較兩個simhash的01有多少個不同嗎?對的,其實也就是這樣,我們通過海明距離(Hamming distance)就可以計算出兩個simhash到底相似不相似。兩個simhash對應二進位制(01串)取值不同的數量稱為這兩個simhash的海明距離。舉例如下: 10101 和 00110 從第一位開始依次有第一位、第四、第五位不同,則海明距離為3。對於二進位制字串的a和b,海明距離為等於在a XOR b運算結果中1的個數(普遍演算法)。

為了高效比較,我們預先載入了庫裡存在文字並轉換為simhash code 儲存在記憶體空間。來一條文字先轉換為 simhash code,然後和記憶體裡的simhash code 進行比較,測試100w次計算在100ms。速度大大提升。

未完待續:

1、目前速度提升了但是資料是不斷增量的,如果未來資料發展到一個小時100w,按現在一次100ms,一個執行緒處理一秒鐘 10次,一分鐘 60 * 10 次,一個小時 60*10 *60 次 = 36000次,一天 60*10*60*24 = 864000次。 我們目標是一天100w次,通過增加兩個執行緒就可以完成。但是如果要一個小時100w次呢?則需要增加30個執行緒和相應的硬體資源保證速度能夠達到,這樣成本也上去了。能否有更好的辦法,提高我們比較的效率?

2、通過大量測試,simhash用於比較大文字,比如500字以上效果都還蠻好,距離小於3的基本都是相似,誤判率也比較低。但是如果我們處理的是微博資訊,最多也就140個字,使用simhash的效果並不那麼理想。看如下圖,在距離為3時是一個比較折中的點,在距離為10時效果已經很差了,不過我們測試短文字很多看起來相似的距離確實為10。如果使用距離為3,短文字大量重複資訊不會被過濾,如果使用距離為10,長文字的錯誤率也非常高,如何解決?

simhash_hammingdistance

相關推薦

海量資料相似計算simhash距離

通過 採集系統 我們採集了大量文字資料,但是文字中有很多重複資料影響我們對於結果的分析。分析前我們需要對這些資料去除重複,如何選擇和設計文字的去重演算法?常見的有餘弦夾角演算法、歐式距離、Jaccard相似度、最長公共子串、編輯距離等。這些演算法對於待比較的文字資料不多時還比較好用,如果我們的爬蟲每天採集的

相似計算Jaccard係數

Jaccard相似係數 定義 給定兩個集合A,B,Jaccard 係數定義為A與B交集的大小與A與B並集的大小的比值,定義如下: 當集合A,B都為空時,J(A,B)定義為1。 與Jaccard 係數相關的指標叫做Jaccard 距離,用於描述集合之間的不相似度。Jaccard

相似計算餘弦相似

 一、定義及概念: 餘弦取值範圍為[-1,1]。求得兩個向量的夾角,並得出夾角對應的餘弦值,此餘弦值就可以用來表徵這兩個向量的相似性。夾角越小,趨近於0度,餘弦值越接近於1,它們的方向更加吻合,則越相似。當兩個向量的方向完全相反夾角餘弦取最小值-1。當餘弦值為0時,兩向量正交,夾角為9

文字相似計算餘弦定理

前言 餘弦相似度,又稱為餘弦相似性,是通過計算兩個向量的夾角餘弦值來評估他們的相似度。餘弦相似度將向量根據座標值,繪製到向量空間中。用向量空間中兩個向量夾角的餘弦值作為衡量兩個個體間差異的大小。餘弦值越接近1,就表明夾角越接近0度,也就是兩個向量越相似,反之越接近0就表示兩個向量相似度越低,這就叫"餘弦

相似演算法歐幾里得距離

在計算使用者相似度的過程中,歐幾里得距離是比較直觀,常見的一種相似度演算法。 根據兩使用者之間共同評價的Item為維度,建立一個多維的空間,那麼通過使用者對單一維度上的評價Score組成的座標系X(s1,s2,s3……,si)即可定位該使用者在這個多維度空間中的位置,那麼

推薦系統中常見的幾種相似計算方法其適用資料

在推薦系統中,相似度的計算是一個很重要的課題。而相似度的計算方法多種多樣,今天我們來把這些方法比較一下,也為以後做專案留個筆記。其實無論是基於user的cf還是基於item的cf,亦或是基於svd的推薦,相似度計算都是必不可少的一步,只不過cf中計算相似度是一箇中間步驟,而

Spark MLlib 大規模數據集的相似計算原理探索

tis afr 廣播 圖片 times 導致 coord 向量 校驗 無論是ICF基於物品的協同過濾、UCF基於用戶的協同過濾、基於內容的推薦,最基本的環節都是計算相似度。如果樣本特征維度很高或者<user, item, score>的維度很大,都會導致無法直

高效相似計算 LSH minHash simHash的學習

joey 周琦 本文首先介紹了局部敏感雜湊的概念與用處,然後介紹了常見的快速計算相似度、尋找近鄰的方法minHash, simHash 區域性敏感雜湊Locality-sensitive hashing (LSH) 定義 首先我們看看wiki上比較準確的英文

基於神經網路的文字相似計算【醫療大資料

任務描述 問句匹配是自然語言處理的最基本任務之一,是自動問答,聊天機器人,資訊檢索,機器翻譯等各種自然語言處理任務基礎。問句匹配的主要目的是判斷兩個問句之間的語義是否等價。判別標準主要根據主句(即提問者)所蘊含的意圖來判斷兩個語句是否等價,而不直接判斷兩個語句是否表達相

海量資料的儲存計算查詢模型

   海量資料(“Big Data”)是指那些足夠大的資料,以至於無法再使用傳統的方法進行處理。在過去,一直是Web搜尋引擎的建立者們首當其衝的面對這個問題。而今天,各種社交網路,移動應用以及各種感測器和科學領域每天建立著上PB的資料。 為了應對這種大規模資料處理的挑戰

用戶相似計算

計算 使用 val PE 相似度 ID turn 稀疏 code 協同過濾中用戶距離計算 # 構建共同的評分向量 def build_xy(user_id1, user_id2): bool_array = df.loc[user_id1].notnull() &

短文本相似計算

實用 好的 svm center 大量 network alt 詞匯 很難 短文本的相似度計算方法可以分為兩大類:基於深度學習的方法和基於非深度學習的方法。科研方面基本都是從深度學習方面入手,但個人覺得想把單語言的短文本相似度計算給做出花來比較難,相對而言基

1. 文本相似計算-文本向量化

就是 mage method 根據 計算 down youdao 比較 所有 1.前言 在自然語言處理過程中,經常會涉及到如何度量兩個文本之間的相似性,我們都知道文本是一種高維的語義空間,如何對其進行抽象分解,從而能夠站在數學角度去量化其相似性。 有了文本之間相似性的度量方

資料結構JAVA版佇列

一、涉及的內容大綱 二、簡單介紹棧、佇列和其他資料結構的不同 1 對於其他的資料結構而言,都適用與資料庫應用中作資料記錄。但是因為棧和佇列的生命週期比那些資料庫型別的資料結構要短,所以他們只是在程式的操作期間才會建立和執行,在完成任務之後就會被銷燬。所以棧和佇列更多的是用於構思演算法的

影象相似計算-kmeans聚類

關於影象相似度,主要包括顏色,亮度,紋理等的相似度,比較直觀的相似度匹配是直方圖匹配.直方圖匹配演算法簡單,但受亮度,噪聲等影響較大.另一種方法是提取影象特徵,基於特徵進行相似度計算,常見的有提取影象的sift特徵,再計算兩幅影象的sift特徵相似度.對於不同的影象型別,也可以採用不同的

協同過濾相似計算

   (1)傳統的傑卡德相似度計算公式如下,  其中A,B可以為不同使用者的購物品類,         當用戶量特別大的時候,導致計算複雜度比較高,因為直接進行了笛卡爾積運算,這時候可能沒有辦法進行運算。優化方法

餘弦相似計算[轉載]

轉自:https://www.cnblogs.com/dsgcBlogs/p/8619566.html 1.定義及計算公式   餘弦相似度用向量空間中兩個向量夾角的餘弦值作為衡量兩個個體間差異的大小。 餘弦值越接近1,就表明夾角越接近0度,也就是兩個向量越相似,這就叫"餘弦相似性"。

nlp中文字相似計算問題

文章的目的:文字相似度計算一直是nlp中常見的問題,本文的目標是總結並對比文字相似度計算方法。當然文字的相似度計算會有進一步的應用,比如文字的分類、聚類等。 文章結構:本文先介紹最直接的字面距離相似度度量,而後介紹語義主題層面的度量,最後介紹目前一些新的相似度計算方法。 一、字面距

資料結構與演算法 佇列廣度優先搜尋(BFS)

 佇列和 BFS 廣度優先搜尋(BFS)的一個常見應用是找出從根結點到目標結點的最短路徑。在本文中,我們提供了一個示例來解釋在 BFS 演算法中是如何逐步應用佇列的。 洞悉 1. 結點的處理順序是什麼? 在第一輪中,我們處理根結點。在第二輪中,我們處理根結點旁

句子相似計算的幾種方法

在做自然語言處理的過程中,我們經常會遇到需要找出相似語句的場景,或者找出句子的近似表達,這時候我們就需要把類似的句子歸到一起,這裡面就涉及到句子相似度計算的問題,那麼本節就來了解一下怎麼樣來用 Python 實現句子相似度的計算。 基本方法 句子相似度計算我們一共歸類