推薦系統——基於隱因子矩陣分解的協同過濾算法


  在新手接觸推薦系統這個領域時,遇到第一個理解起來比較困難的就是協同過濾法。那么如果這時候百度的話,得到最多的是奇異值分解法,即(SVD)。SVD的作用大致是將一個矩陣分解為三個矩陣相乘的形式。如果運用在推薦系統中,首先我們將我們的訓練集表示成矩陣的形式,這里我們以movielen數據集為例。這個數據集包含了用戶對電影的評分。那么矩陣形式大致為:

  movie1  movie2  movie3 moive4
user1 1      
user2 2     3
user3   5 4  
user4 2     4

  其中1~5就是對應用戶對電影的評分。空余處表示數據集中沒有對應用戶和電影的信息。如果我們想使用SVD,一般講空余處都填為0.假設此矩陣為V.那么運用SVD可以得到

                          V = UΣVT

  但是上面的等號並不能取到,只能是約等於。那么我們將得到的三個矩陣相乘得到V'(注意與V不同)。那么原來的空白處(也就是0處)可能就不再為0,那么這就是對該user-moive對的預測。這就是SVD的主要原理。因為SVD有很多現成的算法,也不用迭代就可直接得到,所以使用比較方便。

 

  但是我們會看到,上面方法有一個致命的缺陷,那就是將未知的評分全都設為0.這其實是極其不合理的,因為用戶不給某個電影打分並不是很不喜歡(0分),而是有可能還沒有看過這個電影。這樣就加入了我們主觀臆斷的信息,最后造成錯誤。解決的方法就是使用隱因子的矩陣分解法。注意矩陣分解法和SVD有相似的地方也有不同的地方,下面我就對矩陣分解法進行詳細介紹。

  在矩陣分解法中,有一個假設,就是每一個用戶都有一個長度為k的特征向量,每一部電影也有一個相同長度的特征向量(k一般需要用戶指定)。那么所有用戶的特征向量排列成一個矩陣 U 的維度為UserNum * k。其中用戶i對應的向量為Ui。所有電影的特征向量排列成一個矩陣M 的維度為MoiveNum * k。其中電影j對應的向量為Uj。那么用戶i對電影j的評分 Vij = <Ui , Mj>(<>代表點乘)。那么所有用戶和所有電影之間的評分就可以用兩個矩陣相乘來得到:

                          V' = UMT

  注意這里是V'而不是V。那么問題來了,我們如何確定這個U和M?一個自然的想法就是讓V'和V盡可能地相等。那么這又有一個問題,那就是V(即數據集)有很多地方是沒有評分的,如何判斷和V'是否相等?那么我們在這里只計算有評分處的MSE。這樣既沒有使用額外的信息,又能判斷兩者是否接近。那么自然而然得就引入了我們的lost function:

      

  這里Iij表示用戶i對電影j有評分記錄。后面兩項是懲罰因子,目的是防止過擬合。那么利用梯度下降法,我們就可以通過迭代得到U和M的值。其對U和對M的求到如下:

  到這里我們就已經完成了基礎的矩陣分解法。那么進一步,為了實現更好的效果,我們要考慮每個個體打分的影響,因為有些用戶打分偏高,有些用戶打分偏低。同樣對於電影和所有的評分。所以我們評分的計算公式應該改為:

      Vij = <Ui,Mj> + overall_mean + ai +bj

  其中overall_mean是所有評分的平均值,ai是用戶i打分的平均值,bj是電影j得分的平均值。其中overall_mean認為是一個常數,而ai和bj都是需要優化的參數。這里我們就不給出對他們求導的式子,我直接給出矩陣形式的算法,便於大家具體實現。(INCOMING) (拖了一周左右放上去,這拖延症也是沒sei了 0.0)

 

  我自己寫了一個python版的,有興趣可以參考 https://github.com/ccienfall/RecommandSystem/blob/master/script/Factorize.py

  在2016Byte Cup國際機器學習競賽的數據集上分別運用SVD和矩陣分解(MF),最后結果是MF的方法能比SVD的效果高20%左右。

  參考文獻:《A Guide to Singular Value Decomp osition for Collaborative Filtering》


免責聲明!

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



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