Py学习  »  机器学习算法

机器学习(37)之矩阵分解在协同过滤推荐中的应用

机器学习算法与Python学习 • 6 年前 • 535 次点击  

微信公众号

关键字全网搜索最新排名

【机器学习算法】排名第一

【机器学习】排名第一

【Python】排名第三

【算法】排名第四


前言

在协同过滤推荐算法总结(机器学习(36)之协同过滤典型算法概述【精华】)中,讲到了用矩阵分解做协同过滤是广泛使用的方法,这里就对矩阵分解在协同过滤推荐算法中的应用做一个总结。

解决什么问题

在推荐系统中,常常遇到的问题是这样的,我们有很多用户和物品,也有少部分用户对少部分物品的评分,希望预测目标用户对其他未评分物品的评分,进而将评分高的物品推荐给目标用户。比如下面的用户物品评分表:



对于每个用户,希望较准确的预测出用户对未评分物品的评分。对于这个问题有很多解决方法,本文关注于用矩阵分解的方法来做。如果将m个用户和n个物品对应的评分看做一个矩阵M,我们希望通过矩阵分解来解决这个问题。


使用SVD解决

说道矩阵分解,首先想到的就是奇异值分解SVD。在奇异值分解(SVD)原理(机器学习(29)之奇异值分解SVD原理与应用详解)和在降维中的应用中,对SVD原理做了总结。


此时可以将这个用户物品对应的m×n矩阵M进行SVD分解,并通过选择部分较大的一些奇异值来同时进行降维,也就是说矩阵M此时分解为:

其中k是矩阵M中较大的部分奇异值的个数,一般会远远的小于用户数和物品数。如果要预测第i个用户对第j个物品的评分mij,则只需要计算uTiΣvj即可。通过这种方法,可以将评分表里面所有没有评分的位置得到一个预测评分。通过找到最高的若干个评分对应的物品推荐给用户。


可以看出这种方法简单直接,似乎很有吸引力。但是有一个很大的问题我们忽略了,就是SVD分解要求矩阵是稠密的,也就是说矩阵的所有位置不能有空白。有空白时M是没法直接去SVD分解的。如果这个矩阵是稠密的,那不就是说我们都已经找到所有用户物品的评分了嘛,那还要SVD干嘛! 的确,这是一个问题,传统SVD采用的方法是对评分矩阵中的缺失值进行简单的补全,比如用全局平均值或者用用户物品平均值补全,得到补全后的矩阵。接着可以用SVD分解并降维。


虽然有了上面的补全策略,传统SVD在推荐算法上还是较难使用。因为用户数和物品一般都是超级大,随便就成千上万了。这么大一个矩阵做SVD分解是非常耗时的。那么有没有简化版的矩阵分解可以用呢?我们下面来看看实际可以用于推荐系统的矩阵分解。


FunkSVD横空出世

FunkSVD是在传统SVD面临计算效率问题时提出来的,既然将一个矩阵做SVD分解成3个矩阵很耗时,同时还面临稀疏的问题,那么能不能避开稀疏问题,同时只分解成两个矩阵呢?也就是说,现在期望矩阵M这样进行分解:

SVD分解已经很成熟了,但是FunkSVD如何将矩阵M分解为P和Q呢?这里采用了线性回归的思想。目标是让用户的评分和用矩阵乘积得到的评分残差尽可能的小,也就是说,可以用均方差作为损失函数,来寻找最终的P和Q。


对于某一个用户评分mij,如果用FunkSVD进行矩阵分解,则对应的表示为qTjpi,采用均方差做为损失函数,则我们期望

尽可能的小,如果考虑所有的物品和样本的组合,则我们期望最小化下式:

只要能够最小化上面的式子,并求出极值所对应的pi,qj,则最终可以得到矩阵P和Q,那么对于任意矩阵M任意一个空白评分的位置,可以通过qTjpi计算预测评分。


当然,在实际应用中,为了防止过拟合,会加入一个L2的正则化项,因此正式的FunkSVD的优化目标函数J(p,q)是这样的:

其中λ为正则化系数,需要调参。对于这个优化问题,一般通过梯度下降法来进行优化得到结果。将上式分别对pi,qj求导我们得到:

则在梯度下降法迭代时,pi,qj的迭代公式为:

通过迭代最终可以得到P和Q,进而用于推荐。FunkSVD算法虽然思想很简单,但是在实际应用中效果非常好,这真是验证了大道至简。


BiasSVD再升级

在FunkSVD算法火爆之后,出现了很多的改进版算法。其中BiasSVD算是改进的比较成功的一种算法。BiasSVD假设评分系统包括三部分的偏置因素:一些和用户物品无关的评分因素,用户有一些和物品无关的评分因素,称为用户偏置项。而物品也有一些和用户无关的评分因素,称为物品偏置项。这其实很好理解。比如一个垃圾山寨货评分不可能高,自带这种烂属性的物品由于这个因素会直接导致用户评分低,与用户无关。


假设评分系统平均分为μ,第i个用户的用户偏置项为bi,而第j个物品的物品偏置项为bj,则加入了偏置项以后的优化目标函数J(p,q)是这样的:



这个优化目标也可以采用梯度下降法求解。和FunkSVD不同的是,此时我们多了两个偏执项bi,bj,pi,qj的迭代公式和FunkSVD类似,这里就不给出了。而bi,bj一般可以初始设置为0,然后参与迭代。这里给出bi,bj的迭代方法

通过迭代我们最终可以得到P和Q,进而用于推荐。BiasSVD增加了一些额外因素的考虑,因此在某些场景会比FunkSVD表现好。


SVD++更强悍

SVD++算法在BiasSVD算法上进一步做了增强,这里它增加考虑用户的隐式反馈。好吧,一个简单漂亮的FunkSVD硬是被越改越复杂。


对于某一个用户i,它提供了隐式反馈的物品集合定义为N(i), 这个用户对某个物品j对应的隐式反馈修正的评分值为cij, 那么该用户所有的评分修正值为∑csj。一般将它表示为用qTjys形式,则加入了隐式反馈项以后的优化目标函数J(p,q)是这样的:

其中,引入|N(i)|−1/2是为了消除不同|N(i)|个数引起的差异。式子够长的,不过需要考虑用户的隐式反馈时,使用SVD++还是不错的选择。


小结

FunkSVD将矩阵分解用于推荐方法推到了新的高度,在实际应用中使用也是非常广泛。当然矩阵分解方法也在不停的进步,目前张量分解和分解机方法是矩阵分解推荐方法今后的一个趋势。


对于矩阵分解用于推荐方法本身来说,它容易编程实现,实现复杂度低,预测效果也好,同时还能保持扩展性。这些都是它宝贵的优点。当然,矩阵分解方法有时候解释性还是没有基于概率的逻辑回归之类的推荐算法好,不过这也不影响它的流形程度。小的推荐系统用矩阵分解应该是一个不错的选择。大型的话,则矩阵分解比起现在的深度学习的一些方法不占优势。


欢迎分享给他人让更多的人受益

参考:

  1. 宗成庆《统计自然语言处理》 第2版

  2. 博客园

    http://www.cnblogs.com/pinard/p/6351319.html

  3. 周志华《机器学习》

  4. 李航《统计学习方法》

  5. 《推荐系统》

  6. 《机器学习实战》


近期热文

资料 | 美图区域链白皮书(附PDF链接)

手册 | Linux 运维人员最常用 150 个命令汇总

机器学习(36)之协同过滤典型算法概述【精华】

机器学习(35)之PrefixSpan算法原理详解

2017年度盘点:Github上十大有趣的机器学习项目(文末有惊喜......)

加入微信机器学习交流

请添加微信:guodongwe1991

备注姓名-单位-研究方向


广告、商业合作

请添加微信:guodongwe1991

(备注:商务合作)


今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/Sr1ifIqL3r
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/6814
 
535 次点击