【推荐系统】矩阵分解MF利用BASIC-SVD分解

简介: 【推荐系统】矩阵分解MF利用BASIC-SVD分解

2021人工智能领域新星创作者,带你从入门到精通,该博客每天更新,逐渐完善推荐系统各个知识体系的文章,帮助大家更高效学习。

1.矩阵分解算法的求解

那么到底如何才能将评分矩阵进行分解呢?

主成分分析利用到了奇异值分解(SVD)进行分解特征矩阵,那么这里我们可不可以使用SVD进行分解呢?

答案是不行的,因为对于我们的评分矩阵是稀疏的,存在大量用户和物品无交互的情况,所以我们在使用SVD之前需要进行填充,其次是SVD的计算复杂度非常高,需要计算矩阵的特征值,而且当维度较高时,计算会非常复杂。

那么对于矩阵分解还有一种方式就是特征值分解,在这里也是显然不行的,因为使用特征值分解的前提要求是矩阵必须是方阵,这个要求对于我们的评分矩阵显然一般情况是不能够满足的。

那么应如何分解呢?

其实这个和神经网络的反向传播很像,我们定义一个优化函数,然后进行优化,那么我们就想办法将我们矩阵分解转化成一个优化问题,然后使用随机梯度下降进行求解。

2006年的Netflix Prize之后, Simon Funk公布了一个矩阵分解算法叫做Funk-SVD, 后来被Netflix Prize的冠军Koren称为Latent Factor Model(LFM)。 Funk-SVD的思想很简单:把求解上面两个矩阵的参数问题转换成一个最优化问题, 可以通过训练集里面的观察值利用最小化来学习用户矩阵和物品矩阵。

我们之前说到可以用用户矩阵与物品矩阵的乘积作为最终评分,那么现在是没有这个矩阵,那么我们刚开始可以随机初始化一个,里面随机赋些值,然后真实值与初始化矩阵得到的评分会有误差,因为我们这两个矩阵是随机初始化的最终计算结果是肯定不准的,那么就会产生一个误差:

image.png

那么此时就可以利用所有用户对所有物品的误差平方和作为优化函数:

image.png

现在有了可以评估精度的函数了,此时我们就可以利用最优化的算法进行求解其中的参数使其最小化:

image.png

对于这种优化函数,我们一般采用的是随机梯度下降(stochastic gradient descent),所以此时我们需要知道我们需要优化的参数的导数:

image.png


所以我们最终得到的参数更新公式为:

image.png

然后就可以基于梯度下降求其最优解,就可以获得分解后的矩阵了,因为我们求解的参数分别是两个矩阵的列向量。

这里没有考虑正则化,如果我们的数据过少或者说要防止过拟合,我们还需要对参数进行惩罚使用正则化。

2.优化函数的修改

上面我们已经获得了优化方程以及梯度更新公式,然后可以使用梯度下降法进行求解,但是此时会存在问题,结果可能有所偏差。

原因是有一些因素还没有考虑到,我们只是考虑用户矩阵和物品矩阵,这两个矩阵分别代表用户、物品与那些隐特征之间的联系,没有考虑到一些个人或者物品自身的一些影响。

比如说现在长津湖电影是非常火的,那么它的评分一定是很高的,但是它不一定都与用户有关系,一定程度上有它自身的因素影响,比如说里面的演员很出名或者上映时间等,这些与用户是没有关系的。

再比如一个用户是比较批判的,不管他观看什么类型的电影最终给出的评分都是比较低的,这个与电影就没什么关系了,单纯是个人因素影响。

所以针对这些问题,只考虑两个矩阵显然是不科学的,还需要在原来基础上加入一些偏置项来消除用户和物品打分的偏差,即:

image.png

这个预测公式加入了3项偏置μ , b u , b i \mu,b_u,b_iμ,bu,bi, 作用如下:

  • μ \muμ: 训练集中所有记录的评分的全局平均数。 在不同网站中, 因为网站定位和销售物品不同, 网站的整体评分分布也会显示差异。 比如有的网站中用户就喜欢打高分, 有的网站中用户就喜欢打低分。 而全局平均数可以表示网站本身对用户评分的影响。
  • b u b_ubu: 用户偏差系数, 可以使用用户u uu给出的所有评分的均值, 也可以当做训练参数。 这一项表示了用户的评分习惯中和物品没有关系的那种因素。 比如有些用户比较苛刻, 对什么东西要求很高, 那么他评分就会偏低, 而有些用户比较宽容, 对什么东西都觉得不错, 那么评分就偏高
  • b i b_ibi: 物品偏差系数, 可以使用物品i ii收到的所有评分的均值, 也可以当做训练参数。 这一项表示了物品接受的评分中和用户没有关系的因素。 比如有些物品本身质量就很高, 因此获得的评分相对比较高, 有的物品本身质量很差, 因此获得的评分相对较低。

加入偏置项后的优化函数为:


image.png

image.png

对于新加入的偏置项的梯度为:


image.png

image.png

3.BASIC-SVD编程实现

"""
 * Created with PyCharm
 * 作者: Laura
 * 日期: 2021/11/5
 * 时间: 11:10
 * 描述: BASIC-SVD
"""
import numpy as np
import pandas as pd
users = {
    "Tom":{"物品1":5,"物品2":3,"物品3":4,"物品4":4},
    "用户1":{"物品1":3,"物品2":1,"物品3":2,"物品4":3,"物品5":3},
    "用户2":{"物品1":4,"物品2":3,"物品3":4,"物品4":3,"物品5":5},
    "用户3":{"物品1":3,"物品2":3,"物品3":1,"物品4":5,"物品5":4},
    "用户4":{"物品1":1,"物品2":5,"物品3":5,"物品4":2,"物品5":1},
}
user_df = pd.DataFrame(users).T
user_df = user_df.fillna(0)
class SVD():
    def __init__(self, rating_data, k = 5, alpha = 0.1, lmbda = 0.1, max_iter = 2000):
        self.rating_data = rating_data
        self.mu = 1.0
        self.bu = None   # (user,1)
        self.bi = None   # (item,1)
        self.P = None    # (user,k)
        self.Q =None     # (item,k)
        self.alpha = alpha
        self.lmbda = lmbda
        self.k = k
        self.max_iter = max_iter
    def init_params(self):
        self.mu = self.rating_data.mean().mean()
        self.bu = np.zeros((self.rating_data.shape[0], 1))
        self.bi = np.zeros((self.rating_data.shape[1], 1))
        self.P = np.random.rand(self.rating_data.shape[0], self.k) / np.sqrt(self.k)
        self.Q = np.random.rand(self.rating_data.shape[1], self.k) / np.sqrt(self.k)
    def train(self):
        self.init_params()
        for step in range(self.max_iter):
            r_hat = self.compute()
            error = self.rating_data.values - r_hat
            self.P = self.P + self.alpha * error @ self.Q
            self.Q = self.Q + self.alpha * error.T @ self.P
            self.bu = self.bu + self.alpha * (error.mean(axis=1).reshape(-1,1) - self.lmbda * self.bu)
            self.bi = self.bi + self.alpha * (error.mean(axis=1).reshape(-1,1) - self.lmbda * self.bi)
            self.alpha *= 0.1
    def compute(self):
        return self.mu + self.bu + self.bi + self.P @ self.Q.T
    def predict(self,user,item):
        return self.mu + self.bu[user][0] + self.bi[item][0] + np.dot(self.P[user], self.Q[item])
model = SVD(user_df, k=5)
model.train()
model.predict(0,0)


目录
相关文章
|
5月前
|
数据采集 搜索推荐 算法
实战基于矩阵分解的推荐系统
实战基于矩阵分解的推荐系统
|
搜索推荐 算法 数据挖掘
# 【推荐系统入门到项目实战】(三):矩阵分解和ALS算法
# 【推荐系统入门到项目实战】(三):矩阵分解和ALS算法
# 【推荐系统入门到项目实战】(三):矩阵分解和ALS算法
|
2月前
|
分布式计算 搜索推荐 算法
推荐系统的数学模型-从矩阵分解到推荐系统(Scala实现)
推荐系统的数学模型-从矩阵分解到推荐系统(Scala实现)
36 0
|
机器学习/深度学习 数据采集 资源调度
【推荐系统】推荐场景为什么不可以使用SVD分解共现矩阵
【推荐系统】推荐场景为什么不可以使用SVD分解共现矩阵
120 0
【推荐系统】推荐场景为什么不可以使用SVD分解共现矩阵
|
机器学习/深度学习 并行计算 搜索推荐
推荐系统总结(交替最小二乘法、LightFM、神经网络矩阵分解和神经协同过滤)
在社交媒体网络上,有大量的半结构化数据。该任务的数据集是从在线照片共享社交媒体网络 Flickr 收集的。Flickr 允许用户分享照片并相互交流(朋友)。目标是向访问此社交媒体平台的大量数据的每个用户推荐对象(图片)列表。训练数据集包含一组用于构建推荐系统的用户和项目(照片)之间的交互,包含评分基本事实的验证数据用于决定最终模型。除测试数据外,其余数据集不用于分析。
386 0
|
机器学习/深度学习 搜索推荐 算法
# 【推荐系统入门到项目实战】(五):SVD矩阵分解 -
# 【推荐系统入门到项目实战】(五):SVD矩阵分解
# 【推荐系统入门到项目实战】(五):SVD矩阵分解 -
|
机器学习/深度学习 存储 搜索推荐
【推荐系统】推荐系统中分解共现矩阵的优点与局限性
【推荐系统】推荐系统中分解共现矩阵的优点与局限性
80 0
|
人工智能 搜索推荐 TensorFlow
【推荐系统】TensorFlow实现FM特征分解机
【推荐系统】TensorFlow实现FM特征分解机
128 0
|
6月前
|
搜索推荐 算法 前端开发
旅游管理与推荐系统Python+Django网页平台+协同过滤推荐算法
旅游管理与推荐系统Python+Django网页平台+协同过滤推荐算法
149 0
|
3天前
|
算法 搜索推荐 数据挖掘
MATLAB模糊C均值聚类FCM改进的推荐系统协同过滤算法分析MovieLens电影数据集
MATLAB模糊C均值聚类FCM改进的推荐系统协同过滤算法分析MovieLens电影数据集
11 0

热门文章

最新文章