矩阵分解算法

宇宙微尘
2024-12-26 14:25:36
本帖最后由 宇宙微尘 于 2025-1-21 16:16 编辑

一、定义(什么是矩阵分解)

矩阵分解就是预测出评分矩阵中的缺失值,然后根据预测值以某种方式向用户推荐。常见的矩阵分解方法有基本矩阵分解(basic MF),正则化矩阵分解)(Regularized MF),基于概率的矩阵分解(PMF)等。矩阵分解,直观上来说就是把原来的大矩阵,近似分解成两个小矩阵的乘积,在实际推荐计算时不再使用大矩阵,而是使用分解得到的两个小矩阵。

二、矩阵分解的原理

首先来概括的说下矩阵分解的原理。 上图中每一行u代表每个用户,每一列s 代表每个物品,矩阵中的数字代表着用户对物品的打分。?代表着用户没有给这个物品打过分。在实际数据中,我们通过数据构建的矩阵如上图一样并不是一个全部有评分的矩阵。在Netflix真实的数据集里,矩阵的稠密度仅有3%左右。那么就意味着,矩阵中有绝大部分的评分是空白的。如何得到这些空白的评分呢?矩阵分解的就是为了解决这个问题。

矩阵分解算法将m × n 维的矩阵R 分解为m × k 的用户矩阵U 和k × n 维的物品矩阵S 相乘的形式。其中,m 为用户的数量,n为物品的数量,k 为隐向量(Latent Factor)的维度。k的大小决定了隐向量表达能力的强弱,实际应用中,其取值要经过多次的实验来确定。在得到了用户矩阵U和物品矩阵I后,将两个矩阵相乘,就可以得到一个新的矩阵。那么,我们就对未被评价过的物品,有了一个预测评分。接下来,可以将评分进行排序,推荐给用户。这就是矩阵分解对于推荐系统最基本的用途。

用大白话总结一下,矩阵分解的目的就是通过分解之后的两矩阵内积,来填补缺失的数据,用来做预测评分。矩阵分解的核心是将矩阵分解为两个低维的矩阵的乘积,分别以k维的隐因子向量表示,用户向量和物品向量的内积则是用户对物品的偏好度,即预测评分。值得注意的是k 的选取是通过实验和经验而来的,因此矩阵分解的可解释性不强。

三、矩阵分解的方法

Funk-SVD的核心思想认为用户的兴趣只受少数几个因素的影响,因此将稀疏且高维的User-Item评分矩阵分解为两个低维矩阵,即通过User、Item评分信息来学习到的用户特征矩阵P和物品特征矩阵Q,通过重构的低维矩阵预测用户对产品的评分。由于用户和物品的特征向量维度比较低,因而可以通过梯度下降(Gradient Descend)的方法高效地求解。

但是Funk-SVD如何将矩阵M分解成为P和Q呢?这里采用了线性回归的思想。我们的目标是让用户的评分和用矩阵乘积得到的评分残差尽可能的小,也就是说,可以用均方差作为损失函数,来寻找最终的P和Q。即通过 User-Item 评分信息来学习到的用户特征矩阵 P 和物品特征矩阵 Q,通过重构的低维矩阵预测用户对物品的评分。

这里通过loss函数,为了防止过拟合,采用正则化的方法。

四、矩阵分解的步骤

1.首先我们要定义一个类似于上图的评分矩阵,用R表示,其维度为N × M,也就是R为N 行M列矩阵。

然后我们将其分解P矩阵与Q矩阵,其中P矩阵维度为N × K ,Q矩阵维度为K × M ,于是我们可以得到

R ≈ R\approxR≈ R ^ = P × Q

R =P×Q

对于P,Q矩阵的解释,直观上,P矩阵是N 个用户对K个主题的关系,Q矩阵是K个主题跟M个物品的关系,至于K个主题具体是什么,在算法里面K是一个参数,需要调节的,通常10 ∼ 100 之间。

2.对于R矩阵:

R^与R的维度相同,其中rij^是R^第i行第j列的元素值。

3.求损失函数并更新变量

使用原始的评分矩阵R与重新构建的评分矩阵R^之间的误差的平方作为损失函数,即:

通过梯度下降法,更新变量:

求导:

根据负梯度的方向更新变量:

4.在损失函数中加入正则化惩罚项:通常在求解的过程中,为了能够有较好的泛化能力,会在损失函数中加入正则项,以对参数进行约束。加入正则项后的计算过程如下:

通过梯度下降法,更新变量:

求导:

根据负梯度的方向更新变量:

5.算法终止:每次更新完R^后,计算一次loss值,若loss值非常小或者到达最大迭代次数,结束算法。于是就得到了我们最终的预测矩阵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):
        #更新 R^
        for i in range(N):
            for j in range(M):
                if R[j] != 0:
                    #计算损失函数
                    error = R[j]
                    for k in range(K):
                        error -= P[k]*Q[k][j]
                    #优化 P,Q 矩阵的元素
                    for k in range(K):
                        P[k] = P[k] + alpha*(2*error*Q[k][j]-beta*P[k])
                        Q[k][j] = Q[k][j] + alpha*(2*error*P[k]-beta*Q[k][j])
                    
        loss = 0.0
        #计算每一次迭代后的 loss 大小,就是原来 R 矩阵里面每个非缺失值跟预测值的平方损失
        for i in range(N):
            for j in range(M):
                if R[j] != 0:
                    #计算 loss 公式加号的左边
                    data = 0
                    for k in range(K):
                        data = data + P[k]*Q[k][j]
                    loss = loss + math.pow(R[j]-data,2)
                    #得到完整 loss 值
                    for k in range(K):
                        loss = loss + beta/2*(P[k]*P[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))

六、矩阵分解的优缺点

1.优点

①比较容易编程实现,随机梯度下降方法依次迭代即可训练出模型。比较低的时间和空间复杂度,高维矩阵映射为两个低维矩阵节省了存储空间,训练过程比较费时,但是可以离线完成;评分预测一般在线计算,直接使用离线训练得到的参数,可以实时推荐。

②预测的精度比较高,预测准确率要高于基于领域的协同过滤以及内容过滤等方法。

③非常好的扩展性,很方便在用户特征向量和物品特征向量中添加其它因素,例如添加隐性反馈因素的SVD++,;添加时间动态Time SVD++,此方法将偏置部分和用户兴趣都表示成一个关于时间的函数,可以很好的捕捉到用户的兴趣漂移。

2.缺点

①模型训练比较费时。

②推荐结果不具有很好的可解释性,分解出来的用户和物品矩阵的每个维度无法和现实生活中的概念来解释,无法用现实概念给每个维度命名,只能理解为潜在语义空间。
————————————————

本文转载自CSDN博主:涵~~

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/crhispretty/article/details/126312651

542
0
0
0
关于作者
相关文章
  • 交替方向乘子法(ADMM):原理、算法流程、实例与扩展应用综述 ...
    本文全面介绍了ADMM算法的定义、背景、起源与延伸、问题模型、增广拉格朗日函数、算法流程以及应 ...
    了解详情 
  • 求解整数规划问题的割平面法和分支定界法
    整数规划整数规划问题是优化变量必须取整数值的线性或非线性规划问题,不过,在大多数情况下,整 ...
    了解详情 
  • 优化算法 | 混合整数规划问题之Benders解耦法
    算法背景Benders分解算法是 J.F.Benders 在1962年首先提出的,旨在解决某些大规模优化问题,其核 ...
    了解详情 
  • 最优化算法—整数规划
    1.整数规划问题1.1.定义在数学规划问题中一部分变量或者全部变量为整数变量的话,该数学规划问题 ...
    了解详情 
  • 【数学建模】求解混合整数线性规划 MILP 问题
    实验介绍混合整数线性规划(Mixed Integer Linear Programming,MILP)是一类优化问题,其中目标 ...
    了解详情 
在本版发帖返回顶部
快速回复 返回顶部 返回列表
玻色有奖小调研
填写问卷,将免费赠送您5个100bit真机配额
(单选) 您是从哪个渠道得知我们的?*
您是从哪个社交媒体得知我们的?*
您是通过哪个学校的校园宣讲得知我们的呢?
取消

提交成功

真机配额已发放到您的账户,可前往【云平台】查看