協同過濾——隱式評級及基于物品的過濾
第一篇講的是顯示評級,是用戶確實打了的分,是過于理想的情況,現實中有很多不可控因素,有時用戶打分口是心非,有時懶得打分,有時初次評價之后即使后來發現當初打分打低了,有時僅僅是與個人聯系緊密的獨家偏好……
隱式評級,不要求用戶打分,而是觀察用戶的行為,可觀察的維度很多:
上述講的都是基于用戶的過濾,也叫基于內存的過濾,意思是要進行大量的計算,尤其當用戶很多的時候,對計算機內存要求比較高。現在亞馬遜有上百萬用戶,計算擴展性是一個問題,更重要的是有時找不到最近鄰。基于以上原因,最好采用基于物品的過濾。也叫基于模型的過濾。
1. 基于物品的過濾
利用物品之間的相似度進行推薦。從所有商品中找出與用戶購買過的商品最相似的商品推薦給用戶。
2. 計算物品之間的相似度,使用調整后的余弦相似度
和第一篇的余弦相似度類似,為了消除分數貶值,調整后的余弦相似度與余弦相似度公式有一點不同,用戶U給物品i的打分減去用戶U對所有物品打分的平均值。因為是基于物品的推薦,所以如果使用之前的余弦相似度,就要用物品的每一列屬性中的每一項減去這一列的平均值,顯然與實際情況不符。
U 表示所有同時對i和j 進行過評級的用戶的集合。
這個公式計算的是** 物品 i 和物品 j 之間的相似度 **。這個公式的直觀解釋是:
要計算 物品i 和 物品j 之間的相似度
1. 找出同時對物品i和物品j打分的用戶
2. 計算每個用戶對自己購買的書打分的平均值 R
3. 按照公式計算
Python 代碼:
# -*- coding: utf-8 -*-
from math import sqrt
users3 = {"David": {"Imagine Dragons": 3, "Daft Punk": 5,
"Lorde": 4, "Fall Out Boy": 1},
"Matt": {"Imagine Dragons": 3, "Daft Punk": 4,
"Lorde": 4, "Fall Out Boy": 1},
"Ben": {"Kacey Musgraves": 4, "Imagine Dragons": 3,
"Lorde": 3, "Fall Out Boy": 1},
"Chris": {"Kacey Musgraves": 4, "Imagine Dragons": 4,
"Daft Punk": 4, "Lorde": 3, "Fall Out Boy": 1},
"Tori": {"Kacey Musgraves": 5, "Imagine Dragons": 4,
"Daft Punk": 5, "Fall Out Boy": 3}}
def computeSimilarity(band1, band2, userRatings):
averages = {}
for (key, ratings) in userRatings.items():
averages[key] = (float(sum(ratings.values())) /len(ratings.values()))
num = 0 # 分子
dem1 = 0 # 分母的第一部分
dem2 = 0
for (user, ratings) in userRatings.items():
if band1 in ratings and band2 in ratings:
avg = averages[user]
num += (ratings[band1] - avg) * (ratings[band2] - avg)
dem1 += (ratings[band1] - avg) ** 2
dem2 += (ratings[band2] - avg) ** 2
return num / (sqrt(dem1) * sqrt(dem2))
print computeSimilarity('Kacey Musgraves', 'Lorde', users3)
print computeSimilarity('Imagine Dragons', 'Lorde', users3)
print computeSimilarity('Daft Punk', 'Lorde', users3)
得到的結果填入表中:
3. 利用相似度矩陣進行預測
公式如下圖,p(u,i) 指的是用戶u將對物品i的評分的預測值(即用戶u對物品i的喜歡程度)。
N 是用戶u的所有評級物品中每個和物品i得分相似的物品。存在在相似度矩陣中。R(u,N) 是u給N的評分。S(i,N)是i和N的相似度。
4. 對用戶的打分結果歸一化
類似皮爾遜相關系數對結果做處理的原因,讓用戶對物品的評分結果值位于-1到1之間。
公式如下圖所示,NR(u,N) 是歸一化的結果,即用戶u對物品N打分的結果的處理。MinR表示評級范圍(比如1~5)中的最小值,MaxR表示最大值。
計算舉例,很簡單,比如某人的對某本書的打分是2分,歸一化后結果如下:
將第3點里面的預測用戶打分的公式更新為:
最后用歸一化的結果反推真實的分數公式:
就得到了預測的打分。
5. Slope One 算法
據說 Slope One 算法簡潔,易實現,來自 Daniel Lemire 和 Anna Machlachlan 的論文 ↓
Slope One Predictors for Online Rating-Based Collaborative
Filtering” by Daniel Lemire and Anna Machlachlan (http://www.daniel-lemire.com/fr/abstracts/SDM2005.html).
1. 問題描述
假設 Amy 給 PSY 打了 3分,給 WH 打了 4 分,Ben 給 PSY 打了 4 分,想預測 Ben 給 WH 打多少分?
描述如圖:
我們直觀進行預測,依據只能是 Amy 對 WH 的打分,相對而言,Ben 對 WH 的打分可能是 5 分。
Slope One 算法將問題看成兩部分:
第一部分: 計算所有物品對的偏差
第二部分: 利用偏差進行預測
2. 計算偏差
數據如下:
計算物品i 到 物品j 的平均偏差的公式:
其中,card(S) 是S集合中的元素個數,X 是整個評分集合。
card(S(X))即為所有同時對i和j評分的用戶個數。
舉個例子:
3. 利用加權的 Slope One 算法進行預測
公式如下:
該公式最終得出的結果是用戶對某物品的打分的預測值。其中,c(i,j) 表示所有同時對物品i和物品j打分的用戶數。
公式看似復雜,計算卻不復雜,舉個例子:
給出了Ben的評分表及物品之間的偏差表:
6. 加權 Slope One : 推薦模塊
通過 Slope One 算法得出用戶對某一商品的預測值,如何對用戶推薦呢?
(整個的利用 Slope One 算法推薦商品的代碼在這里)
- 先從一大堆商品中找出用戶沒有打過分的商品,并且用戶評過分的商品與未評過分的商品之間的偏差存在。
- 用 Python 程序計算所有用戶對未評過分的商品的可能評分。
- 根據預測分數由高到低展示出來(可只展示前幾項),排名越靠前,推薦給用戶的可能性越高。