1. 程式人生 > 其它 >python實現推薦系統矩陣分解(Matrix Decomposition)提取特徵向量

python實現推薦系統矩陣分解(Matrix Decomposition)提取特徵向量

技術標籤:機器學習資料探勘自然語言處理機器學習

文章目錄


前言

矩陣分解是推薦系統中常用的方法,其目的是提取使用者的特徵向量,以及被打分推薦物品的特徵向量。相當於一中embedding的方法,適用於使用者極多,被推薦物體數量極大,導致的由於矩陣中存在較多空缺而無法進行推薦的情況。


一、Matrix Decomposition數學原理

在這裡插入圖片描述

R為原始矩陣,P和Q使我們要通過學習得到的矩陣,最終P*Q的結果即為我們對於R中空缺值填入後的結果。

在這裡插入圖片描述
加上正則化的LOSS損失函式表示式如上所示,r為原始矩陣的元素,β為正則化係數。在這裡我們通過反向傳播(Backward Propagation)進行學習,損失函式的偏導數如下。

在這裡插入圖片描述
α為學習率(learning rate),這裡偏導數並不難求,通過對上面的損失函式手推即可退出。
得到損失函式以及偏導數後我們就可以程式設計實現了。

二、python實現

程式如下所示:

需要十分注意的是,該演算法的核心就是用原始矩陣中真正有使用者打分的元素的值,填充特徵矩陣,生成預測矩陣。而非用預測矩陣逼近原始矩陣!!!所以必須通過判斷原始矩陣在某處是否有值,若有值則通過該值進行梯度下降更新特徵值矩陣,若沒有則不更新(注意!)。由於numpy中沒有隻運算有值處元素的API,因此只能通過遍歷進行。

**

實際應用中應注意

**

由於我用來提取軌跡中使用者的特徵因此原始矩陣較大,需要注意的矩陣越大,越要調低learning rate,否則可能出現不收斂的情況。

對於K的選取,K越低最低損失自然也是越大,由於存在大量空值,預測矩陣對這些空值進行了填值,因此評價損失還應該用原始矩陣中存在的值來進行。


import numpy as np
import matplotlib.pyplot as plt
import time

def LOSS(matrix1,matrix2):
    return sum(sum((matrix1-matrix2)**2))**0.5 

def gradiantdecentMD(matrix,K,learningrate,regularate,epoch):
    los=[]
    m1=np.random.
rand(matrix.shape[0],K) m2 = np.random.rand(matrix.shape[1], K) for ep in range(epoch): print(ep) predict=np.dot(m1,m2.T) for i in range(m1.shape[0]): for j in range(m2.shape[0]): if matrix[i][j]!=0: lo = loss(true=matrix, m1=m1, m2=m2, i=i, j=j) for k in range(K): m1[i][k] = m1[i][k] + learningrate * (2 * lo * m2[j][k] - regularate * m1[i][k]) m2[j][k] = m2[j][k] + learningrate * (2 * lo * m1[i][k] - regularate * m2[j][k]) los.append(LOSS(predict,matrix)) print(LOSS(predict,matrix)) if ep>10: if los[-5] - los[-1]<10: break plt.plot(range(los.__len__()), los) plt.show() return m1,m2 def main(): K=10 epoch=50000 regularrate=0.01 learningrate=0.001 test=np.array([ [5, 3, 0, 1], [4, 0, 0, 1], [1, 0, 0, 4], [0, 1, 5, 4], [0, 1, 5, 4]]) t1 = time.time() userfeature, itemfeature = gradiantdecentMD(test, K, learningrate, regularrate, epoch) t2 = time.time() print(t2 - t1) print(np.dot(userfeature,itemfeature.T)) np.savetxt(fname='data/userfeature_1000.txt', X=userfeature) np.savetxt(fname='data/itemfeature_1000.txt', X=itemfeature) if __name__ == '__main__': main()

總結

總之用於對大量含有空值的矩陣進行學習,與Node2Vec相比無需構成網路,在使用資料填充原始矩陣時也需要一定的方法,才能使原始矩陣更容易被學習,學習效果更好。

http://www.quuxlabs.com/blog/2010/09/matrix-factorization-a-simple-tutorial-and-implementation-in-python/#source-code