zoukankan      html  css  js  c++  java
  • Weighted Slope One 算法

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

  • 相关阅读:
    android的布局管理器
    android控件---自定义带文本的ImageButton
    新建android项目src和layout文件夹中没有内容的问题
    android控件---spinner
    maven+springMVC+mybatis+junit详细搭建过程 ***
    JUnit4的使用
    Jenkins集成Docker镜像实现自动发布
    Docker部署tomcat及应用
    Docker的离线安装
    Java中的static关键字解析
  • 原文地址:https://www.cnblogs.com/naniJser/p/2976508.html
Copyright © 2011-2022 走看看