矩阵分解
1预测矩阵
预测矩阵一般用符号R`来表示,有
,(R`与R的维度相同,其中 是第i行第j列的元素值。
2构造损失函数(平方法)
使用原始的评分矩阵R与重新构建的评分矩阵之间的误差的平方作为损失函数,即:
通过梯度下降法,更新变量:
求导:
根据负梯度的方向更新变量:
3算法终止:
每次更新完R’ 后,计算一次loss值,若loss值非常小或者到达最大迭代次数,结束算法。于是就得到了我们最终的预测矩阵R’
4 过拟合问题与正则化
1 理论概述
(啥也不懂 )
过拟合问题(over-fitting)指为了得到一致的假设而使假设变得过度严格(这里的假设可以理解为构建的函数模型)。简单来说就是在训练集中训练出过于完美的模拟,而在测试集中失效的问题。通俗来说就是拟合的越好,但相应预测的能力可能变得很差。
具体解决方法为正则化。即在损失函数加入正则项。 损失函数中加入正则化惩罚项:通常在求解的过程中,为了能够有较好的泛化能力,会在损失函数中加入正则项,以对参数进行约束。
5 矩阵分解与基于用户的协同过滤的比较
方法一:矩阵分解法
商品1 | 商品2 | 商品3 | 商品4 |
---|---|---|---|
用户A | 4 | 4.523 | 3 |
用户B | 4.131 | 5 | 4 |
用户C | 5 | 4 | 2 |
用户D | 2 | 4 | 3.019 |
用户E | 3 | 4 | 5 |
方法二:协同过滤算法
用户 | 商品1 | 商品2 | 商品3 | 商品4 |
---|---|---|---|---|
用户A | 4 | 4.305 | 3 | 5 |
用户B | 4.730 | 5 | 4 | 5 |
用户C | 5 | 4 | 2 | 4.272 |
用户D | 2 | 4 | 3.481 | 3 |
用户E | 3 | 4 | 5 | 4.000 |
6代码实现
import numpy as np
import math
import matplotlib.pyplot as plt
#定义矩阵分解函数
def Matrix_decomposition(R,P,Q,N,M,K,alpha=0.0002,beta=0.02):
Q = Q.T #Q矩阵转置
loss_list = [] #存储每次迭代计算的loss值
for step in range(5000):
#更新R^
for i in range(N):
for j in range(M):
if R[i][j] != 0:
#计算损失函数
error = R[i][j]
for k in range(K):
error -= P[i][k]*Q[k][j]
#优化P,Q矩阵的元素
for k in range(K):
P[i][k] = P[i][k] + alpha*(2*error*Q[k][j]-beta*P[i][k])
Q[k][j] = Q[k][j] + alpha*(2*error*P[i][k]-beta*Q[k][j])
loss = 0.0
#计算每一次迭代后的loss大小,就是原来R矩阵里面每个非缺失值跟预测值的平方损失
for i in range(N):
for j in range(M):
if R[i][j] != 0:
#计算loss公式加号的左边
data = 0
for k in range(K):
data = data + P[i][k]*Q[k][j]
loss = loss + math.pow(R[i][j]-data,2)
#得到完整loss值
for k in range(K):
loss = loss + beta/2*(P[i][k]*P[i][k]+Q[k][j]*Q[k][j])
loss_list.append(loss)
plt.scatter(step,loss)
#输出loss值
if (step+1) % 1000 == 0:
print("loss={:}".format(loss))
#判断
if loss < 0.001:
print(loss)
break
plt.show()
return P,Q
if __name__ == "__main__":
N = 5
M = 4
K = 5
R = np.array([[4,0,3,5],
[0,5,4,0],
[5,4,2,0],
[2,4,0,3],
[3,4,5,0]]) #N=5,M=4
print("初始评分矩阵:")
print(R)
#定义P和Q矩阵
P = np.random.rand(N,K) #N=5,K=2
Q = np.random.rand(M,K) #M=4,K=2
print("开始矩阵分解:")
P,Q = Matrix_decomposition(R,P,Q,N,M,K)
print("矩阵分解结束。")
print("得到的预测矩阵:")
print(np.dot(P,Q))