推薦系統之矩陣分解及其Python代碼實現


 有如下R(5,4)的打分矩陣:(“-”表示用戶沒有打分)

其中打分矩陣R(n,m)是n行和m列,n表示user個數,m行表示item個數

那么,如何根據目前的矩陣R(5,4)如何對未打分的商品進行評分的預測(如何得到分值為0的用戶的打分值)?

——矩陣分解的思想可以解決這個問題,其實這種思想可以看作是有監督的機器學習問題(回歸問題)。

矩陣R可以近似表示為P與Q的乘積:R(n,m)≈ P(n,K)*Q(K,m)

矩陣分解的過程中,將原始的評分矩陣分解成兩個矩陣的乘積: 

 

矩陣P(n,K)表示n個user和K個特征之間的關系矩陣,這K個特征是一個中間變量,矩陣Q(K,m)的轉置是矩陣Q(m,K),矩陣Q(m,K)表示m個item和K個特征之間的關系矩陣,這里的K值是自己控制的,可以使用交叉驗證的方法獲得最佳的K值。為了得到近似的R(n,m),必須求出矩陣P和Q,如何求它們呢?

 

 【方法】

 1. 首先令

 2. 損失函數:使用原始的評分矩陣與重新構建的評分矩陣之間的誤差的平方作為損失函數,即:

      如果R(i,j)已知,則R(i,j)的誤差平方和為:

  最終,需要求解所有的非“-”項的損失之和的最小值:

 

 3. 使用梯度下降法獲得修正的p和q分量:

  •   求解損失函數的負梯度:

     

 

  •        根據負梯度的方向更新變量:

     

 

 4. 不停迭代直到算法最終收斂(直到sum(e^2) <=閾值)

 

 

(Plus:為了防止過擬合,增加正則化項

【加入正則項的損失函數求解】

 1.  首先令

 2.  通常在求解的過程中,為了能夠有較好的泛化能力,會在損失函數中加入正則項,以對參數進行約束,加入正則的損失函數為:

   

 

也即:

       

 

 3.  使用梯度下降法獲得修正的p和q分量:

  •   求解損失函數的負梯度:

        

 

  •   根據負梯度的方向更新變量:

       

 

 4. 不停迭代直到算法最終收斂(直到sum(e^2) <=閾值)

 

【預測】利用上述的過程,我們可以得到矩陣這樣便可以為用戶 i 對商品  j 進行打分:

                 

 

 

 【Python代碼實現如下】(基於Python 3.X ;使用正則項)

 1 # !/usr/bin/env python
 2 # encoding: utf-8
 3 __author__ = 'Scarlett'
 4 #矩陣分解在打分預估系統中得到了成熟的發展和應用
 5 # from pylab import *
 6 import matplotlib.pyplot as plt
 7 from math import pow
 8 import numpy
 9 
10 
11 def matrix_factorization(R,P,Q,K,steps=5000,alpha=0.0002,beta=0.02):
12     Q=Q.T  # .T操作表示矩陣的轉置
13     result=[]
14     for step in range(steps):
15         for i in range(len(R)):
16             for j in range(len(R[i])):
17                 if R[i][j]>0:
18                     eij=R[i][j]-numpy.dot(P[i,:],Q[:,j]) # .dot(P,Q) 表示矩陣內積
19                     for k in range(K):
20                         P[i][k]=P[i][k]+alpha*(2*eij*Q[k][j]-beta*P[i][k])
21                         Q[k][j]=Q[k][j]+alpha*(2*eij*P[i][k]-beta*Q[k][j])
22         eR=numpy.dot(P,Q)
23         e=0
24         for i in range(len(R)):
25             for j in range(len(R[i])):
26                 if R[i][j]>0:
27                     e=e+pow(R[i][j]-numpy.dot(P[i,:],Q[:,j]),2)
28                     for k in range(K):
29                         e=e+(beta/2)*(pow(P[i][k],2)+pow(Q[k][j],2))
30         result.append(e)
31         if e<0.001:
32             break
33     return P,Q.T,result
34 
35 if __name__ == '__main__':
36     R=[
37         [5,3,0,1],
38         [4,0,0,1],
39         [1,1,0,5],
40         [1,0,0,4],
41         [0,1,5,4]
42     ]
43 
44     R=numpy.array(R)
45 
46     N=len(R)
47     M=len(R[0])
48     K=2
49 
50     P=numpy.random.rand(N,K) #隨機生成一個 N行 K列的矩陣
51     Q=numpy.random.rand(M,K) #隨機生成一個 M行 K列的矩陣
52 
53     nP,nQ,result=matrix_factorization(R,P,Q,K)
54     print("原始的評分矩陣R為:\n",R)
55     R_MF=numpy.dot(nP,nQ.T)
56     print("經過MF算法填充0處評分值后的評分矩陣R_MF為:\n",R_MF)
57 
58 #-------------損失函數的收斂曲線圖---------------
59 
60     n=len(result)
61     x=range(n)
62     plt.plot(x,result,color='r',linewidth=3)
63     plt.title("Convergence curve")
64     plt.xlabel("generation")
65     plt.ylabel("loss")
66     plt.show()

 

運行結果如下:

 

損失函數的收斂曲線圖:

 

 

 

 【代碼的GitHub地址】

https://github.com/shenxiaolinZERO/CoolRSer/blob/master/CoolRSer/MatrixFactorization.py

 

 

【Reference】

1、 Matrix Factorization: A Simple Tutorial and Implementation in Python

2、矩陣分解在推薦系統的應用以及python代碼的實現


免責聲明!

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



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