现在的位置: 首页 > 综合 > 正文

Weighted Slope One 算法

2013年01月29日 ⁄ 综合 ⁄ 共 2105字 ⁄ 字号 评论关闭

协同过滤方法是推荐系统采用的主要技术之一,这篇文章将要介绍此类方法中中的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过程!

 

抱歉!评论已关闭.