TedDunning在
《AccurateMethodsfortheStatisticsofSurpriseandCoincidence》中介紹了
Log−LikehoodRatio在文本計算中的基本使用。
LLR因爲實現簡單、有效並且具有大規模數據上的可擴展性,能夠被很好的使用到工業系統中。因此基於
LLR的相似度度量廣泛應用在推薦系統等多種應用當中。
在這篇Blog中,我們忽略
《AccurateMethodsfortheStatisticsofSurpriseandCoincidence》中對
LLR過多的冗餘描述,主要集中的去關注
LLR的計算方式和現有的一些簡單有效的代碼實現。
本篇博客的組織方式如下。在章節1中,以最簡單的方式討論了
Log−LikelihoodRatio相似度的計算方式,在章節2中討論了
Log−LikelihoodRatio的具體的代碼實現,以及一些可以現用的相似度計算工具。
1. LLR的計算方式
在計算兩個事件(例如推薦系統中的點擊行爲)的LLR值來做相似度衡量的時候,我們通過兩個事件的計數來計算事件之間的相似度。接下來我們以推薦系統中物品相似度的計算爲例來介紹LLR的計算方式。
有兩個物品分別爲物品i和物品j。對應事件計數的簡單形式化描述如下:
k11:表示同時瀏覽了物品i和物品j的用戶。
k12:表示瀏覽了物品i,但是沒有瀏覽物品j的用戶。
k21:表示瀏覽了物品j,但是沒有瀏覽物品i的用戶。
k22:表示沒有瀏覽物品i,並且沒有瀏覽物品j的用戶。
根據上述,我們可以得到如下的一個表格:
事件 |
瀏覽Itemi |
沒有瀏覽Itemi |
瀏覽Itemj |
k11 |
k21 |
沒有瀏覽Itemj |
k12 |
k22 |
Itemi和Itemj的LLR計算公式如下:
S=2×(Hm−Hc−Hr)
其中:
Hm表示上述矩陣的矩陣熵,總體的計算公式如下:
Hm=−(Nk11log(Nk11)+Nk12log(Nk12)+Nk21log(Nk21)+Nk22log(Nk22))
Hr表示每行相加計算得到的信息熵,相關的具體計算公式如下:
Hr=−(Nk11+k12log(Nk11+k12)+Nk21+k22log(Nk21+k22))
Hc表示矩陣的每一列相加計算得到的信息熵,相關的具體計算公式如下:
Hc=−(Nk11+k21log(Nk11+k21)+Nk21+k22log(Nk21+k22))
其中N=k11+k12+k21+k22
2. LLR的代碼實現
在Mahout的math庫中定義了LogLikelihood類,實現了LLR的計算,其中具體的計算代碼在下面給出。
- rowEntropy的計算方式如下
private static double xLogX(long x) {
return x == 0 ? 0.0 : x * Math.log(x);
}
private static double entropy(long a, long b) {
return xLogX(a + b) - xLogX(a) - xLogX(b);
}
其中a=k11+k12並且b=k21+k22,綜合得到
rowEntropy=(N×log(N)−(k11+k12)×log(k11+k12)−(k21+k22)×log(k21+k22))=−((k11+k12)×log(N)−(k11+k12)×log(k11+k12)+(k21+k22)×log(N)−(k21+k22)×log(k21+k22))=−((k11+k12)×(log(N)−log(k11+k12))+(k21+k22)×(log(N)−log(k21+k22)))=(k11+k12)×(logNk11+k12)+(k21+k22)×(logNk21+k22)=−Hr×N
- 同樣的colEntropy的計算方式如下:
colEntropy=(k11+k21)×(logNk11+k21)+(k12+k22)×(logNk12+k22)=−Hc×N
- matrixEntropy的計算方式
private static double entropy(long a, long b, long c, long d) {
return xLogX(a + b + c + d) - xLogX(a) - xLogX(b) - xLogX(c) - xLogX(d);
}
matrixEntropy=N×log(N)−k11log(k11)−k12log(k12)−k21log(k21)−k22log(k22)=−(k11×log(Nk11)+k12×log(Nk12)+k21×log(Nk21))+k21×log(Nk21))×N
public static double logLikelihoodRatio(long k11, long k12, long k21, long k22) {
Preconditions.checkArgument(k11 >= 0 && k12 >= 0 && k21 >= 0 && k22 >= 0);
double rowEntropy = entropy(k11 + k12, k21 + k22);
double columnEntropy = entropy(k11 + k21, k12 + k22);
double matrixEntropy = entropy(k11, k12, k21, k22);
if (rowEntropy + columnEntropy < matrixEntropy) {
return 0.0;
}
return 2.0 * (rowEntropy + columnEntropy - matrixEntropy);
}
S=2×(rowEntropy+colEntropy−matrixEntropy)=2×(−NHr−NHc+NHm)=N2(Hm−Hr−Hc)
在代碼實現裏面相似度的計算過程中把N約掉了,所以在mahout計算當中實際計算得到的值爲
S=N2(Hm−Hr−Hc)
3 相關疑問
問題 1: 在代碼的計算過程中,約掉分母N對整個結果有影響嘛?
問題 2: 在有些博客資料中稱Hr爲行熵,稱Hc爲列熵,並且計算公式不如下:
這種方式和我上面描述的計算方式等價嘛?那種更準確?
歡迎大家留言討論,如果有問題或者建議的地方希望大家能夠提出再覈對問題後我會在第一時間進行修正。
4 參考資料
【1】LLR (Log-Likelihood Ratio) used for recommendations
【2】Accurate Methods for the Statistics of Surprise and Coincidence
【3】Building a Correlated Cross-Occurrence (CCO) Recommenders with the Mahout CLI
【4】github · Mathout LogLikelihood Similarity
【5】Surprise and Coincidence
【6】loglikelihood ratio 相似度