1.示例引入
多個吃貨在某美團的某家飯館點餐,如下兩道菜:
可樂雞翅:

紅燒肉:

顧客吃過后,會有相關的星級評分。假設評分如下:
評分 可樂雞翅 紅燒肉
小明 4 5
小紅 4 3
小偉 2 3
小芳 3 ?
問題:請猜測一下小芳可能會給“紅燒肉”打多少分?
思路:把兩道菜的平均差值求出來,可樂雞翅減去紅燒肉的平均偏差:[(4-5)+(4-3)+(2-3)]/3=-0.333。一個新客戶比如小芳,只吃了可樂雞翅評分為3分,那么可以猜測她對紅燒肉的評分為:3-(-0.333)=3.333
這就是slope one 算法的基本思路,非常非常的簡單。
2.slope one 算法思想
Slope One 算法是由 Daniel Lemire 教授在 2005 年提出的一個Item-Based 的協同過濾推薦算法。和其它類似算法相比, 它的最大優點在於算法很簡單, 易於實現, 執行效率高, 同時推薦的准確性相對較高。
Slope One算法是基於不同物品之間的評分差的線性算法,預測用戶對物品評分的個性化算法。主要兩步:
Step1:計算物品之間的評分差的均值,記為物品間的評分偏差(兩物品同時被評分);
Step2:根據物品間的評分偏差和用戶的歷史評分,預測用戶對未評分的物品的評分。
Step3:將預測評分排序,取topN對應的物品推薦給用戶。
舉例:
假設有100個人對物品A和物品B打分了,R(AB)表示這100個人對A和B打分的平均偏差;有1000個人對物品B和物品C打分了, R(CB)表示這1000個人對C和B打分的平均偏差;
3.python實現
def loadData(): items={'A':{1:5,2:3}, 'B':{1:3,2:4,3:2}, 'C':{1:2,3:5}} users={1:{'A':5,'B':3,'C':2}, 2:{'A':3,'B':4}, 3:{'B':2,'C':5}} return items,users
3.2物品間評分偏差
#***計算物品之間的評分差
#items:從物品角度,考慮評分
#users:從用戶角度,考慮評分
for itemId in items: for otherItemId in items: average=0.0 #物品間的評分偏差均值 userRatingPairCount=0 #兩件物品均評過分的用戶數 if itemId!=otherItemId: #若無不同的物品項 for userId in users: #遍歷用戶-物品評分數 userRatings=users[userId] #每條數據為用戶對物品的評分 #當前物品項在用戶的評分數據中,且用戶也對其他物品由評分 if itemId in userRatings and otherItemId in userRatings: #兩件物品均評過分的用戶數加1 userRatingPairCount+=1 #評分偏差為每項當前物品評分-其他物品評分求和 average+=(userRatings[otherItemId]-userRatings[itemId]) averages[(itemId,otherItemId)]=average/userRatingPairCount
3.3預估評分
#***預測評分
#users:用戶對物品的評分數據
#items:物品由哪些用戶評分的數據
#averages:計算的評分偏差
#targetUserId:被推薦的用戶
#targetItemId:被推薦的物品
def suggestedRating(users,items,averages,targetUserId,targetItemId): runningRatingCount=0 #預測評分的分母 weightedRatingTotal=0.0 #分子 for i in users[targetUserId]: #物品i和物品targetItemId共同評分的用戶數 ratingCount=userWhoRatedBoth(users,i,targetItemId) #分子 weightedRatingTotal+=(users[targetUserId][i]-averages[(targetItemId,i)])\ *ratingCount #分母 runningRatingCount+=ratingCount #返回預測評分 return weightedRatingTotal/runningRatingCount
統計兩物品共同評分的用戶數
# 物品itemId1與itemId2共同有多少用戶評分
def userWhoRatedBoth(users,itemId1,itemId2): count=0 #用戶-物品評分數據 for userId in users: #用戶對物品itemId1與itemId2都評過分則計數加1 if itemId1 in users[userId] and itemId2 in users[userId]: count+=1 return count
3.4測試結果:
if __name__=='__main__': items,users=loadData() averages={} #計算物品之間的評分差 buildAverageDiffs(items,users,averages) #預測評分:用戶2對物品C的評分 predictRating=suggestedRating(users,items,averages,2,'C') print 'Guess the user will rate the score :',predictRating
結果:用戶2對物品C的預測分值為
Guess the user will rate the score : 3.33333333333
4.slopeOne使用場景
該算法適用於物品更新不頻繁,數量相對較穩定並且物品數目明顯小於用戶數的場景。依賴用戶的用戶行為日志和物品偏好的相關內容。
優點:
1.算法簡單,易於實現,執行效率高;
2.可以發現用戶潛在的興趣愛好;
缺點:
依賴用戶行為,存在冷啟動問題和稀疏性問題。
