在新手接触推荐系统这个领域时,遇到第一个理解起来比较困难的就是协同过滤法。那么若是这时候百度的话,获得最多的是奇异值分解法,即(SVD)。SVD的做用大体是将一个矩阵分解为三个矩阵相乘的形式。若是运用在推荐系统中,首先咱们将咱们的训练集表示成矩阵的形式,这里咱们以movielen数据集为例。这个数据集包含了用户对电影的评分。那么矩阵形式大体为:python
movie1 | movie2 | movie3 | moive4 | |
user1 | 1 | |||
user2 | 2 | 3 | ||
user3 | 5 | 4 | ||
user4 | 2 | 4 |
其中1~5就是对应用户对电影的评分。空余处表示数据集中没有对应用户和电影的信息。若是咱们想使用SVD,通常讲空余处都填为0.假设此矩阵为V.那么运用SVD能够获得git
V = UΣVT github
可是上面的等号并不能取到,只能是约等于。那么咱们将获得的三个矩阵相乘获得V'(注意与V不一样)。那么原来的空白处(也就是0处)可能就再也不为0,那么这就是对该user-moive对的预测。这就是SVD的主要原理。由于SVD有不少现成的算法,也不用迭代就可直接获得,因此使用比较方便。
web
可是咱们会看到,上面方法有一个致命的缺陷,那就是将未知的评分全都设为0.这实际上是极其不合理的,由于用户不给某个电影打分并非很不喜欢(0分),而是有可能尚未看过这个电影。这样就加入了咱们主观臆断的信息,最后形成错误。解决的方法就是使用隐因子的矩阵分解法。注意矩阵分解法和SVD有类似的地方也有不一样的地方,下面我就对矩阵分解法进行详细介绍。
算法
在矩阵分解法中,有一个假设,就是每个用户都有一个长度为k的特征向量,每一部电影也有一个相同长度的特征向量(k通常须要用户指定)。那么全部用户的特征向量排列成一个矩阵 U 的维度为UserNum * k。其中用户i对应的向量为Ui。全部电影的特征向量排列成一个矩阵M 的维度为MoiveNum * k。其中电影j对应的向量为Uj。那么用户i对电影j的评分 Vij = <Ui , Mj>(<>表明点乘)。那么全部用户和全部电影之间的评分就能够用两个矩阵相乘来获得:
机器学习
V' = UMT ide
注意这里是V'而不是V。那么问题来了,咱们如何肯定这个U和M?一个天然的想法就是让V'和V尽量地相等。那么这又有一个问题,那就是V(即数据集)有不少地方是没有评分的,如何判断和V'是否相等?那么咱们在这里只计算有评分处的MSE。这样既没有使用额外的信息,又能判断二者是否接近。那么天然而然得就引入了咱们的lost function:
学习
这里Iij表示用户i对电影j有评分记录。后面两项是惩罚因子,目的是防止过拟合。那么利用梯度降低法,咱们就能够经过迭代获得U和M的值。其对U和对M的求到以下:
优化
到这里咱们就已经完成了基础的矩阵分解法。那么进一步,为了实现更好的效果,咱们要考虑每一个个体打分的影响,由于有些用户打分偏高,有些用户打分偏低。一样对于电影和全部的评分。因此咱们评分的计算公式应该改成:ui
Vij = <Ui,Mj> + overall_mean + ai +bj
其中overall_mean是全部评分的平均值,ai是用户i打分的平均值,bj是电影j得分的平均值。其中overall_mean认为是一个常数,而ai和bj都是须要优化的参数。这里咱们就不给出对他们求导的式子,我直接给出矩阵形式的算法,便于你们具体实现。(INCOMING) (拖了一周左右放上去,这拖延症也是没sei了 0.0)
我本身写了一个python版的,有兴趣能够参考 https://github.com/ccienfall/RecommandSystem/blob/master/script/Factorize.py
在2016Byte Cup国际机器学习竞赛的数据集上分别运用SVD和矩阵分解(MF),最后结果是MF的方法能比SVD的效果高20%左右。
参考文献:《A Guide to Singular Value Decomp osition for Collaborative Filtering》