目录
五、代码
一、矩阵分解
1、提出问题
那么,如何根据目前的矩阵R(5,4)如何对未打分的商品进行评分的预测(如何得到分值为0的用户的打分值)?
思路:如果说两个矩阵相乘可以得到一个预测矩阵
补充:第一点矩阵相乘必须要第一个矩阵的列数等于第二个矩阵的行数
第二点矩阵相乘的方法
预测矩阵与原矩阵的差值的平方(保证是正数)小于某一个很小的值,那么可以从预测矩阵近似得到未评分用户的评分
这个函数也称之为损失函数,这是人工智能中非常重要的函数。
二、损失函数(Loss Function)
1、定义:是定义在单个样本上的,是指一个样本的误差。
2、构建损失函数:
首先写出预估矩阵的值的计算公式如下:
其次构建损失函数:
最终需要求解所有非负项的损失之和的最小值:
三、梯度下降 (非常重要)
1、定义
梯度在向量微积分中,标量场的梯度是一个向量场。标量场中某一点上的梯度指向标量场增长最快的方向,梯度的长度是这个最大的变化率。
假如我们的损失函数是二次函数,那么导数就是我们最好的向导,导数为零的点即为损失函数最低的点
方向有了,那么步长(学习率)怎么确定呢?(W为函数某点的导数)
W新=W旧+学习率(步长)
2、与损失函数的联系:损失函数要找到最小的点,可以通过梯度下降(沿着最优的方向与步长不断迭代)的方法来进行。
3、利用梯度下降法求解损失函数的过程
首先,使用梯度下降法获得修正的p和q分量
然后,依据负梯度的方向更新变量
最后,不断迭代直到算法最终收敛(直到sum(e^2) <=阈值)
四、正则化
1、目的:为了防止过拟合(过拟合:为得到一致假设而使假设变得过度复杂称为过拟合。)
2、方法:常用的正则化方法有L1正则化和L2正则化
3、加入正则项的损失函数求解
通常在求解的过程中,为了能够有较好的泛化能力,会在损失函数中加入正则项,以对参数进行约束,加入正则的损失函数为:
总结:通过梯度下降和正则化从而求解出构建的损失函数预测未打分顾客的评分
五、代码实现
# !/usr/bin/env python
# encoding: utf-8
__author__ = 'Scarlett'
#矩阵分解在打分预估系统中得到了成熟的发展和应用
# from pylab import *
import matplotlib.pyplot as plt
from math import pow
import numpy
def matrix_factorization(R,P,Q,K,steps=5000,alpha=0.0002,beta=0.02):
Q=Q.T # .T操作表示矩阵的转置
result=[]
for step in range(steps):
for i in range(len(R)):
for j in range(len(R[i])):
if R[i][j]>0:
eij=R[i][j]-numpy.dot(P[i,:],Q[:,j]) # .dot(P,Q) 表示矩阵内积
for k in range(K):
P[i][k]=P[i][k]+alpha*(2*eij*Q[k][j]-beta*P[i][k])
Q[k][j]=Q[k][j]+alpha*(2*eij*P[i][k]-beta*Q[k][j])
eR=numpy.dot(P,Q)
e=0
for i in range(len(R)):
for j in range(len(R[i])):
if R[i][j]>0:
e=e+pow(R[i][j]-numpy.dot(P[i,:],Q[:,j]),2)
for k in range(K):
e=e+(beta/2)*(pow(P[i][k],2)+pow(Q[k][j],2))
result.append(e)
if e<0.001:
break
return P,Q.T,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=numpy.array(R)
N=len(R)
M=len(R[0])
K=2
P=numpy.random.rand(N,K) #随机生成一个 N行 K列的矩阵
Q=numpy.random.rand(M,K) #随机生成一个 M行 K列的矩阵
nP,nQ,result=matrix_factorization(R,P,Q,K)
print("原始的评分矩阵R为:\n",R)
R_MF=numpy.dot(nP,nQ.T)
print("经过MF算法填充0处评分值后的评分矩阵R_MF为:\n",R_MF)
#-------------损失函数的收敛曲线图---------------
n=len(result)
x=range(n)
plt.plot(x,result,color='r',linewidth=3)
plt.title("Convergence curve")
plt.xlabel("generation")
plt.ylabel("loss")
plt.show()
运行结果: