传统推荐模型(二)协同过滤的进化——矩阵分解算法

传统推荐模型(二)协同过滤的进化——矩阵分解算法

针对协同过滤算法的头部效应较明显、泛化能力较弱的问题,矩阵分解算法被提出。矩阵分解在协同过滤算法中“共现矩阵”的基础上,加人了隐向量的概念,加强了模型处理稀疏矩阵的能力,针对性地解决了协同过滤存在的主要问题。

1、矩阵分解算法原理

协同过滤算法找到用户可能喜欢的视频的方式很直接,即基于用户的观看历史,找到跟目标用户A 看过同样视频的相似用户,然后找到这些相似用户喜欢看的其他视频,推荐给目标用户A。

在这里插入图片描述

矩阵分解算法则期望为每一个用户和视频生成一个隐向量,将用户和视频定位到隐向量的表示空间上,距离相近的用户和视频表明兴趣特点接近,在推荐过程中,就应该把距离相近的视频推荐给目标用户。例如,如果希望为上图中的用户 Dave 推荐视频可以发现离 Dave 的用户向量最近的两个视频向量分别是“Ocean’s 11”和“The Lion King”,那么可以根据向量距离由近到远的顺序生成 Dave 的推荐列表。

在“矩阵分解”的算法框架下,用户和物品的隐向量是通过分解协同过滤生成的共现矩阵得到的。

在这里插入图片描述

矩阵分解算法将mxn维的共现矩阵R分解为mxk维的用户矩阵U和kxn维的物品矩阵V相乘的形式。其中 m 是用户数量,n 是物品数量,k是隐向量的维度。k 的大小决定了隐向量表达能力的强弱。

k 的取值越小,隐向量包含的信息越少,模型的泛化程度越高;反之,k 的取值越大,隐向量的表达能力越强但泛化程度相应降低。此外,k 的取值还与矩阵分解的求解复杂度直接相关。

基于用户矩阵U和物品矩阵V,用户u对于物品i的预估评分:

在这里插入图片描述

2、矩阵分解(MF)

(1) 特征值分解(Eigen Decomposition)

特征分解(Eigen decomposition),又称谱分解(Spectral decomposition)是将矩阵分解为由其特征值特征向量表示的矩阵之积的方法。

在这里插入图片描述

特征值分解可以得到特征值特征向量特征值表示的是这个特征到底有多重要,而特征向量表示这个特征是什么,可以将每一个特征向量理解为一个线性的子空间,我们可以利用这些线性的子空间干很多的事情。不过,特征值分解也有很多的局限,比如说变换的矩阵必须是方阵,那这也是后来又引入了奇异值分解的原因之一。

特征值分解只能作用于方阵,显然不适用于分解用户-物品矩阵。

(2) 奇异值分解(Singular Value Decomposition,SVD)

SVD是一种常用的降维数据压缩方法,核心是矩阵因子分解,即用因子分解的方式近似地表示原始矩阵,这种近似是在平方损失意义下的最优近似。

下面奇异值分解的定义、证明、计算及案例,来源于李航老师的《统计学习方法》。

奇异值分解的定义

在这里插入图片描述

在这里插入图片描述

奇异值分解例子:

在这里插入图片描述

矩阵的奇异值分解不是唯一的。

任意给定一个实矩阵,奇异值分解一定存在。

奇异值分解定理的证明

在这里插入图片描述

证明过程:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

奇异值分解的计算步骤

1、构造n阶实对称矩阵W

W = (A.T)A

2、计算W的特征值和特征向量

在这里插入图片描述

3、求得n阶正交矩阵V(利用上述求得的特征向量

在这里插入图片描述

4、求对角矩阵(利用上述求得的特征值

在这里插入图片描述

5、求解m阶正交矩阵(利用上述求得的V和对角矩阵)

在这里插入图片描述

在这里插入图片描述

奇异值分解的计算案例

1、构造n阶实对称矩阵W

在这里插入图片描述

2、计算W的特征值和特征向量

在这里插入图片描述

在这里插入图片描述

3、求得n阶正交矩阵V(利用上述求得的特征向量

在这里插入图片描述

4、求对角矩阵(利用上述求得的特征值

在这里插入图片描述

5、求解m阶正交矩阵(利用上述求得的V和对角矩阵)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

上面的算法和例题只是为了说明计算的过程,并不是实际应用中的算法。可以看出,奇异值分解算法关键在于 ATA 的特征值的计算。实际应用的奇异值分解算法是通过求 ATA 的特征值进行,但不直接计算 ATA。按照这个思路产生了许多矩阵奇异值分解的有效算法。

奇异值分解的缺点

1、传统的SVD分解,会要求原始矩阵是密的,而我们这里的这种矩阵一般情况下是非常稀疏的,如果想用奇异值分解,就必须对缺失的元素进行填充,而一旦补全,空间复杂度就会非常高,且补的不一定对。
2、然后就是SVD分解计算复杂度非常高,而我们的用户-物品矩阵非常大,所以基本上无法使用。

传统奇异值分解也不适用于解决大规模稀疏矩阵的矩阵分解问题,因此,梯度下降法成了进行矩阵分解的主要方法。

(3) Basic SVD(LFM、Funk SVD)

Funk-SVD, 也称Latent Factor Model(LFM)。 Funk-SVD的思想很简单: 把求解两个矩阵的参数问题转换成一个【最优化】问题,可以通过训练集里面的观察值利用最小化来学习用户矩阵和物品矩阵。

我们知道,如果有了用户矩阵和物品矩阵的话,我们就知道了如果想计算用户对物品的评分,只需要

在这里插入图片描述

我们有真实的r(u,i),我们可以随机初始化一个用户矩阵 U 和一个物品矩阵 V,我们就可以计算一个猜测的r^(u,i),那么这个猜测的和真实值之间就会有一个误差,有了误差,我们就可以计算出总的误差平方和,有了损失,我们就可以想办法进行训练,把SSE降到最小,那么我们的两个矩阵参数就可以算出来。所以就把这个问题转成了最优化的的问题。

预测函数

在这里插入图片描述

损失函数(误差平方和)

在这里插入图片描述

优化目标

在这里插入图片描述

梯度下降

求梯度

在这里插入图片描述

梯度更新

在这里插入图片描述

1、首先先初始化这两个参数矩阵U和V
2、通过两个隐向量乘积得到预测值pred
3、根据label和pred计算损失
4、通过梯度下降的方式,更新两个隐向量的值
5、未评过分的那些样本当做测试集,通过两个隐向量就可以得到测试集的label值这样就填充完了矩阵,下一步就可以进行推荐了
import random
import math


class LFM(object):

    def __init__(self, rating_data, F, alpha=0.1, lmbd=0.1, max_iter=500):
        """
        :param rating_data: rating_data是[(user,[(item,rate)]]类型
        :param F: 隐因子个数
        :param alpha: 学习率
        :param lmbd: 正则化
        :param max_iter:最大迭代次数
        """
        self.F = F
        self.P = dict()  # R=PQ^T,代码中的Q相当于博客中Q的转置
        self.Q = dict()
        self.alpha = alpha
        self.lmbd = lmbd
        self.max_iter = max_iter
        self.rating_data = rating_data

        '''随机初始化矩阵P和Q'''
        for user, rates in self.rating_data:
            self.P[user] = [random.random() / math.sqrt(self.F)
                            for x in range(self.F)]
            for item, _ in rates:
                if item not in self.Q:
                    self.Q[item] = [random.random() / math.sqrt(self.F)
                                    for x in range(self.F)]
        print(self.P)

    def train(self):
        """
        随机梯度下降法训练参数P和Q
        :return:
        """

        for step in range(self.max_iter):  # 遍历次数max_iter
            for user, rates in self.rating_data:
                for item, rui in rates:
                    hat_rui = self.predict(user, item)  # 预测得分
                    err_ui = rui - hat_rui  # 计算误差
                    for f in range(self.F):  # 梯度下降更新
                        self.P[user][f] += self.alpha * (err_ui * self.Q[item][f] - self.lmbd * self.P[user][f])
                        self.Q[item][f] += self.alpha * (err_ui * self.P[user][f] - self.lmbd * self.Q[item][f])
            self.alpha *= 0.9  # 每次迭代步长要逐步缩小

    def predict(self, user, item):
        """
        :param user:
        :param item:
        :return:
        预测用户user对物品item的评分
        """
        return sum(self.P[user][f] * self.Q[item][f] for f in range(self.F))


if __name__ == '__main__':
    '''用户有A B C,物品有a b c d'''
    rating_data = list()
    rate_A = [('a', 2.0), ('b', 1.0)]
    rating_data.append(('A', rate_A))
    rate_B = [('b', 1.0), ('c', 1.0)]
    rating_data.append(('B', rate_B))
    rate_C = [('c', 1.0), ('d', 1.0)]
    rating_data.append(('C', rate_C))

    lfm = LFM(rating_data, 2)
    lfm.train()
    for item in ['a', 'b', 'c', 'd']:
        print(item, lfm.predict('A', item))  # 计算用户A对各个物品的喜好程度

(4) RSVD(增加正则项)

RSVD是在Basic SVD目标函数的基础上,中加入正则化参数(加入惩罚项),以防止过拟合。

预测函数

在这里插入图片描述

目标函数(损失函数+正则项)

在这里插入图片描述

梯度下降

求梯度

在这里插入图片描述

梯度更新

在这里插入图片描述

(5) RSVD进一步优化(消除用户和物品打分的偏差)

  • 由于不同用户的打分体系不同(比如在 5分为满分的情况下,有的用户认为打 3 分已经是很低的分数了,而有的用户认为打 1 分才是比较差的评价 )
  • 不同物品的衡量标准也有所区别(比如电子产品的平均分和日用品的平均分差异有可能比较大 )

为了消除用户和物品打分的偏差(Bias ),常用的做法是在矩阵分解时加入用户和物品的偏差向量。

预测函数

在这里插入图片描述

目标函数(损失函数+正则项)

在这里插入图片描述

梯度下降

求梯度

在这里插入图片描述

梯度更新

在这里插入图片描述

3、矩阵分解优缺点

优点

相比协同过滤,矩阵分解有如下非常明显的优点:

(1)泛化能力强,在一定程度上解决了数据稀疏问题。

  • 显然,协同过滤在应对稀疏矩阵时,准确率很低。举个例子:在一个共现矩阵中,大部分物品只有少数用户评分了,那么计算相似性的时候,很难找到准确的相似。而在矩阵分解中,比如梯度下降中,我们是不需要关注缺失值的,我们只需要利用已知的评分,去拟合出我们的两个矩阵然后就可以通过这两个矩阵,去预测缺失值

  • 协同过滤中,它只利用了用户自身物品自身的信息,矩阵分解中,挖掘了用户与物品的潜在信息,可以看作是对用户和物品“打标签”,用户和物品画像都得到了丰宫,提高了泛化能力

(2)空间复杂度低。

协同过滤,需要存储庞大的
[用户-用户 相似度] m×m矩阵,[物品-物品 相似度] n×n矩阵
矩阵分解,只需要存储
[用户隐向量] m×k,[物品隐向量]n×k

(3)更好的扩展性和灵活性
产生的隐向量,便于与其他特征进行组合和拼接便于与深度学习网络进行无缝结合

缺点

  • 与协同过滤一样,矩阵分解同样不方便加入用户、物品和上下文相关的特征,这使得矩阵分解丧失了利用很多有收信息的机会

  • 同时在缺乏用户历史行为时,无法进行有效的推荐。

为了解决这问题,逻辑回归模型及其后续发展出的因子分解机等模型,凭借其天然的融合不同特征的能力,逐渐在推荐系统领域得到更广泛的应用。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于协同过滤算法的在线图书推荐系统是利用用户对图书的评分行为以及图书之间的相似性来为用户推荐可能感兴趣的图书。在这个系统中,ALS矩阵分解算法是一种基于模型协同过滤算法。 ALS矩阵分解算法是一种常用的协同过滤算法,其主要思想是将用户-图书评分矩阵分解为两个低维度的矩阵,通过学习用户和图书的隐含特征来预测用户对未评价图书的评分,并根据预测评分来进行推荐。 具体而言,ALS矩阵分解算法分为两个步骤:交替最小二乘法和优化用户/图书隐向量。在交替最小二乘法中,通过固定隐向量中一个变量,更新另一个变量,直到收敛。在优化用户/图书隐向量过程中,通过最小化预测评分和实际评分之间的差距来优化隐向量。 在在线图书推荐系统中,首先需要根据用户的历史评分数据构建用户-图书评分矩阵。然后,通过ALS矩阵分解算法来训练模型,得到用户和图书的隐向量。接下来,对于一个给定的用户,可以通过计算用户的隐向量与图书的隐向量之间的相似性来获取与用户兴趣最相似的图书。最后,根据相似性进行推荐,将推荐的图书推送给用户。 基于协同过滤算法的在线图书推荐系统不仅考虑用户的历史行为,还能通过挖掘图书之间的相似性来为用户推荐可能感兴趣的图书。通过使用ALS矩阵分解算法,系统可以根据用户行为数据进行模型训练和隐向量推断,从而提高图书推荐的准确性和个性化程度。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值