在Python中實現你自己的推薦系統

發表於2016-06-24

現今,推薦系統被用來個性化你在網上的體驗,告訴你買什麼,去哪裡吃,甚至是你應該和誰做朋友。人們口味各異,但通常有跡可循。人們傾向於喜歡那些與他們所喜歡的東西類似的東西,並且他們傾向於與那些親近的人有相似的口味。推薦系統試圖捕捉這些模式,以助於預測你還會喜歡什麼東西。電子商務、社交媒體、視訊和線上新聞平臺已經積極的部署了它們自己的推薦系統,以幫助它們的客戶更有效的選擇產品,從而實現雙贏。

兩種最普遍的推薦系統的型別是基於內容協同過濾(CF)。協同過濾基於使用者對產品的態度產生推薦,也就是說,它使用“人群的智慧”來推薦產品。與此相反,基於內容的推薦系統集中於物品的屬性,並基於它們之間的相似性為你推薦。一般情況下,協作過濾(CF)是推薦引擎的主力。該演算法具有能夠自身進行特徵學習的一個非常有趣的特性,這意味著它可以開始學習使用哪些特性。CF可以分為基於記憶體的協同過濾基於模型的協同過濾。在本教程中,你將使用奇異值分解(SVD)實現基於模型的CF和通過計算餘弦相似實現基於記憶體的CF。

我們將使用MovieLens資料集,它是在實現和測試推薦引擎時所使用的最常見的資料集之一。它包含來自於943個使用者以及精選的1682部電影的100K個電影打分。你應該新增解壓縮的movielens資料資料夾你的notebook目錄下。你也可以在這裡下載資料集。

讀入u.data檔案,它包含完整的資料集。你可以 file, which contains the full dataset. You can在這裡閱讀該資料集的簡要說明。

先看看資料集中的前兩行。接下來,讓我們計算唯一使用者和電影的數量。

你可以使用scikit-learn庫將資料集分割成測試和訓練。Cross_validation.train_test_split根據測試樣本的比例(test_size),本例中是0.25,來將資料混洗並分割成兩個資料集。

基於記憶體的協同過濾

基於記憶體的協同過濾方法可以分為兩個主要部分:使用者-產品協同過濾產品-產品協同過濾。一個使用者-產品協同過濾將選取一個特定的使用者,基於打分的相似性發現類似於該使用者的使用者,並推薦那些相似使用者喜歡的產品。相比之下,產品-產品協同過濾會選取一個產品,發現喜歡該產品的使用者,並找到這些使用者或相似的使用者還喜歡的其他的產品。輸入一個產品,然後輸出其他產品作為推薦。

  • 使用者-產品協同過濾: “喜歡這個東西的人也喜歡……”
  • 產品-產品協同過濾: “像你一樣的人也喜歡……”

在這兩種情況下,從整個資料集構建一個使用者-產品矩陣。由於你已經將資料拆分到測試集和訓練集,那麼你將需要建立兩個[943 x 1682]矩陣。訓練矩陣包含75%的打分,而測試矩陣包含25%的打分。

使用者-產品矩陣的例子: blog8

在構建了使用者-產品矩陣後,計算相似性並建立一個相似性矩陣。

產品-產品協同過濾中的產品之間的相似性值是通過觀察所有對兩個產品之間的打分的使用者來度量的。

對於使用者-產品協同過濾,使用者之間的相似性值是通過觀察所有同時被兩個使用者打分的產品來度量的。

通常用於推薦系統中的距離矩陣是餘弦相似性,其中,打分被看成n維空間中的向量,而相似性是基於這些向量之間的角度進行計算的。使用者am的餘弦相似性可以使用下面的公式進行計算,其中,獲取使用者向量的點積,然後用向量的歐幾里得長度的乘積來除以它。

要計算產品mb之間的相似性,使用公式:

第一步是建立使用者-產品矩陣。由於你既有測試資料,又有訓練資料,那麼你需要建立兩個矩陣。

你可以使用sklearnpairwise_distances函式來計算餘弦相似性。注意,輸出範圍從0到1,因為打分都是正的。

下一步是做出預測。你已經建立了相似性矩陣:user_similarityitem_similarity,因此,你可以通過為基於使用者的CF應用下面的公式做出預測:

你可以將使用者ka之間的相似性看成權重,它乘以相似使用者a (校正的平均評分使用者)的評分。你需要規範化該值,使打分位於1到5之間,最後,對你嘗試預測的使用者的平均評分求和。

這裡的想法是,某些使用者可能會傾向於對所有的電影,總是給予高或低評分。這些使用者提供的評分的相對差比絕對評分值更重要。舉個例子:假設,使用者k對他最喜歡的電影打4星,而對所有其他的好電影打3星。現在假設另一個使用者t對他/她喜歡的電影打5星,而對他/她感到無聊的電影打3星。那麼這兩個使用者可能品味非常相似,但對打分系統區別對待。

當為基於產品的CF進行預測時,你無須糾正使用者的平均打分,因為查詢使用者本事就是用來做預測的。

評估

有許多評價指標,但其中最受歡迎的用來度量預測評分的準確性的指標是均方根誤差 (RMSE)

你可以使用sklearnmean_square_error (MSE)函式,其中,RMSE僅僅是MSE的平方根。要了解更多不同的評價指標,你可以看看這篇文章

由於你只是想要考慮測試資料集中的預測評分,因此,使用prediction[ground_truth.nonzero()]篩選出預測矩陣中的所有其他元素。

基於記憶體的演算法事很容易實現併產生合理的預測質量的。

基於記憶體的CF的缺點是,它不能擴充套件到真實世界的場景,並且沒有解決眾所周知的冷啟動問題,也就是當新使用者或新產品進入系統時。基於模型的CF方法是可擴充套件的,並且可以比基於記憶體的模型處理更高的稀疏度,但當沒有任何評分的使用者或產品進入系統時,也是苦不堪言的。

基於模型的協同過濾

基於模型的協同過濾是基於矩陣分解(MF),它已獲得更大的曝光,它主要是作為潛變數分解和降維的一個無監督學習方法。矩陣分解廣泛用於推薦系統,其中,它比基於記憶體的CF可以更好地處理與擴充套件性和稀疏性. MF的目標是從已知的評分中學習使用者的潛在喜好和產品的潛在屬性(學習描述評分特徵的特徵),隨後通過使用者和產品的潛在特徵的點積預測未知的評分。

當你有一個非常稀疏的多維矩陣時,通過進行矩陣分解可以調整使用者-產品矩陣為低等級的結構,然後你可以通過兩個低秩矩陣(其中,每行包含該本徵向量)的乘積來代表該矩陣。你通過將低秩矩陣相乘,在原始矩陣填補缺少項,以調整這個矩陣,從而儘可能的近似原始矩陣。

讓我們計算MovieLens資料集的稀疏度:

舉例說明使用者和產品的學習隱藏偏好:假設MovieLens資料集中有以下資訊:(user id, age, location, gender, movie id, director, actor, language, year, rating)。通過應用矩陣分解,模型學習到重要的使用者特徵是年齡組(10歲以下,10-18歲,18-30歲,30-90歲),位置和性別,而對於電影特性,它學習到年份,導演和演員是最重要的。現在,如果你看看你所儲存的資訊,其中並沒有年份這樣的特性,但該模型可以自己學習。重要方面是,CF模型僅使用資料(user_id, movie_id, rating)來學習潛在特徵。如果只有少數可用的資料,那麼基於模型的CF模式將預測不良,因為這將更難以學習潛在特徵。

同時使用評分和內容特性的模型稱為混合推薦系統,其中,協同過濾和基於內容的模型相結合。混合推薦系統通常比協同過濾或基於內容的模型自身表現出更高的精度:它們有能力更好的解決冷啟動問題,因為如果你沒有一個使用者或者一個產品的評分,那麼你可以使用該使用者或產品的後設資料進行預測。混合推薦系統將在未來的教程中介紹。

SVD

一個眾所周知的矩陣分解方法是奇異值分解(SVD)。通過使用奇異值分解,協同過濾可以被近似一個矩陣X所制定。Netflix Prize比賽中的獲勝隊伍使用SVD矩陣分解模型來生成產品建議,更多的資訊,推薦閱讀文章:Netflix推薦:5星之外Netflix Prize和SVD

一般的方程可以表示為:

給定m x n矩陣X

  • U是一個(m x r)正交矩陣
  • S是一個對角線上為非負實數的(r x r)對角矩陣
  • V^T是一個(r x n)正交矩陣

S的對角線上的元素被稱為X的奇異值

矩陣X可以被分解成USVU矩陣表示對應於隱藏特性空間中的使用者的特性矩陣,而V矩陣表示對應於隱藏特性空間中的產品的特性矩陣。

現在,你可以通過U, SV^T的點積進行預測了。

草草解決只有相對較少為人所知的問題是非常容易出現的過度擬合。SVD可能會非常緩慢,並且計算成本比較高。更近期的工作通過應用交替最小二乘或隨機梯度下降最小化平方誤差,並使用正則項以防止過 度擬合。你可以看到我們之前的一個關於隨機梯度下降的教程,以獲取更多詳細資訊。用於CF的交替最小二乘和隨機梯度下降的方法將在未來的教程中介紹。

總結一下:

  • 在這篇文章中,我們講了如何實現簡單的協同過濾方法,包括基於記憶體的CF和基於模型的CF。
  • 基於記憶體的模型是基於產品或使用者之間的相似性,其中,我們使用餘弦相似性。
  • 基於模型的CF是基於矩陣分解,其中,我們使用SVD來分解矩陣。
  • 構建在冷啟動的情況下(其中,對於新使用者和新產品來說,資料不可用)表現良好的推薦系統仍然是一個挑戰。標準的協同過濾方法在這樣的設定下表現不佳。在接下來的教程中,你將深入研究這一問題。

相關文章