2_基于物品的協(xié)同過濾方法

1 直觀描述

基于物品的協(xié)同過濾方法,簡單來說就是:通過分析歷史數(shù)據(jù)發(fā)現(xiàn),很多人的購物清單里同時存在啤酒與尿布,那么,對于某一個購買了尿布的客戶,我們將啤酒推薦給他。這里我們可以再思考一個問題,就是將尿布推薦給買了啤酒的客戶是否合理呢?

2 基于物品協(xié)同過濾的步驟

⑴ 構建物品與物品的同現(xiàn)矩陣,基于同現(xiàn)矩陣計算物品之間的相似度矩陣。

\omega_{ij} =\frac{同時喜歡物品i和物品j的用戶數(shù)}{喜歡物品i的用戶數(shù)乘以喜歡物品j的用戶數(shù),再對乘積開根號}

⑵?預測某一用戶對物品集中他尚未進行評分的物品的評分,并依據(jù)計算出來的評分高低來進行推薦。也可以先對所有物品進行評分預測,然后剔除掉已評分的物品,對剩下的物品進行排序。

給單個用戶進行推薦,自然需要遍歷一下他所評價過的物品。該用戶對任意一個物品 j 的評分預測值為:

? ??????\sum_{i}(該用戶給其操作過的物品i的評分*物品j與物品i的相似度)

但是這樣需要對所有物品都計算一次,計算量太大。

我們可以定義一個近鄰物品數(shù) k 。遍歷一下該用戶所有操作過的物品 i ,我們只對與物品 i 相似度最高的 k 個物品進行評分預測。比如,假設該用戶操作過 10 個物品,取 k 的值為 8, 那么我們進行評分預測的物品數(shù)為 80 個(假設這里面沒有出現(xiàn)重復的物品)。如果出現(xiàn)重復的物品,那么我們實際預測的物品數(shù)將小于 80。用字典數(shù)據(jù)類型比較容易解決重復的問題。

3 物品相似度的計算

①我們需要統(tǒng)計出每個物品被多少用戶喜歡,即喜歡該物品的用戶數(shù)。

②我們還需要計算出同現(xiàn)矩陣,即同時喜歡物品 i 和物品 j 的用戶數(shù)。

根據(jù)①和②,我們便可以計算物品之間的相似度了。

下面我們寫一個函數(shù)來實現(xiàn)這個功能。

def? item_similarity(user_dict):

? ? ? ? item_count = dict()? ? ? ? # 用來保存喜歡某物品的用戶數(shù)

? ? ? ? count = dict()? ? ? ? # 同現(xiàn)矩陣,用來保存同時喜歡物品 i 和物品 j 的用戶數(shù)

? ? ? ? # 下面我們遍歷user_dict中的所有用戶,來獲得①和②兩個步驟所需要的數(shù)據(jù)

? ? ? ? for user, user_item in?user_dict.items():

? ? ? ? ? ? ? ? for i in user_item.keys():? ? # 這里僅計數(shù),沒利用上user_item.values()數(shù)據(jù)

? ? ? ? ? ? ? ? ? ? ? ? item_count.setdefault( i, 0)

? ? ? ? ? ? ? ? ? ? ? ? if? user_dict[user] [ i ]? > 0.0:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? item_count[ i ] += 1

? ? ? ? ? ? ? ? ? ? ? ? for j in?user_item.keys():

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if??user_dict[user] [ i ]? > 0.0? and??user_dict[user] [ j ]? > 0.0? and? i != j:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? count[ i ][ j ] +=1

? ? ? ? # 下面基于同現(xiàn)矩陣計算相似度矩陣

? ??????similarity = dict()? ? ? ? # 用來保存物品間的相似度

? ? ? ? for? i, i_itemsimilar_num? in count.items():

? ? ? ? ? ? ? ? similarity.setdefault( i, {} )

? ? ? ? ? ? ? ? for j , num in?i_itemsimilar_num.items():

? ??????????????????????similarity[ i ].setdefault( j , 0)

? ??????????????????????similarity[ i ][ j ] = num / math.sqrt( item_count[ i] * item_count[ j ])

? ? ? ? return?similarity

4 預測評分的過程

我們先找出該用戶評價過的所有物品,假設保存在 item_of_thisuser字典里,字典的鍵為各個評價過的物品,并假設鍵的數(shù)目為 num_of_thisuser,字典的值為他給對應物品的評分。事實上,?item_of_thisuser 很容易從原始評分文件user_dict中提取出來。

然后,對于item_of_thisuser里的各個鍵(即各個物品),我們通過similarity字典找出與其最相似的 k 個物品,最后將這 k *?num_of_thisuser 個物品的預測評分去排序(假設任意兩個鍵對應的 2k 個物品中不存在重復的)。

以上思路很簡單,下面我們通過一個函數(shù)來實現(xiàn)一下。

def prediction(thisuser, k=8):

? ? ? ? result = dict()? ? # 用來保存各個物品的評分

? ? ? ? for i, score in?item_of_thisuser.items():

? ? ? ? ? ? ? ? sort_similarity = sorted( similarity[ i ].items(), key=lambda x: x[1], reverse=True)

? ? ? ? ? ? ? ? for j, wij in sort_similarity[0:k]:

? ? ? ? ? ? ? ? ? ? ? ? if j in?score in?item_of_thisuser:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? continue? ? # 對于已經(jīng)評分過的物品,沒必要對其計算預測評分了

? ? ? ? ? ? ? ? ? ? ? ? result.setdefault( j, 0)

? ? ? ? ? ? ? ? ? ? ? ? result[ j ] += score * wij

? ? ? ? return result? ? ?# 此處先不對result里的物品按預測評分排序

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容