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

简介: 那么到底如何才能将评分矩阵进行分解呢?主成分分析利用到了奇异值分解(SVD)进行分解特征矩阵,那么这里我们可不可以使用SVD进行分解呢?

1.矩阵分解算法的求解


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


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


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


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


那么应如何分解呢?


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


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


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


网络异常,图片无法展示
|


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


网络异常,图片无法展示
|


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


网络异常,图片无法展示
|


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


网络异常,图片无法展示
|


网络异常,图片无法展示
|


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


网络异常,图片无法展示
|


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


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


2.优化函数的修改


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


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


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


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


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


网络异常,图片无法展示
|


这个预测公式加入了3项偏置

网络异常,图片无法展示
|
, 作用如下:


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


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


网络异常,图片无法展示
|


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


网络异常,图片无法展示
|


网络异常,图片无法展示
|


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)

目录
相关文章
|
7月前
|
数据采集 搜索推荐 算法
实战基于矩阵分解的推荐系统
实战基于矩阵分解的推荐系统
106 0
|
2月前
|
机器学习/深度学习 算法 搜索推荐
django调用矩阵分解推荐算法模型做推荐系统
django调用矩阵分解推荐算法模型做推荐系统
40 4
|
2月前
|
机器学习/深度学习 搜索推荐 算法
推荐系统的矩阵分解和FM模型
推荐系统的矩阵分解和FM模型
23 0
|
6月前
|
机器学习/深度学习 搜索推荐 算法
【阿旭机器学习实战】【37】电影推荐系统---基于矩阵分解
【阿旭机器学习实战】【37】电影推荐系统---基于矩阵分解
|
7月前
|
存储 搜索推荐 算法
python推荐系统实现(矩阵分解来协同过滤)
python推荐系统实现(矩阵分解来协同过滤)
|
7月前
|
机器学习/深度学习 搜索推荐 算法
python机器学习:推荐系统实现(以矩阵分解来协同过滤)
python机器学习:推荐系统实现(以矩阵分解来协同过滤)
|
7月前
|
分布式计算 搜索推荐 算法
推荐系统的数学模型-从矩阵分解到推荐系统(Scala实现)
推荐系统的数学模型-从矩阵分解到推荐系统(Scala实现)
136 0
|
4月前
|
搜索推荐 前端开发 数据可视化
【优秀python web毕设案例】基于协同过滤算法的酒店推荐系统,django框架+bootstrap前端+echarts可视化,有后台有爬虫
本文介绍了一个基于Django框架、协同过滤算法、ECharts数据可视化以及Bootstrap前端技术的酒店推荐系统,该系统通过用户行为分析和推荐算法优化,提供个性化的酒店推荐和直观的数据展示,以提升用户体验。
170 1
【优秀python web毕设案例】基于协同过滤算法的酒店推荐系统,django框架+bootstrap前端+echarts可视化,有后台有爬虫
|
6月前
|
搜索推荐 算法 小程序
基于Java协同过滤算法的电影推荐系统设计和实现(源码+LW+调试文档+讲解等)
基于Java协同过滤算法的电影推荐系统设计和实现(源码+LW+调试文档+讲解等)
|
6月前
|
搜索推荐 算法 小程序
基于Java协同过滤算法的图书推荐系统设计和实现(源码+LW+调试文档+讲解等)
基于Java协同过滤算法的图书推荐系统设计和实现(源码+LW+调试文档+讲解等)