对矩阵分解(MF)正则项的理解

在矩阵分解中,我们对得到的损失函数

\sum_{p,q}^{}e_{pq}^{2}=\sum_{p,q}^{}(r_{pq}-\sum_{k=1}^{K}p_{ik}q_{kj})^{2}

而在优化目标中,我们在损失函数后加上了正则项\lambda (\left \| p \right \|^{2}+\left \| q \right \|^{2}),下面我们就对正则项系数\lambda进行分析实验。

函数拟合分析

过拟合

过拟合表现为在训练集上测试较为准确而在测试集中测试准确度较低。一般会导致为损失函数值较大。因此,我们可以在所定义的损失函数后面加入一项永不为0的部分,那么最后经过不断优化损失函数还是会存在。其实这就是所谓的“正则化”。

欠拟合

欠拟合表现为在训练集正确度比较低,在测试集上测试正确度较低。而在实际中随着迭代次数的增大,基本不会出现欠拟合现象。

矩阵分解代码

# -*- coding: utf-8 -*-

from math import *
import  numpy as np
import matplotlib.pyplot as plt
#调用math、numpy、matplotlib库
 
def MF(R,P,Q,K,aplha,beta,steps):
    '''
    :param R: 用户-物品评分矩阵 m*n
    :param P: 用户的分解矩阵 m*k
    :param Q: 物品的分解矩阵 k*n
    :param K: 隐向量的维度
    :param aplha: 学习率
    :param beta: 正则化参数 
    '''
    print('开始分解原矩阵')
    Q=Q.T
    result=[]
    #开始训练  更新参数 计算损失值
    #更新参数 使用梯度下降方法
    print('开始训练')
    for step in range(steps):#训练次数
        ''''''
        for i in range(len(R)):
            for j in range(len(R[i])):
                eij=R[i][j]-np.dot(P[i,:],Q[:,j])#eij
                for k in range(K):#隐向量维度
                    if R[i][j]>0:
                        #梯度下降法更新参数
                        P[i][k]=P[i][k]+aplha*(2*eij*Q[k][j]-beta*P[i][k])
                        Q[k][j]=Q[k][j]+aplha*(2*eij*P[i][k]-beta*Q[k][j])
        eR=np.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] - np.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
    print('training Finshed 。。。。')
 
    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]
    ]#未进行评分用0表示
    R=np.array(R)
    N=len(R)    #原矩阵R的行数
    M=len(R[0]) #原矩阵R的列数
    K=3    #K值可根据需求改变
    P=np.random.rand(N,K) #随机生成一个 N行 K列的矩阵
    Q=np.random.rand(M,K) #随机生成一个 M行 K列的矩阵
    nP,nQ,result=MF(R,P,Q,K,aplha=0.0002,beta=0.02,steps=5000)
    print(result)
    print('原矩阵',R)         #输出原矩阵
    R_MF=np.dot(nP,nQ.T)
    print('计算出的矩阵',R_MF)      #输出新矩阵
    #画图
    plt.plot(range(len(result)),result)
    plt.xlabel("time")
    plt.ylabel("loss")
    plt.show()

改变\lambda数值观察其对矩阵分解效果的影响

1、当\lambda =0.02时,计算出的矩阵和误差-时间图如下所示:

2、当\lambda > 0.02时,观察\lambda从0.02逐渐增大到0.60时损失函数的数值变化,可以发现当\lambda=0.02时,loss值最小且接近于0,当\lambda增大到大于等于0.10时,误差已经接近8%附近,已经出现了过拟合现象,损失函数在多次迭代后值过大,如下图所示。

3、当\lambda < 0.02时,观察\lambda从0.02逐渐减小到0.001过程中损失函数值的变化情况,可以发现\lambda再减小后,损失函数值基本不再发生改变并且接近于0。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值