推荐算法1-基于用户的协同过滤

1 介绍

基于用户的协同过滤推荐(User-based-Recommendation)是协同过滤的一种。基本思想很简单:人以群分,相似用户喜欢的东西也会有共同之处。

基于用户的协同过滤算法主要包含两个步骤:
1)找到和目标用户兴趣相似的用户群;
2)找到这个用户群中用户喜欢的,而目标用户没有看过(听过\点击过)的物品推荐给该用户
——当然还需要给出一个顺序。

2 找到相似的用户群

可以使用距离差别,两两用户比较,距离越近表示越相似;或者相关系数差别:如皮尔森系数。或者余弦等。

2.1 使用欧式距离计算用户间相似性

以用户间都参与过评价的物品为坐标轴,对每个用户形成一个偏好空间(每个用户对每个物品的评分,就是该用户在对应坐标轴上的取值),直观上看,距离相近的用户相似性越大。

再将距离转换成0-1之间的值即可:+1 取倒数,这样得到的结果即是:越接近1,越相似。

《推荐算法1-基于用户的协同过滤》 偏好空间示例,横轴为电影名

计算代码:

# 采用欧式距离计算用户之间的相似性:

from math import sqrt

def sim_distance(prefs,person1,person2):
    #得到shrared_items 列表
    si = {}
    for item in prefs[person1]:
        if item in prefs[person2]:
            si[item]=1
    #print(si.keys())
    # 如果两者没有共同之处,则返回0
    if len(si)==0: return 0
    
    # 计算所有差值的平方和
    
    sum_of_squares = sum([pow(prefs[person1][item]-prefs[person2][item],2) for item in si.keys()])
    return 1/(1+sqrt(sum_of_squares))

实际应用时,会选则与目标用户最相似的top K 个用户来进行推荐计算,K是一个可调整参数。

2.2 选择top K 用户

#相似性排序,针对目标用户,选出与之最为相拟的用户群;
#注意,选top多少的用户,是推荐系统的一个可调变量,此处设计为10

def topMathches(prefs,person,n=10,similarity = sim_distance):
    scores=[(similarity(prefs,person,other),other) for other in prefs if other != person]
    
    #对列表进行排序,相似性最高的排在前面。
    scores.sort()
    scores.reverse()
    
    return scores[0:n]

3 相似用户群喜欢的‘新物品’

最简单的方式:上述K个最相似用户,看过的物品,而目标用户没有看过的物品,按这K个用户的评分求和排序,即可得到一份排序推荐表。

这样就忽略了‘相似’这个度量。

《推荐算法1-基于用户的协同过滤》 推荐计算:相似度*评分,对每个物品得出S.xNight等,求出总计行,Sim.Sum 是对该物品有评价的用户相似度之和

更优方式:针对目标用户A,其最相似用户B、C、D,相似性依次是Bs\Cs\Ds,对A未看物品itemx的评分依次为b、c、d
则计算出itemx的推荐值 = (Bsb + Csc + Ds*d)/ sum(Bs,Cs,Ds)

# 利用所有他人评价值的加权平均,为某人提供建议
def getRecommendations(prefs,person,similarity=sim_distance):
    totals = {}
    simSums = {}
    
    for other in prefs:    
        # 不和自己比较
        if other==person: continue
        sim=similarity(prefs,person,other)
        
        #忽略相似性为0或小于0的情况
        if sim<=0: continue
        for item in prefs[other]:
            
            #只对目标用户还未曾看过的物品进行计算:
            if item not in prefs[person]:
                totals.setdefault(item,0)
                totals[item]+= prefs[other][item]*sim
                
                #相似度之和:
                simSums.setdefault(item,0)
                simSums[item]+=sim
        
        #建立一个归一化的列表:
        
        rankings = [(total/simSums[item],item) for item,total in totals.items()]
        
        #返回经过排序的列表。
        
        rankings.sort()
        rankings.reverse()
        
        return rankings

4 补充说明:

采用movielens数据计算。

未决问题

  • 只用top K 个用户进行计算;
  • 划分测试集,评价推荐效果;
  • 相似性计算,其它相似性度量方法;
  • 欧式距离计算,不同用户,共同评价物品数量不同,计算距离时大小会有差异,这个是否会影响相似性比较?

参考
项亮,《推荐系统实践》
Toby,《集体智慧编程》

    原文作者:废柴社
    原文地址: https://www.jianshu.com/p/dde92ede7d98
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞