协同滤波模型的推荐算法(ACM暑校-案例学习)
基于協(xié)同濾波的推薦技術(shù)可以細分為基于用戶的協(xié)同過濾方法、基于產(chǎn)品的協(xié)同過濾方法、基于模型的協(xié)同過濾方法;本博文進行了一一測試。
1. 數(shù)據(jù)準(zhǔn)備、評價指標(biāo)
由于協(xié)同濾波模型需要用到用戶的行為,這里選用MovieLen數(shù)據(jù)集進行測試研究。
MovieLen是明尼蘇達大學(xué)計算機科學(xué)系GroupLens研究中心開發(fā)和維護的,也是最常用于測試協(xié)同濾波算法性能的公開數(shù)據(jù)集之一。Movielens提供了大量電影的用戶評分。完整的版本包括超過了26000000的電影評分,他們來源于270000用戶觀看45000部電影的體會。GroupLens網(wǎng)站上提供的數(shù)據(jù)集不再提供用戶人口統(tǒng)計信息。因此,這里使用Prajit-Datta在kaggle上提供的部分數(shù)據(jù)集。
- 數(shù)據(jù)下載
下載地址:https://www.kaggle.com/prajitdatta/movielens-100k-dataset/data?
該數(shù)據(jù)集包括:1682部電影上943名用戶的100000個評分(1-5)。每個用戶至少為20部電影打分。該數(shù)據(jù)集也為用戶提供簡單的人口統(tǒng)計信息(年齡、性別、工作等)。這些數(shù)據(jù)是在1997年9月19日至1998年4月22日的七個月期間通過Movielens網(wǎng)站(movielens.umn.edu)收集的。此數(shù)據(jù)已被清除-從該數(shù)據(jù)集中刪除了評分低于20或沒有完整人口統(tǒng)計信息的用戶。
- 數(shù)據(jù)瀏覽
在解壓文件中,只需要使用u.date/ u.user/ u.item三個文件。
① 查看用戶圖譜文件
import pandas as pd# load the u.user file into a dataframe u_cols = ['user_id', 'age', 'sex', 'occupation', 'zip_code'] users = pd.read_csv('C:/Users/Administrator/Desktop/RecoSys/data/movielens/u.user', sep='|',names=u_cols, encoding='latin-1') users.head()可以看到,u.user文件中主要包含的用戶圖譜,如年齡,性別,職業(yè),zip_code。
② 查看電影描述文件
i_cols = ['movie_id', 'title', 'release date', 'video release date', 'IMDB URL', 'unknow', 'Action', 'Adventure', 'Animation', 'Children\'s', 'Comedy', 'Crime', 'Documentary', 'Drama', 'Fantasy', 'Film-Noir', 'Horror', 'Musical', 'Mystery', 'Romance', 'Sci-Fi', 'Thriller', 'War','Western'] movies = pd.read_csv('C:/Users/Administrator/Desktop/RecoSys/data/movielens/u.item',sep='|', names=i_cols, encoding='latin-1') movies.head()可以看出,u.item文件中主要提供了電影的名字、發(fā)行時間、IMDB URL和題材等信息。因為,本編博客主要研究的是協(xié)同濾波算法,因此,電影中的題材等是用不到的,只需要保留movie_id和title就好。
movies = movies[['movie_id', 'title']] movies.head()③ 查看用戶對電影評分文件
r_cols = ['user_id', 'movie_id', 'rating', 'timestamp'] ratings = pd.read_csv('C:/Users/Administrator/Desktop/RecoSys/data/movielens/u.data',sep='\t', names=r_cols, encoding='latin-1') ratings.head()- 訓(xùn)練數(shù)據(jù)?training data & 測試數(shù)據(jù) test data
DataFrame包含從1-5的用戶對電影的評分。因此,可以將該問題建模為監(jiān)督學(xué)習(xí)的實例,目的在于預(yù)測給定用戶和電影的評分。雖然電影的分數(shù)只是1-5的五個離散值,其實質(zhì)仍為回歸問題。考慮用戶對電影的真實評分是5:分類模型不能區(qū)分預(yù)測評分為1和4的情況。分類模型會將1-4的評分都視為錯誤分類。然而,回歸模型卻不是這樣子,其對rating=4的懲罰遠遠大于rating=1的情況。
對于監(jiān)督模型的學(xué)習(xí),重要的一步在于訓(xùn)練集和測試集的劃分。在本次試驗中,用戶評分數(shù)據(jù)中的75%用作模型訓(xùn)練,25%用于模型測試
from sklearn.model_selection import train_test_split X = ratings.copy() y = ratings['user_id'] # split into training and test datasets, stratified along user_id X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, stratify=y, random_state=42)>>> X_train.shape = (75000, 3) X_test.shape = (25000, 3)- 評估方法
這里選用根均方差(RMSE=root-mean-square-error)對模型的推薦性能進行評估。其Python實現(xiàn)如下所示:
from sklearn.metrics import mean_squared_error from numpy as npdef rmse(y_true, y_pred):return np.sqrt( mean_squared_error(y_true, y_pred) )# Function to compute the RMSE score obtained on the testing set by a model def score(cf_model):# Construct a list of user-movie tuples from the testing datasetid_pairs = zip(X_test['user_id'], X_test['movie_id'])# Predict the rating for every user-movie tupley_pred = np.array([cf_model(user, movie) for (user, movie) in id_pairs])# Extract the actual ratings given by the users in the test datay_true = np.array(X_test['rating'])# Return the final RMSE scorereturn rmse(y_true, y_pred)2. 基于用戶的協(xié)同過濾推薦算法實例 Users-based
基于用戶的協(xié)同推薦算法把主要的研究精力放在用戶角度,實質(zhì)上就是具有相同興趣的用戶群體進行聚類,然后對相同類群的用戶進行產(chǎn)品推薦。核心在于對高度稀疏的用戶-產(chǎn)品矩陣進行預(yù)測和填充。PANDAS提供了一個非常好用的函數(shù)pivot_table去構(gòu)造rating矩陣:
# Build the ratings matrix using pivot_table function r_matrix = X_train.pivot_table(values='rating', index='user_id', columns='movie_id') r_matrix.head(5)該矩陣就是推薦領(lǐng)域最最重要的了:①用戶-產(chǎn)品矩陣是高度稀疏的;②實際應(yīng)用過程中,從用戶和產(chǎn)品兩個維度考慮,評分矩陣是非常非常巨大的。
- 均值Mean角度初步考慮
首先可以構(gòu)建一個最簡單的協(xié)同過濾算法,只需輸入用戶ID和電影ID,并輸出所有看過的用戶對該電影的平均評分。用戶之間沒有區(qū)別。換言之,每個用戶的評分被賦予相等的權(quán)重。其中,有一種完全可能異常情況:有些電影只能在測試數(shù)據(jù)集進行訪問,而在訓(xùn)練數(shù)據(jù)集不存在。該情況下,我們直接設(shè)置一個baseline,將其默認賦值為3.0。
# User Based Collaborative Filter using MEan Rating def cf_user_mean(user_id, movie_id):# Check if movie_id exists in r_matrixif movie_id in r_matrix:# Compute the mean of all the ratings given to the moviemean_rating = r_matrix[movie_id].mean()else:# Default to a rating of 3.0 in the absence of any informationmean_rating = 3.0return mean_rating# Compute RMSE for the Mean model score(cf_user_mean)>>> 1.0234701463131335該方法僅僅適合討論研究,是沒有實際應(yīng)用價值的:一方面,用戶對產(chǎn)品的評分肯定會有偏好;另一方面,大部分少數(shù)群體的興趣沒有被認真關(guān)注。一種合適的改進方法是采用加權(quán)平均weighted mean。
- 加權(quán)均值weighted mean角度考慮
在前面的模型中,我們?yōu)槊恳粋€用戶分配了等同的權(quán)重。然而,與普通用戶相比,對那些評分與所討論問題相似的用戶給予更多的關(guān)注。因此,在前面的模型中,比較合適的方案是為每一個用戶分配一個合適的權(quán)重系數(shù)。數(shù)學(xué)可以表示為:
其中,r(u,m)表示為用戶u對電影m的評分。對于相似度測量,同樣采用余弦距離。
數(shù)據(jù)處理:將rating表中的NAN替換成0,然后用scikit-learn中的cosine_similarity函數(shù)進行處理。
r_matrix_dummy = r_matrix.copy().fillna(0) r_matrix_dummy.head() r_matrix_dummy.shape>>> (943, 1647) from sklearn.metrics.pairwise import cosine_similarity cosine_sim = cosine_similarity(r_matrix_dummy, r_matrix_dummy) cosine_sim.shape>>> (943, 943) # Convert into pandas dataframe cosine_sim = pd.DataFrame(cosine_sim, index=r_matrix.index, columns=r_matrix.index) cosine_sim.head() # User Based Collabrative Filter using Weighted Mean Ratings def cf_user_wmean(user_id, movie_id):# Check if movie_id exists in r_matrixif movie_id in r_matrix:sim_scores = cosine_sim[user_id]m_ratings = r_matrix[movie_id]idx = m_ratings[m_ratings.isnull()].indexm_ratings = m_ratings.dropna()sim_scores = sim_scores.drop(idx)wmean_rating = np.dot(sim_scores, m_ratings)/ sim_scores.sum()else:#Default to a rating of 3.0 in the absence of any informationwmean_rating = 3.0return wmean_ratingscore(cf_user_wmean)>>> 1.0174483808407588- 用戶圖譜demographics角度考慮
這是一種相對而言更加精細的處理方式。該算法的核心思想是,具有相同圖譜的用戶傾向于有相似的品味。因此,其有效性取決于這樣的假設(shè):女性、青少年或來自同一地區(qū)的人在電影選擇時會有相同的品味。與前面的模型不同,該種算法不考慮用戶對特定電影的評分。相反,算法只關(guān)注那些符合特定人群的用戶。
3.?基于產(chǎn)品的協(xié)同過濾推薦算法實例 Items-based
Items-based和User-based方法本質(zhì)是一致的,就相當(dāng)于將第二節(jié)中的User變成Item。在基于產(chǎn)品的協(xié)同過濾中,我們計算庫存中產(chǎn)品的成對相似性。然后,根據(jù)user_id和movie_id,計算用戶對其所有評分產(chǎn)品的加權(quán)平均值。這個模型背后的基本思想是:一個特定的用戶可能會對相似的兩個產(chǎn)品有相似的評分。
4. 基于模型的方法 Model-based
到目前為止,上面的協(xié)同過濾算法被稱為memory-based的過濾。因為他們只利用相似性度量來得出結(jié)果,并沒有從數(shù)據(jù)中學(xué)習(xí)任何參數(shù),或者為數(shù)據(jù)分配類/集群。并沒有用到機械學(xué)習(xí)算法的威力。
- 以聚類為核心的協(xié)同過濾算法 - Clustering
weighted mean-based 的濾波算法,考慮到了每一位用戶的評分,最后進行加權(quán);相反,demographic-based濾波算法僅僅考慮了‘某個圈子’的用戶,最后進行平均。通常來說,weighted mean-based取得的結(jié)果會好于demographic-based,因為考慮的相對來說更廣一點。但是,這兩種方法僅僅用到了最直接、最粗淺的信息,一種解決方案是進行多維度用戶刻畫,進行利用機器學(xué)習(xí)算法解決高緯度數(shù)據(jù)處理問題。簡單說,精準(zhǔn)的推薦結(jié)果不一定唯一依賴考慮所有用戶的感受!
demographic-based算法的缺點來源于他的假設(shè):來自某個相同圖譜的用戶具有相同的想法和評分。這種極端的思考模式造成了算法的粗淺。Clustering-based方法,如k-means, 就是為了改善這種情況:將用戶分組到一個群集中,然后在預(yù)測評分時只考慮來自同一個群集中的用戶。下面以KNN-based clustering為例,構(gòu)建相關(guān)的協(xié)同過濾算法。步驟如下 ①找出與用戶u對電影m評分最相似的k個最近鄰;②輸出k個用戶對電影m評分的平均值。
可以直接采用Python中的surprise(Simple Python Recommandation System Engine)庫實現(xiàn)。Windows 平臺下下載方式為:pip install scikit-surprise.
# Import the required classes and methods from the surprise library from surprise import Reader, Dataset, KNNBasic, evaluate # Define a Reader object - The Reader object helps in parsing the file or dataframe containing ratings reader = Reader() # Create the dataset to be used for building the filter data = Dataset.load_from_df(ratings, reader) # Define the algorithm object knn = KNNBasic() # Evaluate the performance in terms of RMSE evaluate(knn, data, measures=['RMSE'])從輸出結(jié)果中,我們能夠看出來。surprise庫將所有的評分數(shù)據(jù)劃分為5個文件包,其中4個文件包用于算法訓(xùn)練,第5個文件包用于模型測試。這樣的過程重復(fù)了5次。
- 監(jiān)督學(xué)習(xí)和降維方法
對于mxn大小的評分矩陣,每一行代表m個用戶中的一個對所有電影的評分;每一列代表n個電影中的一個接受所有用戶的評分。前面已經(jīng)看到了,該評分矩陣是非常稀疏的。通過監(jiān)督學(xué)習(xí)的方法,我們可以嘗試將這個高度稀疏的矩陣補全。
最簡單的思考是,我們可以利用mx(n-1)的評分矩陣進行模型的監(jiān)督訓(xùn)練,然后對m*1的未知評分進行預(yù)測。如此重復(fù)n次,那么評分矩陣將有可能完全被填充。理想是豐滿的,現(xiàn)實的骨感的。因為,一開始我們用的mx(n-1)的模型訓(xùn)練矩陣就是高度稀疏的~~~(目前也沒辦法解決這個事,工程上的一種處理手段是用所屬的列的均值或中值來填充缺失值,但是考慮到rating矩陣高達90%的系數(shù),計算的均值和中位數(shù)一定會引進很大的偏差;同時降維技術(shù),PCA/SVD也不能處理如此稀疏的情況)
可以借鑒的一種思路是,Simon Funk在處理Netflix Problem時,將mx(n-1)的模型訓(xùn)練矩陣壓縮到了更低的維度mxd (d << n),這種處理方式稱為SVD-like,其實效果也比較一般。
- 火極一時的推薦算法-奇異值分解 Singular-value decomposition
本質(zhì)上,奇異值分解是一種矩陣因子技術(shù),其輸入為大型矩陣A,輸出為小矩陣U和V。其中,Σ為對角矩陣用于吃調(diào)整數(shù)據(jù)的尺度。對于U矩陣,其實質(zhì)表征的是用戶主成分,英文專有名詞對應(yīng)user-embedding矩陣;V矩陣,其實質(zhì)表征的是產(chǎn)品主成分,英文專有名詞對應(yīng)item-embedding矩陣。
和大多數(shù)機器學(xué)習(xí)算法一樣,傳統(tǒng)的SVD矩陣對極其稀疏的評分矩陣是沒有效益的。然而,SimonFunk找到了解決這個問題的方法,他的解決方案(SVD++)促成了了推薦系統(tǒng)領(lǐng)域最著名的算法之一。該方法可以利用高度稀疏的評分矩陣A,生成兩個非常稠密的user-embedding矩陣U和item-embedding矩陣V。這些稠密的矩陣(U,V)直接解決了原始數(shù)據(jù)A高度稀疏的難題。surprise庫也集成了該算法,調(diào)用如下:
#Import SVD from surprise import SVD #Define the SVD algorithm object svd = SVD() #Evaluate the performance in terms of RMSE evaluate(svd, data, measures=['RMSE'])?
總結(jié)
以上是生活随笔為你收集整理的协同滤波模型的推荐算法(ACM暑校-案例学习)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《南方都市报》:中国互联网“公共性”正在
- 下一篇: VC改造IE浏览器