前言

奇异值分解(SVD)可以将任意矩阵分解成两个方阵和一个对角矩阵的乘积。借助于SVD,我们可以将推荐系统中的用户-评分矩阵进行分解,通过推广的SVD方法(FunkSVD,BiasSVD和SVD++),我们还可以进一步做评分矩阵的补全。根据补全的评分矩阵,我们将可以给用户推荐他没有购买过的产品。因此,SVD方法在推荐系统中具有重要的应用价值。

下面,我们将逐个介绍 原始SVDFunkSVDBiasSVD以及SVD++。介绍完这些算法之后,我们将在movielens数据集上,用第三方库surprise进行简单的评分预测。

SVD

1. 原始SVD

对于任意m×nm\times nm×n矩阵AAA,通过奇异值分解,有严格等式
A=PΣQTA=P\Sigma Q^TA=PΣQT

其中,PPP和QQQ是方阵,Σ\SigmaΣ是对角矩阵。

进一步的,PPP的列向量是m×mm\times mm×m方阵AATAA^TAAT的特征向量;QQQ的列向量是n×nn\times nn×n方阵ATAA^TAATA的特征向量;m×nm\times nm×n矩阵Σ\SigmaΣ的对角线元素是AAA的特征值。

通过上面的奇异值分解,我们可以将用户-评分矩阵RRR分解为三个矩阵的乘积。

虽然SVD能够将评分矩阵RRR分解,但是存在以下问题

  • 原始SVD过程要求评分矩阵RRR是稠密的,但是通常评分矩阵是很稀疏的,这就无法做SVD
  • 可以通过填充来让评分矩阵稠密,但是,无论如何填充,都会引入噪音

实际上,原始SVD实际上更加适合于数据降维,可以参考我的博客 用SVD做图像降维。

2. FunkSVD

用户-评分矩阵RRR通常是很稀疏的,原始SVD无法使用,因此,我们提出一个近似的矩阵分解算法,FunkSVD。

与MF类似,对于m×nm\times nm×n评分矩阵RRR,我们假设由两个矩阵Pk×mP_{k\times m}Pk×m​和Qk×nQ_{k\times n}Qk×n​的乘积近似得到,这就意味着下式的成立
R≈PTQR\approx P^TQR≈PTQ

对于上面的式子,我们可以这样理解

  • 评分矩阵RRR是m×nm\times nm×n的,这就是说,有mmm个用户和nnn个商品,每个用户不可能使用所有商品,因此仅仅能对其中少量的商品进行打分,这也就是评分矩阵稀疏的原因
  • PPP是k∗mk*mk∗m维的,这就是说,我们可以把第iii列向量当做用户iii的特征pip_ipi​,这个特征pip_ipi​是kkk维的
  • QQQ是k∗nk*nk∗n维的,这就是说,我们可以把第jjj列向量当做商品jjj的特征qjq_jqj​,这个特征qjq_jqj​是kkk维的
  • 一个比较通俗的例子是这样的:
  1. 我们有100个用户和1000部电影,用户对看过的电影打分,从而形成用户-商品评分矩阵R100×1000R_{100\times1000}R100×1000​;
  2. 现在,为了更好的区分不同用户和电影,我们给出3种特征(k=3k=3k=3),分别为 动作,爱情,悬疑;
  3. 第1个用户的特征p1=[0.8,0.2,0.1]Tp_1=[0.8, 0.2, 0.1]^Tp1​=[0.8,0.2,0.1]T,意思就是这个用户更加偏爱动作,第2部电影的特征q2=[0.3,0.2,0.6]Tq_2=[0.3, 0.2, 0.6]^Tq2​=[0.3,0.2,0.6]T,意思是这个电影更加偏向于悬疑;
  4. 那么,第一个用户看完第二部电影之后的评分,我们预测为p1Tq2=0.34p_1^Tq_2=0.34p1T​q2​=0.34,这就是一个综合的喜爱程度。

我们想得到这样的PPP和QQQ,并使得PTQP^TQPTQ尽量接近RRR。注意,RRR中仅有少量位置存在值,我们求的PTQP^TQPTQ就是尽量接近这些值。

假设RRR中非空位置集合为KKK,我们有如下最优化问题
min⁡P,QL=12∑(i,j)∈K(Ri,j−piTqj)2+λ2(∑i=1m∣pi∣2+∑j=1n∣qj∣2)\min_{P,Q}L= \frac{1}{2}\sum_{(i, j)\in K}(R_{i, j}-p_i^Tq_j)^2+\frac{\lambda}{2}(\sum_{i=1}^m\lvert p_i \rvert^2+\sum_{j=1}^n|q_j|^2)P,Qmin​L=21​(i,j)∈K∑​(Ri,j​−piT​qj​)2+2λ​(i=1∑m​∣pi​∣2+j=1∑n​∣qj​∣2)

直接对损失函数求导,我们有
∂L∂pi=∑j(piTqj−Ri,j)qj+λpi=(∑jqjqjT+λI)pi−∑jRi,jqj\begin{array}{lll} \frac{\partial L}{\partial p_i}&=&\sum_j(p_i^Tq_j-R_{i,j})q_j+\lambda p_i\\ &=&(\sum_jq_jq_j^T+\lambda I)p_i-\sum_jR_{i, j}q_j \end{array} ∂pi​∂L​​==​∑j​(piT​qj​−Ri,j​)qj​+λpi​(∑j​qj​qjT​+λI)pi​−∑j​Ri,j​qj​​

∂L∂qj=∑i(piTqj−Ri,j)pi+λqj=(∑ipipiT+λI)qj−∑iRi,jpi\begin{array}{lll} \frac{\partial L}{\partial q_j}&=&\sum_i(p_i^Tq_j-R_{i,j})p_i+\lambda q_j\\ &=&(\sum_ip_ip_i^T+\lambda I)q_j-\sum_iR_{i, j}p_i \end{array} ∂qj​∂L​​==​∑i​(piT​qj​−Ri,j​)pi​+λqj​(∑i​pi​piT​+λI)qj​−∑i​Ri,j​pi​​

因此,有更新策略
pi←pi−α∂L∂pip_i\leftarrow p_i-\alpha\frac{\partial L}{\partial p_i}pi​←pi​−α∂pi​∂L​

qj←qj−α∂L∂qjq_j\leftarrow q_j-\alpha\frac{\partial L}{\partial q_j}qj​←qj​−α∂qj​∂L​

其中,α\alphaα是学习率。

通过以上迭代更新,可以得到PPP和QQQ,从而得到近似的评分矩阵PTQP^TQPTQ,从而补全评分矩阵。

3. BiasSVD

在FunkSVD的基础上,我们进一步考虑用户偏好和商品偏好。

比如,对于某些用户而言,他们打分一向比较高,而对于较为苛刻的用户,他们打分又偏低;对于某些高质量商品而言,给它们的评分一般偏高,比如泰坦尼克电影评分4.9,可能这部电影没有那么好,被高估了。

基于以上观察,我们有,不同用户有自己的打分习惯,或者偏高或者偏低;不同电影也有自己的分数倾向,或者倾向于低分或者倾向于高分。我们需要在模型中加以体现。

令μ\muμ为评分的平均值,bib_ibi​为用户iii的偏好带来的评分偏置,bjb_jbj​为商品jjj的质量带来的评分偏置。这样,用户iii对商品jjj的评分可以写为
μ+bi+bj+piTqj\mu+b_i+b_j+p_i^Tq_jμ+bi​+bj​+piT​qj​

因此,我们的目标函数可以写为
min⁡P,Q,bi,bjL=12∑(i,j)∈K(Ri,j−μ−bi−bj−piTqj)2+λ2(∑i=1m∣bi∣2+∑j=1n∣bj∣2+∑i=1m∣pi∣2+∑j=1n∣qj∣2)\begin{array}{lll} \min_{P,Q, b_i, b_j}L&=& \frac{1}{2}\sum_{(i, j)\in K}(R_{i, j}-\mu-b_i-b_j-p_i^Tq_j)^2\\ &&+\frac{\lambda}{2}(\sum_{i=1}^m|b_i|^2+\sum_{j=1}^n|b_j|^2+\sum_{i=1}^m\lvert p_i \rvert^2+\sum_{j=1}^n|q_j|^2) \end{array}minP,Q,bi​,bj​​L​=​21​∑(i,j)∈K​(Ri,j​−μ−bi​−bj​−piT​qj​)2+2λ​(∑i=1m​∣bi​∣2+∑j=1n​∣bj​∣2+∑i=1m​∣pi​∣2+∑j=1n​∣qj​∣2)​

类似的,对目标函数求导,可以写出更新策略,这里略过。

4. SVD++

在BiasSVD的基础上,我们进一步考虑用户隐式反馈的影响。

用户除了对商品有评分这一显式反馈之外,还有诸如浏览、点击等隐式反馈。一个用户可能对许多商品有隐式反馈,我们将用户iii有过隐式反馈的商品集合记为N(i)N(i)N(i),每一次对于特定商品s∈N(i)s\in N(i)s∈N(i) 的点击或者浏览,都带来对于用户特征pip_ipi​的某些偏置ysy_sys​。

这样,对于用户iii,最终他的特征pip_ipi​可以写为
pi+∑s∈N(i)ysp_i+\sum_{s\in N(i)}y_spi​+s∈N(i)∑​ys​

因此,用户iii对商品jjj的评分可以写为
μ+bi+bj+qjT(pi+∑s∈N(i)ys)\mu+b_i+b_j+q_j^T(p_i+\sum_{s\in N(i)}y_s)μ+bi​+bj​+qjT​(pi​+s∈N(i)∑​ys​)

这样, 我们的目标函数可以写为
min⁡P,Q,bi,bj,ysL=12∑(i,j)∈K(Ri,j−μ−bi−bj−qjT(pi+∑s∈N(i)ys))2+λ2(∑i=1m∣bi∣2+∑j=1n∣bj∣2+∑i=1m∣pi∣2+∑j=1n∣qj∣2+∑i=1m∑s∈N(i)∣ys∣2)\begin{array}{lll} \min_{P,Q, b_i, b_j, y_s}L&=& \frac{1}{2}\sum_{(i, j)\in K}(R_{i, j}-\mu-b_i-b_j-q_j^T(p_i+\sum_{s\in N(i)}y_s))^2\\ &&+\frac{\lambda}{2}(\sum_{i=1}^m|b_i|^2+\sum_{j=1}^n|b_j|^2+\sum_{i=1}^m\lvert p_i \rvert^2+\sum_{j=1}^n|q_j|^2+\sum_{i=1}^m\sum_{s\in N(i)}|y_s|^2) \end{array} minP,Q,bi​,bj​,ys​​L​=​21​∑(i,j)∈K​(Ri,j​−μ−bi​−bj​−qjT​(pi​+∑s∈N(i)​ys​))2+2λ​(∑i=1m​∣bi​∣2+∑j=1n​∣bj​∣2+∑i=1m​∣pi​∣2+∑j=1n​∣qj​∣2+∑i=1m​∑s∈N(i)​∣ys​∣2)​

同样用梯度下降方法,我们可以对变量进行迭代。

简单实战

这里,我们选用movielens的ratings数据集,利用第三方库surprise进行简单的TopN预测。

movielens数据集在本人的免费资源里面,请自取。

# 第三方库
import pandas as pd
from surprise import SVD, SVDpp
from surprise import Dataset, Reader
from surprise import accuracy
from surprise.model_selection import KFold, train_test_split
# 数据读取
# 注意:surprise读取数据需要自己的阅读器和格式,直接使用pandas不行的# 定义阅读器框架
reader = Reader(line_format='user item rating')# 利用pandas读取数据
df_data = pd.read_csv(r'D:\myfile\开课吧\推荐系统\第六节\movielens\ratings.csv', usecols=['userId', 'movieId', 'rating'])# 将数据转化为surprise特定数据集
data = Dataset.load_from_df(df_data, reader)
print(data)

1. 比较不同SVD算法

# 比较funkSVD,BiasSVD和SVDpp的预测效果,指标为rmse# funkSVD
algo = SVD(n_factors=30, biased=False)
kf = KFold(n_splits=5)
error = []
for trainset, testset in kf.split(data):algo.fit(trainset) # 训练模型predictions = algo.test(testset) # 预测cur_error = accuracy.rmse(predictions) # 计算误差error.append(cur_error)mean_error = sum(error) / len(error)
print('funkSVD的平均误差为', mean_error)
# funkSVD误差
RMSE: 0.8478
RMSE: 0.8509
RMSE: 0.8495
RMSE: 0.8487
RMSE: 0.8495
funkSVD的平均误差为 0.8492727275931049
# biasSVD
algo = SVD(n_factors=30, biased=True)
kf = KFold(n_splits=5)
error = []
for trainset, testset in kf.split(data):algo.fit(trainset) # 训练模型predictions = algo.test(testset) # 预测cur_error = accuracy.rmse(predictions) # 计算误差error.append(cur_error)mean_error = sum(error) / len(error)
print('biasSVD的平均误差为', mean_error)
# biasSVD误差
RMSE: 0.8321
RMSE: 0.8327
RMSE: 0.8312
RMSE: 0.8323
RMSE: 0.8320
biasSVD的平均误差为 0.8320637234052113
# SVD++
algo = SVDpp(n_factors=30)
kf = KFold(n_splits=5)
error = []
for trainset, testset in kf.split(data):algo.fit(trainset) # 训练模型predictions = algo.test(testset) # 预测cur_error = accuracy.rmse(predictions) # 计算误差error.append(cur_error)mean_error = sum(error) / len(error)
print('SVD++的平均误差为', mean_error)

这里SVD++算法相对复杂,需要运行较长时间,这里我就没有等到运算出结果了,可以预期到误差应该更低的。

2. TopN预测

这里,我们的思路是

  • 创建字典user_items,记录用户看过的电影
  • 创建userID和itemID,分别记录所有用户ID和电影ID
  • 训练BiasSVD,有alg
  • 遍历所有可能的用户-商品组合,找出用户没有购买过的商品,并用alg预测评分,将这一结果保存在字典user_newitems_ratings中
  • 通过评分排序,找出user评分最高的N个商品
# 创立字典user_items,记录user用过哪些movie
user_items = {}
# 创建userID和itemID,分别记录所有的user和item
userID, itemID = [], []# 将data数据集变成操作的数据集
data = data.build_full_trainset()# 遍历数据集data,生成user_items列表
for user, item, rating in data.all_ratings():user_items.setdefault(user, [])user_items[user].append(item)if item not in itemID:itemID.append(item)userID = list(user_items.keys())
# TopN推荐
# 遍历数据集,找出user没有购买过的商品
# 用user_newitems_ratings列表记录对没有购买过的商品的预估评分
user_newitems_ratings = {}# biasSVD
alg = SVD(n_factors=30)
alg.fit(data) # 训练算法
# 遍历所有可能的用户-物品对,找出用户没有购买过的商品
for user in userID:user_newitems_ratings.setdefault(user, {})for item in itemID:if item not in user_items[user]: # user没有购买过的商品 # 预测用户评分user_newitems_ratings[user][item] = alg.predict(user, item, verbose=False).est
# 对用户评分进行排序
for user in user_newitems_ratings.keys():user_newitems_ratings[user] = sorted(user_newitems_ratings[user].items(), key=lambda x: x[1], reverse=True)
# 获取user的topN推荐
def get_topN(user, N):return user_newitems_ratings[user][:N]
# 例子:user=0,N=4
get_topN(0, 4)
# 预测结果
[(318, 4.460564726496344),(6271, 4.427441820009547),(3090, 4.416865860322598),(7502, 4.409934931201513)]

《推荐系统笔记(六)》svd在推荐系统中的应用推广(FunkSVD,BiasSVD以及SVD++)及简单实战(surprise库)相关推荐

  1. 推荐系统笔记:基于SVD的协同过滤

    1 奇异值分解 奇异值分解(SVD)是矩阵分解的一种形式,其中U和V的列被约束为相互正交 相互正交的优点是概念之间可以完全独立,并且可以用散点几何解释它们. 然而,这种分解的语义解释通常比较困难,因为 ...

  2. 《推荐系统笔记(五)》svd降维 —— 以图片处理为例

    理论部分 任何一个m×nm\times nm×n矩阵AAA,通过svd分解,可以分解为三个矩阵相乘 A=PΣQTA=P\Sigma Q^TA=PΣQT 其中,Σ\SigmaΣ是一个m×nm\times ...

  3. 吴恩达机器学习系列课程笔记——第十六章:推荐系统(Recommender Systems)

    16.1 问题规划 https://www.bilibili.com/video/BV164411b7dx?p=96 在接下来的视频中,我想讲一下推荐系统.我想讲推荐系统有两个原因: 第一.仅仅因为它 ...

  4. 推荐系统笔记:基于矩阵分解(总结篇)

    推荐系统笔记:基于潜在因子模型的协同过滤(latent factor model)_UQI-LIUWJ的博客-CSDN博客 推荐系统笔记:无任何限制的矩阵分解_UQI-LIUWJ的博客-CSDN博客 ...

  5. 推荐系统笔记:决策树回归树

    决策树和回归树经常用于数据分类. 决策树是为那些因变量(target,label)是分类的情况而设计的,而回归树是为那些因变量(target,label)是数值的情况而设计的.          在讨 ...

  6. 推荐系统笔记(十三):SGL算法的代码实现

    前言         本算法是在LightGCN的代码上的基础实现的,LightGCN的代码和原理参考我前面几篇的博客:推荐系统笔记(六):LightGCN代码实现_甘霖那的博客-CSDN博客 由于L ...

  7. 推荐系统笔记:矩阵分解+基于邻居的模型

    由于其启发式性质,基于邻域的方法通常被认为与其他优化模型具有内在的不同. 尽管如此,结果表明基于邻域的方法也可以嵌入在其他优化模型的上下文中. 这是一个相当方便的框架,因为它为邻域模型与其他优化模型( ...

  8. 推荐系统笔记:基于非负矩阵分解的协同过滤

    1 非负矩阵分解 非负矩阵分解 (NMF) 可用于非负的评级矩阵. 这种方法的主要优势不一定是准确性,而是它在理解用户-项目交互方面提供的高度可解释性. 与其他形式的矩阵分解的主要区别在于因子 U 和 ...

  9. 推荐系统笔记:无任何限制的矩阵分解

    1 非稀疏矩阵的矩阵分解 假设我们有各个条目均有值的观测矩阵R,我们希望用低维矩阵U,V的乘积来近似它.目标方程如下: 2 稀疏矩阵的矩阵分解 我们用S记录所有有值的(i,j)点对 预测矩阵的每一个条 ...

最新文章

  1. NAACL 2021 | 担心GPT-3被喂假消息?谷歌新研究,将知识图谱转成“人话”用于训练...
  2. 八、redis性能测试
  3. ElementUI的组件拆解之Tooltip
  4. Java01-day01【发展史、跨平台原理、JRE和JDK、常用DOS命令、关键字、常量、数据类型、变量使用的注意事项、标识符、类型转换】
  5. oppo如何更新计算机,OPPO工程师手把手教你固件升级
  6. 初学者指南:如何为Red Hat Process Automation Manager配置电子邮件服务任务
  7. GCC如何产生core dump
  8. 实现多个输入框的dialog
  9. 【spring boot基础知识】java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
  10. PHP包含文件函数include、include_once、require、require_once区别和总结
  11. 嗅探工具java_权宜之计 让迅雷5支持傲游2嗅探器来下载视频
  12. 优酷kux文件转码成mp4
  13. 微软云服务器机房分布,Azure手把手系列 1:微软中国公有云概述
  14. 《财富》杂志评选出必读的75本最睿智的图书
  15. 2019 中文互联网资源碎碎念
  16. 十大排序方法之基数排序
  17. lca rmq 算法资料
  18. GDKOI2014「壕壕的寒假作业」
  19. 【Python】Python生成个性二维码
  20. zend studio php 错误提示,win7启动Zend Studio弹出错误提示?查看解决方法

热门文章

  1. python文件输入符_python基础入门详解(文件输入/输出 内建类型 字典操作使用方法)...
  2. 偏差(bias)、方差(variance)和噪音(noise)
  3. !!统计字符(处理字符串)(getline函数使用)
  4. 自动驾驶系统的学习笔记
  5. 《南溪的python灵隐笔记》——有趣的Munch字典库
  6. 计算机视觉——主干网络的学习笔记
  7. 计算机视觉(CV)中图像的梯度
  8. 心大于物 ----论意识心灵与物理大脑的关系
  9. ASimpleCache使用感受
  10. 【Qt教程】2.2 - Qt5 布局管理器(水平、垂直、栅格布局)、弹簧、设计一个登陆界面