參考自鄒博的博客!
LFM:將評分矩陣分解爲 item-feature 和 user-feature矩陣,feature數量事先人工確定,但是這兩個矩陣參數未知,首先隨機選取參數,再以此梯度下降迭代即可得到。
import pandas as pd
import numpy as np
def lfm(user_item,k,alpha = 0.01,lamda = 0.01):
"""user_item is matrix of user item,k is the number of latent number"""
if not isinstance(user_item,list):
raise("user item:{user_item} is not a matrix list!".format(user_item=user_item))
mat = np.array(user_item)
user_number,item_number = mat.shape
# init the user and item latent matrix
u = np.random.rand(user_number,k)
v = np.random.rand(item_number,k)
for it in range(1000):
for i in range(user_number):
for j in range(item_number):
# err
err = user_item[i][j] - np.dot(u[i],v[j])
for r in range(k):
gu = err * v[j][r] + lamda * u[i][r]
gv = err * u[i][r] + lamda * v[j][r]
u[i][r] += alpha * gu
v[j][r] += alpha * gv
return u,v
if __name__ == "__main__":
mat = [[5,5,0,5],[5,0,3,4],[3,4,0,3],[0,0,5,3],[5,4,4,5],[5,4,5,5]]
u,v = lfm(mat,3)
print u
print v
print np.dot(u,v.T)
初始評分矩陣
[[5,5,0,5],[5,0,3,4],[3,4,0,3],[0,0,5,3],[5,4,4,5],[5,4,5,5]]
迭代後的u v 矩陣
[[ 0.18447051 2.09168616 0.8831042 ]
[ 1.7912757 1.24549537 -0.48677593]
[-0.1002325 1.29114151 0.86229546]
[ 1.38787106 -0.70947744 0.76619629]
[ 1.26487691 1.27983092 1.02112708]
[ 1.48243041 1.08592233 1.13930052]]
[[ 1.30296976 2.33056037 0.22352664]
[-0.38291845 1.51851172 2.39872099]
[ 2.63593771 -0.74171661 1.47001405]
[ 1.59681827 1.36696209 1.48520738]]
預測的結果
[[ 5.31255767 5.22393338 0.23298999 4.46541444]
[ 5.12787282 0.03774717 3.08231911 3.83992351]
[ 3.07122934 4.06740062 0.04571872 2.88557601]
[ 0.3261393 0.22909989 5.31089216 2.38430948]
[ 4.85906868 3.9084925 3.88593604 5.28584437]
[ 4.71703356 3.81419992 4.77693537 5.54368417]]
結果接近,效果還行。
如果來一個未對item1評分的user1,但是user1和item1的feature我們知道即上面的u1和v1,只需要u1 * v1.T即可得到5.31. 這樣就可以有針對性的進行推薦了。