梯度下降的矩阵分解公式推导与实例分析

梯度下降的矩阵分解公式推导与实例分析

注:此博客只是作者在学习的过程中的一些记录和浅疏的理解,内容多为借鉴和自己的一些总结。

当我们了解和学习过梯度下降之后,对于矩阵分解的学习会更直接易懂。
矩阵分解就是将一个大的矩阵分解成两个行对应列相等的两个小矩阵,用两个小的矩阵去预测大的矩阵的取值通。俗来说就是矩阵相乘的逆运算。在这里我们还要借用损失函数,构造损失函数(loss function)。接下来让我们看一些例子和相关理论介绍。

一,基于矩阵分解的推荐算法相关理论介绍

如图1,是一个用户对物品的评分距图
在这里插入图片描述
U1,2,3,4,5表示五个用户,D1,2,3,4表示四个不同的物品,表中的数据表示用户对物品的打分 评价。- 则表示没有打分。现在我们的目的就是把这些没有打分的通过方法预测出来。这也是矩阵分解的主要内容。

那我们该如何预测这些数值呢?

对于缺失的评分,可以转化为基于机器学习的回归问题,也就是连续值的预测。

对于矩阵分解有如下式子,假设R是图1的评分矩阵,N ∗ * M维度(N为行,M为列),我们可以将其分解为用户-特性矩阵P,以及物品-特性矩阵Q。其中P矩阵维度N ∗ * K,Q矩阵维度M ∗ * K。所以我们可以得到式子1
在这里插入图片描述
其中Q T ^{T} T是对Q矩阵进行转置,便于矩阵之间的计算。

二,对于P,Q矩阵的解释

P矩阵是N个用户对K个主题的关系,Q矩阵是K个主题跟M个物品的关系,这里K是我们引入的一个参数,在这里不予讨论。在算法里面K是一个参数,需要调节,通常是10~100之间。

然后我们便可以通过公式得到我们想要的那些预测值。
在这里插入图片描述
式子2的左边 r ^ i j \hat{r}_{ij} r^ij表示的是 R ^ \hat{R} R^ 第i行,第j列的预测元素值。但是得到预测值是远远不够的,我们还要判断得到的预测值与实际的值误差大不大,如果误差很大,那便没有意义。

三,构造损失函数

所以,这里我们又用到了损失函数来判断两者的相对误差大小。如式子3:
在这里插入图片描述
构造完损失函数,我们便可以运用梯度下降里面的知识对两个参数进行不断地迭代,更新P和Q的值。
在这里插入图片描述

P,Q矩阵求出来以后,对于每个用户i对商品j的评价就是:
p(i,1)*q(1,j)+p(i,2)*q(2,j)+…+p(i,k)*q(k,j)。

一般的为了防止过拟合问题,会对上述式子4加入正则化运算。
四,算法终止

每次更新完 R ^ \hat{R} R^后,计算一次loss值,若loss值非常小或者到达最大迭代次数,结束算法。于是就得到了我们最终的预测矩阵 R ^ \hat{R} R^

五,手工实例
在这里插入图片描述
在这里插入图片描述
六,代码实现

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):
        # 更新$\hat{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))

代码转载出处:

@Author:华阳

@File:MF.py

@Software:PyCharm

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值