python實現推薦系統(一)


協同過濾分為  memory-based 和 model based  

1. memory-based  利用用戶物品之間相似度進行推薦

一種是 item-item 即喜歡這個物品的用戶還喜歡..

一種是 user-item 即與你有相似愛好的用戶還喜歡..

現在有個評分矩陣R,行表示用戶,列表示物品,R(i,j)表示用戶i對物品j的評分,R(:,j)表示所有用戶對物品j的評分列,R(i,:)表示用戶i對所有物品的評分行,用戶與物品沒有交互,評分自然為0,可以知道一般的矩陣R是稀疏的。

由user-item  計算每個用戶的相似度,一般取(余弦相似度),即 cos(R(i,:),R(k,:)),  利用在sklearn中的模塊很容易計算得到用戶相似矩陣

from sklearn.metrics.pairwise import pairwise_distances
user_similarity = pairwise_distances(R, metric='cosine')

由item-item 計算每件商品相似度, 

item_similarity = pairwise_distances(R.T, metric='cosine')

得到相似度就可以計算預測矩陣P, 即將用戶與商品之間沒有交互的R(i,j)賦上一個預測值

先考慮 item-item 我們可以知道如果物品m與某個物品b相似度較高,那么 與b有交互的用戶k對b的評分會很接近於m,最簡單的是m=b,那么評分相等,可以給出公式來預估k對m的評分,其中分母起到正則化的作用

用戶k對物品m的評分預測:分子表示 物品m與其他所有物品b相似度 與 用戶對其他物品b 的乘積 的和,相當於加權平均

考慮user-item  如果兩個用戶相似,自然他們對某個物品評分應該接近,但如果總有些用戶a喜歡給物品評很高的分,這時候即使兩個用戶不相似,按照item-item 的公式,他們也能占到很高的權重,這就相當於一種干擾,一種噪聲, 這樣,對每個用戶評分做一個平均,標准化

用戶k對物品m的評分預測:   用戶k對所有物品評分平均+   (用戶k與其他所有用戶a相似度 與 (其他用戶a對m的評分-其他用戶a對所有物品的平均評分)的加權和)/分母

這樣我們就可以編寫預測函數

def predict(R, similarity, type='item'):
    if type == 'user':
        mean_user_rating = R.mean(axis=1)# axis=1 計算每行
        rating_d = (R - mean_user_rating[:, np.newaxis]) #np.newaxis根據 R 調整矩陣
        prediction = mean_user_rating[:, np.newaxis] + similarity.dot(rating_d) / np.array([np.abs(similarity).sum(axis=1)]).T
    elif type == 'item':
        prediction = ratings.dot(similarity) / np.array([np.abs(similarity).sum(axis=1)])     
    return prediction

通常我們還要對預測結果進行評價,有多種評價函數,一般可以用RMSE(根平均平方誤差)

 自然我們要拿R的非0值進行比較,計算預測前后的誤差

from sklearn.metrics import mean_squared_errordef rmse(prediction, test_R):
    prediction = prediction[test_R.nonzero()].flatten() 
    test_R= test_R[test_R.nonzero()].flatten()
    return sqrt(mean_squared_error(prediction, test_R))

 

2 model-based  采用矩陣因子分解來近似填充原矩陣

一般來說矩陣R是稀疏的,考慮矩陣計算中的奇異值分解(SVD),通過將其分解成三個矩陣,其中S對角元素稱為奇異值,通過過濾前k大的奇異值,可以近似保存原先矩陣的信息,正如一個圖像矩陣,選取合適的k,重新計算得到的新圖像可以在感官上與原圖像無差異。

具體公式如

X 是m×n , U 是m×k , S 是 k×k , V.T 是k×n

這樣通過計算就可以得到預測矩陣X

import scipy.sparse as sp
from scipy.sparse.linalg import svds
U, s, VT = svds(train_R, k = 15)  #選擇k=15
S=np.diag(s)
X = np.dot(np.dot(U, S), VT)

 本文主要介紹了memory-based 和 model-based的協同過濾方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM