前言
推荐系统中最为主流与经典的技术之一是协同过滤技术(Collaborative Filtering),
它是基于这样的假设:用户如果在过去对某些项目产生过兴趣,那么将来他很可能依然对其保持热忱。
目前推荐系统中用的最多的就是矩阵分解(Matrix Factorization)方法。
矩阵分解就是预测出评分矩阵中的缺失值,然后根据预测值以某种方式向用户推荐。
矩阵分解可以解决一些近邻模型无法解决的问题,近邻模型存在的问题:
1、物品之间存在相关性,信息量并不是随着向量维度增加而线性增加
2、矩阵元素稀疏,计算结果不稳定,增减一个向量维度,导致紧邻结果差异很大的情况出现。
这里以用户-项目评分为例来详解矩阵分解。
一、矩阵分解
1.案例
用户-项目评分矩阵R(M×N)
打分矩阵R(n,m)是n行m列,n表示user个数,m表示item个数,‘-’表示用户没有打分
2.思路
矩阵分解就是把大矩阵分解成两个小矩阵,
即矩阵R可近似表示为矩阵P与矩阵Q的乘积:
矩阵P(n,k)表示n个user和K个特征之间的关系矩阵,将矩阵Q(m,k)表示m个item和K个特征之间的关系矩阵,
接下来就是要求的矩阵P和Q,即可的预测矩阵R
3.推导步骤
- 首先:
- 损失函数:
- 对损失函数加入正则项:
为了防止过拟合
加入正则L2范数的损失函数为: - 使用梯度下降法更新p和q分量:
- 求解损失函数的负梯度:
- 根据负梯度的方向更新变量:
- 不停迭代,直到损失函数<=阈值;
- 对结果的输出:
输出得到的预测矩阵;
可对预测矩阵可视化,或转成表格也行;
可输出个学习效率图像。
二、python代码实例
from math import pow
import numpy as np
import matplotlib.pyplot as plt
def MF(R,P,Q,K,steps=5000,alpha=0.0002,beta=0.02):
#矩阵因子分解函数,
#steps:迭代次数,alpha:步长
n,m = R.shape #R矩阵行,列
result = []
for step in range(steps):
#进行迭代
for i in range(n):
for j in range(m):
eij = R[i][j] - np.dot(P[i,:],Q[:,j]) #.dot表矩阵乘
for k in range(K):
#更新参数
if R[i][j] != 0: #限制评分不为0,即预测评分
P[i][k] += alpha*(2*eij*Q[k][j] - beta*P[i][k])
Q[k][j] += alpha*(2*eij*P[i][k] - beta*Q[k][j])
eR = np.dot(P,Q)
e = 0 #误差
#求损失函数:
for i in range(n):
for j in range(m):
if R[i][j] != 0:
e += pow(R[i][j]-np.dot(P[i,:],Q[:,j]),2)
#加入正则化
for k in range(K):
e += (beta/2)*(pow(P[i][k],2) + pow(Q[k][j],2))
result.append(e)
if e <0.001:
break
return P,Q,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 = np.array(R)
N,M = R.shape #获取原矩阵的行列
K = 3 #k值可根据需求改变
P = np.random.rand(N,K)
Q = np.random.rand(K,M)
nP,nQ,result = MF(R, P, Q, K)
print(R)
R_MF = np.dot(nP,nQ)
print(R_MF)
plt.plot(range(len(result)),result) #学习效率
plt.show()
输出:
[[5 3 0 1]
[4 0 0 1]
[1 1 0 5]
[1 0 0 4]
[0 1 5 4]]
[[4.98721783 2.95625121 3.57560418 1.00024006]
[3.9709488 2.24242023 3.11559738 0.99765797]
[1.04748953 0.88624237 5.33748545 4.96558301]
[0.97508183 0.74294582 4.37299881 3.97589923]
[1.84618381 1.13400265 4.94201315 4.01873275]]