矩阵分解——梯度下降

一、算法概述
对于推荐系统(Recommend System, RS),从广义上的理解为:为用户(User)推荐相关的商品(Items)。常用的推荐算法主要有:

基于内容的推荐(Content-Based Recommendation)
协同过滤的推荐(Collaborative Filtering Recommendation)
基于关联规则的推荐(Association Rule-Based Recommendation)
基于效用的推荐(Utility-Based Recommendation)
基于知识的推荐(Knowledge-Based Recommendation)
组合推荐(Hybrid Recommendation)
在推荐系统中,最重要的数据是用户对商品的打分数据,数据形式如下所示:
在这里插入图片描述
U1-U5代表用户,D1-D4代表商品。我们要做的,就是根据已有的不同用户对不同商品的评价,通过推荐算法将未评价的位置的分数预测出来。
二、算法原理
矩阵分解是指将一个矩阵分解成两个或者多个矩阵的乘积。对于上述的用户-商品矩阵(评分矩阵),记为Rm×nRm×n。可以将其分解成两个或者多个矩阵的乘积,假设分解成两个矩阵Pm×kPm×k和Qk×nQk×n,我们要使得矩阵Pm×kPm×k和Qk×nQk×n的乘积能够还原原始的矩阵Rm×nRm×n

Rm×n≈Pm×k×Qk×n= R ^ \hat{R} R^m×n(R。代表预测值)
Rm×n≈Pm×k×Qk×n= R ^ \hat{R} R^m×n
其中,矩阵Pm×kPm×k表示的是m个用户与k个主题之间的关系,而矩阵Qk×nQk×n表示的是k个主题与n个商品之间的关系。
附:矩阵乘法的计算
在这里插入图片描述
①损失函数
可以使用原始的评分矩阵Rm×n与重新构建的评分矩阵 R ^ \hat{R} R^m×n之间的误差的平方作为损失函数,即:
在这里插入图片描述

最终,需要求解所有的非“-”项的损失之和的最小值:
在这里插入图片描述
利用梯度下降法的求解过程为:

●求解损失函数的负梯度:在这里插入图片描述
●根据负梯度的方向更新变量:
在这里插入图片描述
通过迭代,直到算法最终收敛。
算法终止:每次更新完 R ^ \hat{R} R^ 后,计算一次 l o s s loss loss 值,若 l o s s loss loss 值非常小或者到达最大迭代次数,结束算法。于是就得到了我们最终的预测矩阵 R ^ \hat{R} R^
三、算法的Python实现

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([[5,3,0,1],
                [4,0,0,1],
                [1,1,0,5],
                [1,0,0,4],
                [0,1,5,4]]) #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))

初始评分矩阵:
[[5 3 0 1]
[4 0 0 1]
[1 1 0 5]
[1 0 0 4]
[0 1 5 4]]
开始矩阵分解:
loss=2.529256506258465
loss=1.3877265761063808
loss=1.2157986093378128
loss=1.1759370031122929
loss=1.166970403405529
在这里插入图片描述
得到的预测矩阵:
[[4.97823498 2.98086694 2.88980046 1.00251936]
[3.98096291 2.11915475 2.61056143 1.00070949]
[1.00253139 0.9926694 4.03255964 4.969016 ]
[0.99931173 0.8389195 3.88415261 3.98313249]
[2.52402995 1.00755381 4.98164043 3.99291049]]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值