协同过滤方法是推荐系统采用的主要技术之一,这篇文章将要介绍此类方法中中的Weighted Slope One算法。
Slope算法的核心思想来自线性回归分析。在线性回归分析中,给定一个训练集S={<x1,y1>,<x2,y2>...<xn,yn>}, Slope One算法假设xi和yi之间符合y=x+b的线性关系,根据最小二乘法进行线性拟合的方法,可以得到令目标函数:
达到最小值的参数:
b的估计值即为训练集中数对只差的算术平均值。因此,由训练我们可以得到线性拟合公式y=x+b^.
上面即为Slope One算法的思想。其实,这个算法非常简单,举个例子:
user item_1 item_2
A 2 3
B 3 5
C 4 ?
假设用户A对item_1这个东西的打分是2,对item_2的打分是3,用户B对item_1的打分是3,对item_3的打分是5,用户C只对item_1进行了打分,那么该如何预测C对item_2的打分呢?
按照Slope One的思想,先求item_1与item_2之间的差距d=((3-2)+(5-3))/2=1.5 . 既然C给item_1打了4分,那么按照item_2与item_1的预测差距,C给item_2的打分应该是4+1.5=5.5分。
在举一个稍微复杂点的例子:
user item_1 item_2 item_3
A 2 3 1
B 3 5 3
C 4 ? 2
上一个例子拿item_1和item_2来进行了预测,这个例子中又出现了item_3,因此item_c也应该参加到预测中。item_3的与item_2的差距d=((3-1)+(5-3))/2=2,那么按照上面的预测方式C对item_2的打分应该是2+2=4。有个两个预测一个是5.5一个是4,那么最终的预测是(5.5+4)/2=4.75.
这就是Slope One算法,简单但是有效。其实,我个人理解,每个人对一个东西的打分肯定是和个人喜好有关系的,所以当数据量少的时候,两个item之间不一定呈现y=x+b关系,但是当数据量大的时候,这个模型是有效的。
再举一个例子,来说明Weighted Slope One. 假设有个新用户D
user item_1 item_2 item_3
A 2 3 1
B 3 5 3
C 4 ? 2
D 3 4 ?
现在要预测D对item_3的打分,按照上面的做法,先计算d(item_3,item_1)=((2-4)+(3-3)+(1-2))/3=-1. 然后计算d(item_3,item_2)=((3-5)+(1-3))/2=-2。按照slope one的思路就是预测item_3的分数为r=((3-1)+(4-2))/2=2.25。但是,有三个用户A,B,C提供了item_1,item_3之间差距的信息,但是只有量个提供了item_2和item_3之间的差距信息,那么明显的item_1和item_3之间的信息应该更加靠谱些,因此Weighted Slope One算法的做法就是给计算次数多的预测赋予更更高的权重,因此最终的预测是((3-1)*3+(4-2)*2)/(3+2)=2.
Weight Slope的公式是:
下面提供一个简单的wso的python代码:
myd={} # data container in the memory f=open('../testdata/cn') for line in f: line=line.strip() if not line: continue myl=line.split() user=myl.pop(0) myd[user]=[float(i) for i in myl] def predict(user,item): tp=0 tf=0 for i,rate in enumerate(myd[user]): if myd[user][i]<0: continue # the one has not been rate, so pass diff=0 # difference fres=0 # frequency for us in myd.keys(): if us==user: continue if myd[us][item]>0 and myd[us][i]>0: # have rated diff+=myd[us][item]-myd[us][i] fres+=1 tf+=1 tp+=(rate+diff/fres)*fres return tp/tf if __name__=='__main__': p1=predict('C',1) print p1 p2=predict('D',2) print p2
这端代码的输入是一个cn的文件,内容是:
A 2 3 1
B 3 5 3
C 4 -1 2
D 3 4 -1
其中的-1表示没有打分,需要预测。
实际中的数据量往往是很大的,需要采取一些其他方法来实现大数据下的运算。我曾用hadoop实现了一个wso,用了5个map-reduce过程!