推薦演算法之Jaccard相似度與Consine相似度
0-- 前言:
對於個性化推薦來說,最核心、重要的演算法是相關性度量演算法。相關性從網站物件來分,可以針對商品、使用者、旺鋪、資訊、類目等等,從計算方式看可以分為文字相關性計算和行為相關性計算,具體的實現方法有很多種,最常用的方法有餘弦夾角(Cosine)方法、傑卡德(Jaccard)方法等。Google對新聞的相似性計算採用的是餘弦夾角,CBU的個性化推薦以往也主要採用此方法。從9月份開始,CBU個性化推薦團隊實現了傑卡德計算方法計算文字相關性和行為相關性,並且分別在線上做了演算法效果測試。本文基於測試結果,進行了對比及一些分析比較。
1、行為相關性的度量比較
通過前段時間在CBU1688.COM網站上的多個場景的線上測試,我們發現:在
將兩種方法的演算法結果,直接放到線上應用的三個應用場景,通過跟蹤不同演算法結果的實際的CTR(曝光點選率),詳細資料如下:
場景 | 推薦策略 | CTR(Jaccard VS Cosine) |
收藏offer成功後的提示頁面 | 相關商品的推薦普通商品 | 提升21% |
進貨單頁面的相關商品推薦 | 相關商品推薦普通商品 | 提升9% |
阿里巴巴每日焦點-熱賣tab | 猜你喜歡推薦P4P商品 | 提升12% |
簡要分析:
(1) 如果是完全以相關性推薦為主題的頁面,比如“收藏offer成功後的提示頁面”,Jaccard方法對應的CTR提升最大;
(2) 提升達到9%
(3) 提升達到12%的阿里巴巴每日焦點-熱賣,雖然整個頁面的主題就是推薦,但是畢竟推薦的是P4P商品,因為P4P商品覆蓋率不是很高,行為相關性粘稠度肯定不如普通商品,所以覆蓋率也沒有達到20%。
2、文字相關性的度量比較(cosine好一點點,但是Jaccard利於map/red計算)
同樣,在文字相關性計算中,分別使用Cosine和Jaccard,再將演算法結果在線上做測試。線上場景是1688的資訊畫報推薦。資料顯示,兩者的CTR基本一致。
不過,Jaccard方法在hadoop子序列與子字串
這個系列問題包含這麼幾種:最大子序列、最長遞增子序列、最長公共子串、最長公共子序列。
幾個子問題都可以用動態規劃的思路來求解。對於長度為i、j的兩個字串 ,使用m[i][j]矩陣來存放中間結果。
字串編輯距離
精確計算兩個字串的編輯距離,可以使用經典的動態規劃思路。
這裡來看下如何判斷字串A與B的編輯是否>N?這樣我們就可以比較兩個字串的相似度了。
可以構建一個編輯距離自動機(超酷演算法:Levenshtein自動機),把測試字元集合輸入自動機進行判斷。
可用於拼寫檢查,模糊匹配等場景。
向量相似度
使用TF-IDF計算出文字中詞的詞頻集合,把該集合作一個向量,比較不同集合向量線上性空間中的相似度。如:餘弦距離、歐氏距離、概率分佈距離(K-L距離)等。
SimHash
simhash演算法的主要思想是降維,將高維的特徵向量對映成一個f-bit的指紋(fingerprint),通過比較兩篇文章的f-bit指紋的Hamming Distance來確定文章是否重複或者高度近似。
主要分以下幾步:
1、抽取文字中的關鍵詞及其權重。
2、對關鍵詞取傳統hash,並與權重疊加,算出文字的fingerprint值。
3、計算出兩個文字之間fingerprint值的海明距離。
總之,對於行為相關性的度量,Jaccard一般效果更好;而對於文字相關性的度量,Cosine效果略好於Jaccard;但是,但是Jaccard利於map/red計算
補充:Jaccard相似度和廣義Jaccard相似度
1. 狹義Jaccard相似度,計算兩個集合之間的相似程度,元素的“取值”為0或1
對集合A和B,Jaccard相似度計算如下:
Jaccard(A, B)= |A intersectB| / |A union B|
相似度數值在[0, 1]之間,當A==B的時候,為1. 優缺點,就是元素的取值只能是0或者1,無法利用更豐富的資訊
由相似度,可以轉換成Jaccard距離:
Jaccard distance (A, B) = 1- Jaccard(A, B)
2. 廣義Jaccard相似度,元素的取值可以是實數。又稱為Tanimoto係數,用EJ來表示,計算方式如下:
EJ(A,B)=(A*B)/(||A||^2+||B||^2-A*B)
其中A、B分別表示為兩個向量,集合中每個元素表示為向量中的一個維度,在每個維度上,取值通常是[0, 1]之間的值,A*B表示向量乘積,||A||^2表示向量的模,即 ||A||^2 = sqrt (a1^2 + a2^2 + a3^2 +......)。
廣義Jaccard相似度計算公式中,如果把分母的A*B去掉,並將||A||^2+||B||^2替換為(||A||^2)*(||B||^2),就轉成了餘弦相似度(cosine similarity)。
EJ中每個分量的取值可以是實數,通常在[0, 1]之間。對於兩篇文件,分詞之後,形成兩個“詞語--詞頻向量”,詞語可以做為EJ的維度,如何將詞頻轉換為實數值。借鑑tf/idf的思路。對於每個詞語,有兩個頻度:1.在當前文件中的頻度;2. 在所有文件中的頻度。其中1相當於tf,與權重正相關;2相當於df,與權重反相關。
對於2,計算權重為
idf (w) = log (TotalWC/C(w))
C(w)是詞語w在所有文件中出現的次數,TotalWC是所有文件中所有詞的總詞頻。
對於1,權重就可以取詞頻本身 tf(w) = D(w),D(w)表示在當前文件中w出現的次數
具體計算的程式碼可以參考的Documents.cs中的“SimilitudeValueToDocumentUsingGeneralizedJaccardCoefficient”函式。
3. 其他擴充套件方法
EJ(A,B) = sum ( min(a1, b1) + min (a2, b2)... ) / sum ( max(a1, b1) +max (a2, b2).. )
即用向量中每個分量的的最小值和最大值來參與計算。
個人理解,這個可以做如下解釋。當集合A中的元素a1出現C(a1)次的時候,我們可以認為集合中的元素是允許重複存在的,即集合A中有C(a1)個元素;集合B也是這樣,有C(b1)個相同的元素,則A和B在這個元素上的交集就是min(a1, b1) ,並集就是max(a1,b1) ,這樣上述公式就是利用狹義Jaccard相似度計算的結果。