矩阵的解析
矩阵分解是最近⼏年⽐较⽕的算法,经过kddcup和netflix⽐赛的多⼈多次检验,矩阵分解可以带来更好的结果,⽽且可以充分地考虑各种因素的影响,有⾮常好的扩展性,因为要考虑多种因素的综合作⽤,往往需要构造cost function 来将矩阵分解问题转化为优化问题,根据要考虑的因素为优化问题添加constraints,然后通过迭代的⽅法进⾏矩阵分解,原来评分矩阵中的missing vlaue可以通过分解后得到的矩阵求的。
本⽂将简单介绍下最近学习到的矩阵分解⽅法。
(1)PureSvd
怎么评价这种⽅法呢?开始觉得这种⽅法很神奇很数学,⽽且在实际使⽤的时候也⾮常好⽤。
但最近读了Yehuda⼤神的paper之后,觉得这种⽅法⽐较猥琐。
其实,矩阵分解的核⼼是将⼀个⾮常稀疏的评分矩阵分解为两个矩阵,⼀个表⽰user的特性,⼀个表⽰item的特性,将两个矩阵中各取⼀⾏和⼀列向量做内积就可以得到对应评分。
那么如何将⼀个矩阵分解为两个矩阵就是唯⼀的问题了。
说到这⾥⼤家就可能想起了在线代和数值分析中学到的各种矩阵分解⽅法,QR,Jordan,三⾓分解,SVD。。。
这⾥说说svd分解。
svd是将⼀个任意实矩阵分解为三个矩阵U,S,V,其中,U,V是两个正交矩阵,称为左右奇异矩阵,S是个对⾓阵,称为奇异值矩阵。
其实svd分解的问题可以化解为特征值分解的问题。
评分矩阵A(m*n)=U(m*k)*S(k*k)*V'(k*n)
令B(m*m)=A(m*n)*A'(n*m)
B矩阵就是⼀个⽅阵,可以利⽤各种简单的⽅法将B进⾏特征值分解:
Bv=av,
v是⽅阵B的特征向量,a是特征向量v对应的特征值。
所以奇异值s=sqrt(a),
左奇异向量u=A*v/s正则化一个五行五列的随机矩阵
同样的⽅法可以求得右奇异向量。
这样我们就得到了svd分解后的三个矩阵。(你可以⾃⼰写个c程序计算,当然也可以⽤matlab算算得到)
分解后的三个矩阵都有着各⾃的意义,
U:每⼀⾏表⽰⼀个user的特征。
V:每⼀列表⽰⼀个item的特征。
S:表⽰对应的user和item的相关性。
所以可以考虑⽤U和V将S吸收进来,形成两个矩阵分别表⽰user的矩阵和item 的矩阵。
得到这个以后后⾯的事情就好办了。
为什么说这个⽅法猥琐呢?
因为我觉得,这种⽅法有着矩阵分解算法的表,却可以⾮常简单地完成矩阵的分解,然后填充稀疏的评分矩阵。
但它考虑的因素太少了,不过对于简单的推荐系统,这种⽅法还是⾮常有意义的,容易实现,⽽且结果也不会太差。
(2)Latent Factor Model
这是真正的矩阵分解算法,经过实践检验,具有⾮常⾼的准确性和易扩展性。
正如上⾯提到的,实现推荐系统结果的⽬标是将那个稀疏的评分矩阵分解成两个矩阵,⼀个表⽰user的feature,⼀个表⽰item 的feature,然后做内积得到预测。
当然要实现满⾜⼀定约束条件的矩阵分解,可不像上⾯的PureSVD那样容易,需要构造⼀个优化问题,⽤⼀些复杂的算法求解优化问题。⽽这些优化问题往往是NP问题,只有局部最优解。
⾸先构造⼀个优化⽬标函数,
考虑到最后的评价指标是预测分值和实际分值之间的误差的平⽅(RMSE),所以构造的⽬标函数也是误差的平⽅的函数。
为什么这样的算法可以得到更优的结果呢?因为算法可以很容易地扩展很多的feature进来,更加出⾊地考虑了多种影响推荐效果的实实在在的因素。
Biases
因为有的⽤户总是会打出⽐别⼈⾼的分,或者说有的⽤户他的评价尺度⽐较宽松;同样有的item总是被打⾼分。这是⼀个普遍存在的问题,所以在构造⽬标函数的时候需要增加⼏项:所有评分的平均值miu,user的偏见分数bu,item 的偏见分数bi。
⽐如:求⽤户x对电影y的打分,
所有评分电影的评分的平均分是miu=3.5,
电影y⽐所有评分电影平均分⾼bi=0.5
但是⽤户x是个⽐较严格的⽤户,评分总是相对偏低,所以bu=-0.3
所以⽤户x对电影y的打分为3.7
Implicit feedback
⽤户在使⽤web应⽤的时候,会产⽣⼤量的⾏为,充分挖掘这部分的价值,将会很好地提升推荐的效果。
利⽤⽤户的隐式反馈,相当于充分的利⽤了评分矩阵中的missing value的价值,⽤户在页⾯的停留时间,检索,浏览,点击等等各种⾏为都可以建模,内含到⽬标函数中。
这⾥,可以将简单地⽤⼀个Boolean来描述⼀种⾏为有还是没有。
不过在使⽤的时候,需要进⾏归⼀化处理。
User-associated attributes
基于⽤户的社会化属性进⾏推荐也是⼀种很基本的推荐,当然也可以考虑到⽬标函数中。
Temporal dynamics
⽤户的兴趣包括长期和短期,动态地考虑⼀段时间内⽤户的兴趣是很有必要的。
上⾯的⼏个因素中随着时间变化的有,user的bias项bu=bu(t),item的bias 项bi=bi(t),以及user的factor向量pu=pu(t),这⾥可以忽略item的factor 向量的变化,因为item是⽐较稳定的。
Confidence level
因为在处理上述的因素的时候,很多都是⽐较主观的,所以需要给每个因素添加⼀个置信权重,以平衡整个结果。
通过构造出这个⽬标函数,然后添加相应的约束条件,接下来的问题就是求解这个优化问题。
通常⽐较好的⽅法是Stochastic gradient desent。
PS:这种⽅法是现在学术界的主流⽅法,⼤家可以参阅Yehuda的神作
(www.doczj/doc/d418392625.html
/Yehuda_Koren)以及上海交⼤在今年kddcup获奖⽅法的paper以及他们的开源系统
(www.doczj/doc/d418392625.html
/apex_wiki/svdfeature)
(3)NMF(⾮负矩阵分解)
很多⼈⽤这种⽅法是因为他们觉得只有⼀个⾮负的值对于实际的例⼦才会有意义。
考虑到svd或者latent factor model会得到负的值,所以这种⽅法的物理意义⽐较明确。
同样的道理,NMF也是将评分矩阵的转置矩阵分解成两个矩阵。
不同的是这两个矩阵有着和上⾯的矩阵不同的物理意义。
其中⼀个是基矩阵W,另⼀个是投影矩阵H,即R'(n*m)=W(n*r)*H(r*m)
W:每⼀列包含⼀个基向量,这组基向量构成⼀个r维的空间。
H:每⼀列则近似为原始数据对应的列向量在该r维空间的投影。
做这个分解的⽅法也是构造⼀个⽬标函数和⼀些约束条件,然后⽤梯度下降的算法来计算得到⼀个局部最优解。
这种⽅法的思路⼤概是这样的:
将评分矩阵转置然后分解成两个矩阵W和H。
根据基矩阵W,可以计算得到⽬标⽤户评分向量a对基矩阵W的投影向量h。
计算投影向量h与投影矩阵H各⾏之间的欧式距离,将其中距离最⼩的前k个⽤户组成⽬标⽤户a的最近邻集合。
然后⽤⽪尔逊相关法将最近邻集合中的数据进⾏加权计算,然后排序进⾏推荐。
可以看出来,这种⽅法的思路和上⾯的两种还是很不相同的,主要还是在计算⽬标⽤户的最近邻集合,主要思想还是knn,只是在中间⽤了矩阵分解的⽅法降维降低了计算的时间复杂度。
矩阵分解在学习的时候感觉既没⽤⼜⿇烦,尤其是线代⾥⾯做矩阵的分解计算,⽆聊的很。
现在看来,矩阵分解⾮常有意义。
续:
最近研究了下Yehuda⼤神的paper,学习了下矩阵分解⽅法在推荐系统中如何⽤。
本⽂中提到的矩阵分解是⼀般的分解,即R=M*N的形式。
1、矩阵分解⽅法的来源
CF⾥的矩阵分解思想是来⾃于IR领域的Latent Semantic Analysis(LSA)。
google⿊板报的《数学之美》中很清楚地讲了SVD分解在IR中的应⽤。
(www.doczj/doc/d418392625.html
/ggblog/googlechinablog/2006/12/blog-post_8 935.html)
2、矩阵分解的优劣
优点是:
⽐较容易编程实现
⽐较低的时间和空间复杂度
预测的精度⽐较⾼
⾮常好的扩展性
缺点是:推荐的结果不具有很好的可解释性。因为把ratings matrix分解成user-factor matrix和item-factor matrix,这⾥的factor 很难⽤实际意义的概念来解释。不过,矩阵分解的过程相当于⼀个软聚类的过程,得到的每⼀个factor相当于每⼀个聚类后的分组,只是我们没有⼀个通⽤的⽅法来为这些分组命
名。
但是在实际的应⽤中,我们可以提取这些分组中最突出的特点来给这些factor 命名。⽐如,拿新闻资讯类的推荐系统来说,做好分解之后,每个factor都可以看成是⼀类资讯,可以从这些资讯中提取⼀些特征来给这个factor命名。
3、矩阵分解的模型(Latent Factor Model)
矩阵分解的思路是把评分矩阵通过分解,⽤⼀个低秩的矩阵来逼近原来的评分矩阵,逼近的⽬标就是让预测的矩阵和原来的矩阵之间的误差平⽅最⼩。(矩阵分解⼀般不⽤数学上直接分解的办法,尽管分解出来的精度很⾼,但是效率实在太低!矩阵分
解往往会转化为⼀个优化问题,通过迭代求局部最优解。)
但是有个问题是,原来的评分矩阵的稀疏度太⼤,分解很容易产⽣overfitting (过度拟合,意思就是为了迁就⼀些错误的偏僻的值导致整个模型错误)的问题。
所以现在的⽅法是在⽬标函数中增加⼀项regularization(正则化),来避免overfitting问题。
所以⼀般的矩阵分解的⽬标函数(或者称为loss function)是:
前⼀项是预测后的矩阵和现有的评分矩阵的误差,这⾥计算只针对评分矩阵中已经评分的项。
后⼀项就是正则化项,⽤来解决过度拟合的问题。
这个优化问题求解的就是分解之后的user-factor,item-factor矩阵的factor 向量。(qi是item的factor向量,pu是user的factor向量)
求解这个优化问题常⽤两种⽅法,⼀种是alternative least squares(交叉最⼩⼆乘法),另⼀种是stochastic gradient descent(随机梯度下降法)。
前⼀种⽅法会涉及到矩阵的求逆问题,所以计算起来会⽐较⿇烦。
后⼀种⽅法,只需要求梯度,就可以迭代计算了,因此会简单很多。
迭代⽅程如下:
其中,gamma是学习速率,lamda是正则化系数,是两个可选的参数,⽽且对于最后的结果⾮常重要。
这⾥,gamma的⼤⼩不仅会影响到训练时间,还会影响到结果的收敛性。gamma 太⼤的话会导致结果发散,⼀般都会把gamma取得很⼩,不同的数据集取得值不同,但⼤概是0.001这个量级。这样的话训练的时间会长⼀些,但结果会⽐较好。lamda的值⼀般也⽐较⼩,⼤概取0.01这个量级就好了。
迭代开始前,需要对user和item的特征向量赋初值,这个初值很重要,会严重地影响到计算速度。⼀般的做法是在所有已评分的平均分附近产⽣⼀些随机数作为初值。
迭代结束的条件⼀般是loss function开始增加了,或者loss function的值⼩于了某⼀个阈值。
当我们拿到计算出来的user,item的factor向量后,最后预测结果时有两种选择,⼀种是保留计算出来的⼩数rating,⼀种是将这些⼩数rating四舍五⼊并裁减到[1,5]这个区间内。
对于实际的推荐系统来说,结果是⼩数还是整数,没有所谓,因为我们并不会把预测的分数给⽤户看,⽽只是返回⼀个推荐列表。
但对于线下训练参数或者做论⽂的童鞋来说,不同的处理⽅法得到的RMSE或者MAE的值可不相同。
我⽤这个的算法对movielens 100k的⼩数据做了测试,⽤很短的时间就可以计算好,不过那些参数的选
择需要不断地⽤RMSE 来计算得出。在其他的信息都没有利⽤的情况下,也可以得到0.90这个量级的RMSE。
4、增加⼀些扩展项
上⾯的模型中只简单的⽤了已知的评分数据,很多的信息都没有考虑进来。(1)增加biases信息
因为有的user总是趋向于打⼀个很⾼的分,⽽有的user⽐较严格,总是打⼀个很低的分,有的item总是被打⼀个很⾼的分,⽽有的item总是被低估。所以我们需要给模型增加biases项,loss function如下:
迭代⽅程变成了:
同样的⽅法,只是多了对bu和bi的赋初值。
同样,我⽤movielens的100k数据计算,得到的RMSE值也在0.90这个量级,但整体要⽐没有考虑biases结果好。
(2)增加implicit feedback信息
评分是⼀个显性的反馈⽅式,然⽽在很多时候显性的反馈很少很少,⽽user的很多⾏为都可以反映出他们对item的态度,所以利⽤implicit feedback是⾮常必要的。给模型增加implicit feedback项,预测模型如下:
迭代⽅程如下:
implicit feedback信息对于商城来说,可能是购买,浏览等等⾏为,对于Netflix 这样的⽹站来说,可能是浏览,租赁等等。
(3)考虑temporal信息
因为⽤户的兴趣或者对某⼀个item的态度是和时间有关的,⽐如说,可能我今年不太喜欢西服这个东西,因为我⽤不着,所以我不会购买,但可能若⼲年后我不得不穿西服的时候,我⼀定会去买,也就是说我给推荐系统留下我喜欢西服这个东西的印象。(即使我真的不喜欢西服。)
动态地考虑user的兴趣或者需求是⾮常必要的。
矩阵分解是当下⾮常流⾏的算法,可以考虑将这种算法和传统的KNN结合在⼀起来做推荐,相信效果会很不错。
电⼦商务
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论