SLIM推荐模型及分析

 SLIM[1]是Sparse Linear Model简称,即稀疏线性模型,该方法是基于物品相似度的推广形式,而且效果很好,如下面公式

minimize ||AAW||22+β2||W||22+λ||W||1(1)

subject to Wi,j>=0,Wi,i=0

其中,A为user-item评分矩阵,W为item的聚合系数矩阵,β、λ为外部设置的标量参数。后面两项为常见的正则项,控制W大小和稀疏程度。
 由于,W的各列之间可以独立学习,满足分布式学习的条件,上述公式可以细化为
minimize ||ajAwj||22+β2||wj||22+λ||wj||1(2)

subject to wi,j>=0,wj,j=0

可以看出非常适合map-reduce的形式。
 该思想主要是将传统的基于内存的itemNN方法进行改造,通过学习评分矩阵的形式计算相似度矩阵W,顺便提一下,传统的很多计算相似度方法存在某种假设即相似度和贡献度(上面的聚合系数)等价,但实际item-a对item-b的评分贡献度和item-b对item-a的评分贡献度未必一样,而相似度的形式具有非常强对称性的假设条件,且传统相似度是通过直接统计得到而贡献度通过学习得来,这里理解贡献度请从(2)式来看,这几年一些论文对相似度重新学习。

 SLIM从HR和ARHR指标来看效果很好,而且方法简单直观,原文提到(2)实现方法为坐标梯度下降和软阈值[2],但是这种方法的效果存在一定度质疑即如何保证约束条件或者在满足约束条件下找到较好的局部最优值,而且复杂度在一定容忍范围内,另外librec包在实现这种方法提出质疑。那么实现这种受限域内寻找最优值的问题,至少存在两种方法(针对这个问题已经实现),一个是随机梯度下降SGD,另一个SLIM提供的源码(BCLS库)。
  SGD的方法在RecSys上有一篇短文[3],具体办法就是通过采样的小样本集上执行Scikit-learn.SGDRegressor来获取最好的(1)参数,即增加一个预处理步骤,这里trick就是每次得到的W来观察,保证其具有一定稀疏性范围,具体实验需要调试这些“超参数”。但是w在这个子学习过程中并不能保证满足(2)中约束(非负),在得到w后直接截断使其全部非负,这种暴力的方法使得其效果具有一定的局限性。且这种方法需要花较多时间在寻找参数上,另外,在复现过程中到底有没有原文中那么好呢?(注意:SGD和原文方法均进行参数调优)。
  为了复现SGD这种方法的可靠性并同原始SLIM进行对比,我们在MovieLen-100K(简称ML-100K)上进行实验,这里提一下该数据集有#users=943,#items=1682和评分集合为#ratings={0,1,2,3,4,5},其中0表示没有评分,实验数据经过下面三种预处理后最终在二值评分矩阵({0,1}),如下表

Config entries discard rating test rating split binarize fold evaluate-indicator TOP-k
1 55375 <=3 >3 1/2-items yes 5 P,MRR 5,10,15,20,25,30
2 100000 0 >3 One-item yes 5 HR,ARHR 5,10,15,20,25,30
3 100000 0 >0 One-item yes 5 HR,ARHR 5,10,15,20,25,30

(上述表格将ML-100K进行三组实验,分别表示:(1).将原始评分矩阵进行二值化,评分不高于3的部分作为0,高于3作为1,这时候对于每个user从其评分历史中随机选择一个评分为1的item放入test set中,剩下则作为train set,评价指标为准确率HR和ARHR);(2).同(1)但对于每个user从其评分历史随机选择一半评分为1的items放入test set中,评价指标为准确率p和MRR);(3).原始评分矩阵中先对于每个user从其评分历史中随机选择一个评分为1的item放入test set中,剩下则作为train set;再对这两个set进行二值化,大于0为1,否则为0。注意:这里均进行五折验证且推荐结果在top {10}上进行评估。)
 对SGD方法在数据集上进行一定的参数调优(注意:SGD和SLIM具体实现方法不同故其参数空间不同,简单说一个是线性学习一个批量学习,故正则项参数不相同,且前者远小于后者,相当于后者的正则项值划分给各样本上的,且SGD随机顺序以及步长衰减),最终每个方法在每种配置上最好的结果,这里只列举SLIM/SGD在top-10的结果如下表

Config P@10(%) MRR@10(%)
1 34.2/35.63 63.63/65.41
Config HR@10(%) ARHR@10(%)
2 38.43/35.18 18.89/15.77
3 33.28/30.71 15.78/13.88

可以看到,SGD实现方法相对原始SLIM实现方法存在一定的精度损失,SGD不能完全通过采样调整参数达到SLIM的效果,而且实验结果表明SLIM原始实现方法对参数具有很好的稳定性。上述两种方法非常适合大型稀疏二值矩阵的情况。另外,通过实验发现SGD对于多值的情况很不稳定,即SGDRegressor后存在大量的非负截断情况。由此可见,SGD适合于二值矩阵的情况。SLIM原始方法计算得到的W具有较好的稀疏性,但也存在某些列全部为0的情况。
 那么原文SLIM使用什么方法呢?具体翻阅代码查看作者实际调用BCLS库(linux下纯c源码包)来实现(2),而BCLS调用流程来看其存在一定的优势:1.受限域的条件在每个子学习过程中都得到强调 2.采用拟牛顿法和线性搜索分别控制受限空间下的搜索方向和步长。关于这两部分的贡献到底有多大呢?
 这部分我们通过实验来进行验证,就拿上面的三个实验,进行对比存在约束条件(w>=0)和无约束条件下的结果,下表是在有/无约束下的结果:

Config P@10(%) MRR@10(%) W-Density(%) W-AveVal
1 34.2/33.3 63.63/63.09 4.71/14.64 0.011/0.01
Config HR@10(%) ARHR@10(%) W-Density(%) W-AveVal
2 38.43/29.58 18.89/12.84 6.3/34.67 0.013/0.021
3 33.28/26.63 15.78/10.89 1.86/34.71 0.019/ 0.016

(注意:具体实现需要在linux下进行,由于SLIM代码依赖于BCLS、GK源码,需要重新编译,其中过程也比较复杂,一些包需要重新编译,没有文档,需要打开各种源码文件查看依赖关系手动构建makefile文件进行子项目编译,然后静态库链接编译执行等,其中会出现各种配置问题,导入路径等,对于不熟悉linux下完整c项目编译执行有一定工作量,不过c的执行速度还是相当快)。
 上表可以看到,如果废除约束限制,其效果和W稀疏性会急剧降低,且W的非0部分均值非常小,从Config-2和Config-3来看,原始SLIM好于SGD,故SLIM方法的较好效果很大部分归功于受限域贯穿于整个优化各子过程中。故对于稀疏矩阵的学习需要保证学习得到的W尽可能的稀疏,同时保证结果同时具有良好的解释性。从上面还可以看到,在SLIM在HR和ARHR指标上非常不错,但是在P和MRR未必最优,这里需要注意的两种指标的使用配置不同,前者基于user的单个item而后者基于user的items进行评估,这也就说明SLIM非常适合top-rating那一撮部分在测试样本中的预测。
 下面是BCLS的核心过程,当然细节很多,纯c实现标准包具有良好的代码规范,而且看别人代码不仅能提高编程规范技巧,还有一些经验trick等,比如快速迭代求开方等,算法中一些经验值需要反复实验得到。

// 设置itnMajLim和itnMinLim
While(1) // Major iteration
    计算f值,判断哪些维度自由维度nFree
    If (nFree>1) // Minor iteration
        Newton_LSQR计算dxFree(注:这里变换之后最终调用经典LSQR算法)
    Proj_search计算step(注:这里还判断dx合理性以及Boundarize)
    统计信息,评价(最大双不可行性,经验阈值)
    判断是否退出
    更新x(k+1)=x(k)+dx*step (注意:dx表示拟牛顿下降方向,同g不同)

科学是不断证伪的。


[1]: SLIM: Slim_ Sparse linear methods for top-n recommender systems.
[2]: Regularization paths for generalized linear models via coordinate descent.
[3]: Efficient Top-N Recommendation by Linear Regression.

你可能感兴趣的:(RS)