1. 程式人生 > >用Python構建你自己的推薦系統

用Python構建你自己的推薦系統

title who tar 啟動問題 function metrics 模塊 距離度量 tuples

用Python構建你自己的推薦系統

  現如今,網站用推薦系統為你提供個性化的體驗,告訴你買啥,吃啥甚至你應該和誰交朋友。盡管每個人口味不同,但大體都適用這個套路。人們傾向於喜歡那些與自己喜歡的其他東西相似的東西,也傾向於與自己身邊的人有相似的口味。推薦系統就嘗試捕捉這一規律來幫助預測你也可能喜歡的其他東西。

  為幫用戶高效挑選商品,電子商務、社交媒體、視頻和在線新聞平臺已積極部署了他們自己的推薦系統,這是一個雙贏的策略。

  

  推薦系統兩個最普遍的類型是基於內容過濾法和協同過濾法。協同過濾法基於用戶對商品的評價信息來產生推薦,是用大眾的智慧來推薦內容。相比之下,基於內容推薦系統關註的是商品的屬性,基於它們之間的相似度給你推薦。

  大體上,協同過濾(CF)是推薦引擎工作的是主力。這一算法有一個很有趣的特點,它能夠自主學習,這意味著它能夠開始學習哪些特點能為己所用。協同過濾又可分為基於內存的協同過濾和基於模型的協同過濾。在此教程中,你將實現運用奇異值分解的基於模型協同過濾法和通過計算余弦相似性的基於內存協同過濾法。

  我們將使用MovieLens數據集,這是用來實現和測試推薦引擎最普遍的數據集之一。它包含來自於943個用戶的10萬個電影評價和1682部電影集合。你最好將這個數據集(MoviesLens-100k)解壓到你的notebook目錄。

  

  

1 2 import numpy as np
import pandas as pd

 u.data文件中包含了完整數據集。你可以在這裏查閱關於這個數據集的簡要描述

1 2 header = [‘user_id‘, ‘item_id‘, ‘rating‘, ‘timestamp‘] df = pd.read_csv(‘ml-100k/u.data‘, sep=‘\t‘, names=header)

 先看一眼數據集中的前兩行。接下來,讓我們統計其中的用戶和電影總數。

n_users = df.user_id.unique().shape[0]
n_items = df.item_id.unique().shape[0]
print Number of users = ‘ + str(n_users) +  | Number of movies = ‘ + str(n_items)  

Number of users = 943 | Number of movies = 1682

你可以使用scikit-learn文庫將數據集分為測試和訓練兩部分。Cross_validation.train_test_split 模塊根據測試樣本的百分比將數據混合並分為兩部分,在這裏百分比為0.25

from sklearn import cross_validation as cv
train_data, test_data = cv.train_test_split(df, test_size=0.25)

基於內存協同過濾法

  基於內存協同過濾法可以被主要分為兩部分:用戶-項目過濾(user-item filtering項目-項目過濾( item-item filtering user-item filtering選取一個特定用戶,基於評價相似性找到與該用戶相似的其他用戶,並推薦那些相似用戶所喜歡的項目。相比之下, item-item filtering 先選取一個項目,然後找出也喜歡這個項目的其他用戶,並找出這些用戶或相似用戶也喜歡的其他項目,推薦過程需要項目並輸出其他項目。

  • Item-Item Collaborative Filtering: “Users who liked this item also liked …”
  • User-Item Collaborative Filtering: “Users who are similar to you also liked …”

在這兩種情況中,你根據整個數據集創建了一個用戶-項目的矩陣。因為已經把數據分成了測試和訓練兩部分所以你需要創建兩個[943 x 1682]矩陣。訓練矩陣包含75%的評價,測試矩陣包含25%的矩陣。

用戶-項目矩陣例子:

技術分享圖片

創建了用戶-項目矩陣之後,計算相似性並創建一個相似度矩陣。

Item-Item Collaborative Filtering算法中項目之間的相似度依靠觀測所有的已對相同項目評價的用戶來測算。

技術分享圖片

對於User-Item Collaborative Filtering算法,用戶之間的相似性依靠觀測相同用戶已評價的所有項目。

技術分享圖片

  推薦系統中通常使用余弦相似性作為距離度量,在n維孔空間中評價被視為向量,基於這些向量之間的夾角來計算相似性。

  用戶am可以用下面的公式計算余弦相似性,其中你可以使用用戶向量ukua之間的點積然後除以這兩個向量歐式長度之乘。

技術分享圖片

  而計算項目m和b之間的相似度可以用下面的公式:

技術分享圖片

首先創建user-item矩陣,因此你需要創建兩個矩陣為測試和訓練數據集。

1 2 3 4 5 6 7 8 #Create two user-item matrices, one for training and another for testing train_data_matrix = np.zeros((n_users, n_items)) for line in train_data.itertuples(): train_data_matrix[line[1]-1, line[2]-1] = line[3] test_data_matrix = np.zeros((n_users, n_items)) for line in test_data.itertuples(): test_data_matrix[line[1]-1, line[2]-1] = line[3]

  你可以使用 pairwise_distances函數來計算余弦相似性。註意,因為評價都為正值輸出取值應為0到1.

1 2 3 from sklearn.metrics.pairwise import pairwise_distances user_similarity = pairwise_distances(train_data_matrix, metric=‘cosine‘) item_similarity = pairwise_distances(train_data_matrix.T, metric=‘cosine‘)

  下一步是作出預測。既然構造了相似度矩陣user_similarityitem_similarity,因此你可以運用下面的公式為user-based CF做一個預測:

技術分享圖片

  用戶k和用戶a之間的相似度根據一個相似用戶a的一系列評價的乘積(修正為該用戶的平均評價)的權重。你將需要標準化相似度這樣可以使評價維持在1到5之間,最後一步,統計你想預測用戶平均評價的總和。

  這裏考慮到的問題是一些用戶評價所有電影時可能要麽給最高分,要麽給最低分。這些用戶給出評價的相對不同比絕對值更重要。例如:設想,用戶k對他最喜歡的電影評價4顆星,其他的好電影則評價3顆星。假設現在另一個用戶t對他/她喜歡的一部電影評價為5顆星,看了想睡覺的一部電影評價為3顆星。這兩位用戶電影口味可能很相似但使用評價體系的方法不同。

  當為item-based CF做一個推薦時候,你不要糾正用戶的平均評價,因為用戶本身用查詢來做預測。

技術分享圖片

1 2 3 4 5 6 7 8 9 def predict(ratings, similarity, type=‘user‘): if type == ‘user‘: mean_user_rating = ratings.mean(axis=1) #You use np.newaxis so that mean_user_rating has same format as ratings ratings_diff = (ratings - mean_user_rating[:, np.newaxis]) pred = mean_user_rating[:, np.newaxis] + similarity.dot(ratings_diff) / np.array([np.abs(similarity).sum(axis=1)]).T elif type == ‘item‘: pred = ratings.dot(similarity) / np.array([np.abs(similarity).sum(axis=1)]) return pred
item_prediction = predict(train_data_matrix, item_similarity, type=item)
user_prediction = predict(train_data_matrix, user_similarity, type=user‘)

評估  

有許多的評價指標,但是用於評估預測精度最流行的指標之一是Root Mean Squared Error (RMSE)。

技術分享圖片

你可以用sklearn中的 mean_square_error (MSE)函數,RMSE只是MSE其中的一個平方根。想閱讀更多關於不同評估指標你可以 查看這篇文章。

因為你僅僅想考慮在這個測試數據集中的預測評價,你可以用prediction[ground_truth.nonzero()]過濾測試矩陣中所有其他的元素。

1 2 3 4 5 6 from sklearn.metrics import mean_squared_error from math import sqrt def rmse(prediction, ground_truth): prediction = prediction[ground_truth.nonzero()].flatten() ground_truth = ground_truth[ground_truth.nonzero()].flatten() return sqrt(mean_squared_error(prediction, ground_truth))

  

1 2 print ‘User-based CF RMSE: ‘ + str(rmse(user_prediction, test_data_matrix)) print ‘Item-based CF RMSE: ‘ + str(rmse(item_prediction, test_data_matrix))

  

1 2 User-based CF RMSE: 3.1236202241 Item-based CF RMSE: 3.44983070639

  

Memory-based算法容易實施並產生合理的預測質量。memory-based CF的缺點是它不能擴展到現實世界的場景和沒有處理眾所周知的冷啟動問題(面對新用戶或者新項目進去系統時)。Model-based CF方法可伸縮並且能處理 比memory-based方法更高等級的稀疏度,面對新用戶或者沒有任何評價的新項目進入系統時也會變差。我想感謝Ethan Rosenthal關於Memory-Based Collaborative Filtering的博客。

Model-based Collaborative Filtering


基於模型的協同過濾是基於已收到更大的曝光,主要是作為潛變量分解和降維無監督的學習方法矩陣分解(MF)

Model-based Collaborative Filtering基於已收到很多曝光的矩陣因式分解 (MF),主要是作為潛在變量分解和降維無監督學習方法。矩陣因式分解因其能比Memory-based CF更好解決可擴展性和稀疏問題而被廣泛用於推薦系統。MF的目標是學習用戶潛在的喜好和從已知評分的項目的潛在屬性(學習描述評分特征的特點),以隨後通過用戶和項目的潛在特征點積預測未知的評分。

當你有一個多維度稀疏矩陣,通過矩陣因式分解你能夠將用戶-項目矩陣(user-item matrix)重構成低評分結構(low-rank structure),並且你能夠通過兩個低評分( low-rank)矩陣相乘得出這個矩陣,其中矩陣的行包含潛在向量。

通過低評價矩陣乘積盡可能調整這個矩陣近似原始矩陣,以填充原始矩陣中缺失的項。

現在開始計算MovieLens 數據集的稀疏等級:

1 2 sparsity=round(1.0-len(df)/float(n_users*n_items),3) print ‘The sparsity level of MovieLens100K is ‘ + str(sparsity*100) + ‘%‘

  

1 The sparsity level of MovieLens100K is 93.7%

  舉個例子說明學習用戶和項目的潛在喜好:就拿MovieLens數據集來說你有一下信息:(用戶ID,年齡,地理位置,性別,電影ID,導演,演員,語言,年份,評分)。通過運用矩陣因式分解這個模型學習到重要的用戶特征是年齡段(10歲以下、10-18歲、18-30歲、30-90歲)、地理位置和 性別,對電影特征它學習到最重要的是年代、導演和演員。現在如果你回過頭來看你已經存儲的信息,沒有諸如年代等的特征,但是這個模型可以自己學習到。重要的方面是CF模型僅需使用數據(用戶ID,電影ID,評分)來學習這些潛在的特征。如果沒有數據可用CF模型性能將會很差,因為這樣它更困難學習這些潛在的特征。

評分和特征都要使用的模型稱為混合推薦系統(Hybrid Recommender Systems),它是Collaborative Filtering 和Content-based 模型兩者的結合。混合推薦系統通常比Collaborative Filtering 或者Content-based模型獨立地表現出更高的精度:它們能夠更好地處理冷啟動問題(因為如果你沒有可用於數據集的對於用戶或項目的任何評價你就很難做出預測)。混合推薦系統將在下一篇介紹中介紹。

SVD

一個知名的矩陣因式分解方法是Singular value decomposition (SVD)。Collaborative Filtering
協同過濾可以通過使用奇異值分解近似矩陣X被配制

本文翻譯自:http://online.cambridgecoding.com/notebooks/eWReNYcAfB/implementing-your-own-recommender-systems-in-python-2

原作者:Agnes Jóhannsdóttir

用Python構建你自己的推薦系統