矩陣分解

無理詩人發表於2020-12-06

基於推薦系統的矩陣分解

矩陣分解就是把原來的大矩陣,近似的分解成小矩陣的乘積,在實際推薦計算時不再使用大矩陣,而是使用分解得到的兩個小矩陣

我們知道要做推薦系統,最基本的資料就是使用者-物品的評分矩陣

在這裡插入圖片描述上圖中:
​ 矩陣中,描述了5個使用者(U1,U2,U3,U4 ,U5)對4個物品(D1,D2,D3,D4)的評分(1-5分),- 表示沒有評分,現在目的是把沒有評分的 給預測出來,然後按預測的分數高低,給使用者進行推薦。

​ 如何預測缺失的評分呢?

  1. 對於缺失的評分,可以轉化為基於機器學習的迴歸問題,也就是連續值的預測,對於矩陣分解有如下式子,R是類似圖1的評分矩陣,假設NM維(N表示行數,M表示列數),可以分解為P跟Q矩陣,其中P矩陣維度NK,P矩陣維度K*M。

式子1 式1

  1. 對於P,Q矩陣的解釋,直觀上,P矩陣是N個使用者對K個主題的關係,Q矩陣是K個主題跟M個物品的關係,至於K個主題具體是什麼,在演算法裡面K是一個引數,需要調節的,通常10~100之間。

在這裡插入圖片描述式2

  1. ​ 對於式子2的左邊項,表示的是R^第i行,第j列的元素值,對於如何衡量,我們分解的好壞呢,式子3,給出了衡量標準,也就是損失函式,平方項損失,最後的目標,就是每一個元素(非缺失值)的e(i,j)的總和
    最小

式子3
式3

  1. 下面既是基於梯度下降的優化演算法,p,q裡面的每個元素的更新方式
    在這裡插入圖片描述
    式4
  2. 不停迭代直到演算法最終收斂(直到sum(e^2) <=閾值)

程式碼如下:

import matplotlib.pyplot as plt
from math import pow
import numpy


def matrix_factorization(R,P,Q,K,steps=5000,alpha=0.0002,beta=0.02):
    Q=Q.T  # .T操作表示矩陣的轉置
    result=[]
    for step in range(steps):
        for i in range(len(R)):
            for j in range(len(R[i])):
                if R[i][j]>0:
                    eij=R[i][j]-numpy.dot(P[i,:],Q[:,j]) # .dot(P,Q) 表示矩陣內積
                    for k in range(K):
                        P[i][k]=P[i][k]+alpha*(2*eij*Q[k][j]-beta*P[i][k])
                        Q[k][j]=Q[k][j]+alpha*(2*eij*P[i][k]-beta*Q[k][j])
        eR=numpy.dot(P,Q)
        e=0
        for i in range(len(R)):
            for j in range(len(R[i])):
                if R[i][j]>0:
                    e=e+pow(R[i][j]-numpy.dot(P[i,:],Q[:,j]),2)
                    for k in range(K):
                        e=e+(beta/2)*(pow(P[i][k],2)+pow(Q[k][j],2))
        result.append(e)
        if e<0.001:
            break
    return P,Q.T,result

if __name__ == '__main__':
    R=[
        [5,3,0,1],
        [4,0,0,1],
        [1,1,0,5],
        [1,0,0,4],
        [0,1,5,4]
    ]

    R=numpy.array(R)

    N=len(R)
    M=len(R[0])
    K=2

    P=numpy.random.rand(N,K) #隨機生成一個 N行 K列的矩陣
    Q=numpy.random.rand(M,K) #隨機生成一個 M行 K列的矩陣

    nP,nQ,result=matrix_factorization(R,P,Q,K)
    print("原始的評分矩陣R為:\n",R)
    R_MF=numpy.dot(nP,nQ.T)
    print("經過MF演算法填充0處評分值後的評分矩陣R_MF為:\n",R_MF)

#-------------損失函式的收斂曲線圖---------------

    n=len(result)
    x=range(n)
    plt.plot(x,result,color='r',linewidth=3)
    plt.title("Convergence curve")
    plt.xlabel("generation")
    plt.ylabel("loss")
    plt.show()

相關文章