代码链接: github.
1. 用隐语义模型来进行协同过滤的目标
2. 通过矩阵分解进行降维分析
3. 隐语义模型实例
用户对电影的评分矩阵R分解为用户特征矩阵P跟电影特征矩阵Q(f1,f2,f3,f4为相应的特征):
反过来,用户特征矩阵P乘以电影特征矩阵Q得到用户的评分矩阵,其中用户评分矩阵R中的元素就是矩阵P与矩阵Q中相应特征向量的点积,反映的是用户特征与物品特征的契合程度,故R中数字越大反映用户对物品喜好程度越大。
损失函数
1. 交替最小二乘法( Alternating Least Squares , ALS )
2. ALS算法
3. 求解过程
为了便于理解,代码是基于Jupyter编辑器实现,每一个步骤有对应的输出结果。
代码链接: github.
import numpy as np
import pandas as pd
#评分矩阵R
R = np.array([[4,0,2,0,1],
[0,0,2,3,1],
[4,1,2,0,1],
[4,1,2,5,1],
[3,0,5,0,2],
[1,0,3,0,4]])
'''
@输入参数
R:M*N的评分矩阵
K:隐特征向量维度
max_iter:最大迭代次数
alpha:步长
lamda:正则化系数
@输出
分解之后的P、Q
P:初始化用户特征矩阵M*k
Q:初始化物品特征矩阵N*K
'''
#给定超参数
K= 5
max_iter = 5000
alpha = 0.0002
lamda = 0.004
#核心算法
def LFM_grad_desc(R,K,max_iter,alpha=0.0002,lamda = 0.002):
#基本维度参数定义
M = len(R)
N = len(R[0])
#P、Q初始值,随机生成
P = np.random.rand(M,K)
Q = np.random.rand(N,K)
Q = Q.T
#开始迭代
for step in range(max_iter):
#对所有的用户u、物品i做遍历,对应的特征向量Pu,Qi梯度下降
for u in range(M):
for i in range(N):
#对于每一个大于0的评分,求出预测的评分误差
if R[u][i] > 0:
eui = np.dot(P[u,:],Q[:,i]) - R[u][i]
#带入公式,按照梯度下降算法更新当前的Pu与Qi
for k in range(K):
P[u][k] = P[u][k] - alpha * (2 * eui * Q[k][i] + 2 * lamda * P[u][k])
Q[k][i] = Q[k][i] - alpha * (2 * eui * P[u][k] + 2 * lamda * Q[k][i])
#u、i遍历完成,所有的特征向量更新完成,可以得到P、Q,可以计算预测评分矩阵
predR = np.dot(P,Q)
#计算当前损失函数
cost = 0
for u in range(M):
for i in range(N):
if R[u][i] > 0:
cost += (np.dot(P[u,:],Q[:,i]) - R[u][i]) ** 2
#加上正则化项
for k in range(K):
cost += lamda * (P[u][k] ** 2 + Q[k][i] ** 2)
if cost < 0.001:
break
return P,Q.T,cost
P,Q,cost = LFM_grad_desc(R,K,max_iter,alpha,lamda)
'''
print(P)
print(Q)
print(cost)
print(R)
'''
predR = P.dot(Q.T)
#预测矩阵
predR
输出结果:
array([[3.94148951, 1.22116106, 2.07332208, 4.72376533, 0.91906299],
[2.67232719, 0.74839699, 1.98552529, 3.03276144, 0.97156313],
[3.9330541 , 0.94175409, 2.10780256, 4.09245595, 0.88109636],
[4.09412304, 1.05343721, 1.87535923, 4.92277698, 1.17325781],
[3.04067184, 1.03100579, 4.90618167, 3.34662411, 2.08753076],
[0.96925078, 0.10826894, 3.05169384, 3.81235739, 3.92397575]])
从输出的预测矩阵就可以看出,原先矩阵中为 0 的位置现在已经有了相应的预测值。