Programming Collective Intelligence notes

Programming Collective Intelligence notes

第二章 提供推荐

引言

  协同过滤首次出现在《Using collaborative filtering to weave an information tapestry》论文中。他设计了一个名叫Tapesrty的系统,该系统允许人们根据自己对文档感兴趣的程度为其添加标注,并利用这一信息为他人进行文档过滤。

搜集偏好

  以字典格式存储偏好:{user:{‘movie’:socre}}
尽管可以将相当数量人员的偏好信息存储于字典中,但对于一个规模巨大的数据集,还是存在数据库比较方便。

相似度评价

  此处采用了欧几里得距离和皮尔逊相关系数。皮尔逊相关系数可以修正“夸大分值”,即如果A倾向于给出更高的分值,B倾向于给出更低的分值,他们对于movie1和movie2的偏好相同,此时用欧式距离,A和B的偏好相似会被低估。

编程tips:

  1. 对于功能相似的函数编写,尽量使用相同的签名;
  2. 在编写函数的时候,必须考虑到所有输入可能的情况,包括缺失值、分母为0等,需要使用if函数或者其他方式收集这些情况;
  3. 得到结果后,注意排序,sort(reverse=True);
  4. 列表推导式非常强大,可以同时接for循环和if逻辑判断.

点击链接可以了解到不同的距离度量算法

基于用户的协作型过滤

def getRecommendations(prefs,person,similarity=sim_pearson):
    totals={}
    simSums={}
    for other in prefs:
        if other==person:continue
        sim=similarity(prefs,person,other)
        #忽略相关系数小于等于0的情况
        if sim<=0:continue
        for item in prefs[other]:
            #只对自己还未曾看过的影片进行评价
            if item not in prefs[person] or prefs[person][item]==0:
                #相似度*评价值
                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(reverse=True)
    return rankings

基于物品的协作型过滤

  注意setdefault函数,非常强大,可以用于实现设定字典的层数。如果不这么做的话,默认键值对的值只能是单层的,不能写入字典。

def transformPrefs(prefs):
    result={}
    for person in prefs:
        for item in prefs[person]:
            result.setdefault(item,{})
            #将物品和人员对调
            result[item][person]=prefs[person][item]
    return result
	#基于物品的协作型过滤(item-based collaborative filtering)
	#构建物品比较数据集
def calculateSimilarItems(prefs,n=10):
    #建立字典,以给出与这些物品最为相近的其他所有物品
    result={}
    #以物品为中心对偏好矩阵实施倒置处理
    itemPrefs=transformPrefs(prefs)
    c=0
    for item in itemPrefs:
        #创建大数据集更新状态变量
        c+=1
        if c%100==0:print('%d /%d'%(c,len(itemPrefs)))
        #寻找最为相近的物品
        scores=topMatches(itemPrefs,item,n=n,similarity=sim_distance)
        result[item]=scores
    return result
	#为某人提供基于物品的推荐
	#例如,A对电影1的评价是4分,电影1和电影2的相似度是0.5,计算加权得分就是0. 5*4
def getRecommendedItems(prefs,itemMatch,user):
    userRatings=prefs[user]
    scores={}
    totalSim={}
    #循环遍历由当前用户评分的物品
    for (item,rating) in userRatings.items():
        #循环遍历与当前物品相近的物品
        for (similarity,item2) in itemMatch[item]:
            #如果该用户已经对当前物品做过评价,则将其忽略
            if item2 in userRatings: continue
            #评价值与相似度的加权之和
            scores.setdefault(item2,0)
            scores[item2]+=similarity*rating
            #全部相似度之和
            totalSim.setdefault(item2,0)
            totalSim[item2]+=similarity
    #将每个合计值除以加权和,求出平均值
    rankings=[(score/totalSim[item],item) for item,score in scores.items()]
    #按最高值到最低值的顺序,返回评分结果
    rankings.sort(reverse=True)
    return rankings
	##在调用getRecommendedItems时,我们不必再为所有其他评论者计算相似度评价值,因为物品相似度数据集已经实现构造好了

使用movielens数据集

  下载数据后,首先观察原csv文件的数据结构。这么做的目的是:

  1. 搞清楚有多少行、列,列名及代表的含义;
  2. 检查数据是否存在缺失值,如果存在的话,在代码中需要设置相关命令;
  3. 分隔符如何设定,标题行是否需要读入。

编程tips:

  • 使用itertools包的islice函数可以极大促进迭代的效率,语法为islice(iterable,start,stop,step)
  • split函数的使用,多值同时赋值的使用,变量类型转换需要掌握;
  • readlines直接用,进行分隔即可,不需要\t或者\n
#使用movielens数据集
def loadMovieLens(path=''):
    #获取影片标题
    movies={}
    for line in islice(open(path+'movies.csv'),1,None):
        (id,title)=line.split(',')[0:2]
        movies[id]=title
    prefs={}
    for line in islice(open(path+'ratings.csv'),1,None):
        (user,movieid,rating,ts)=line.split(',')
        prefs.setdefault(user,{})#设置prefs的参数为字典嵌套字典
        prefs[user][movies[movieid]]=float(rating)
    return prefs

基于用户与基于物品的效果对比

the advantages of item_based collaborative filtering:

  • 针对大数据集生成推荐列表时,基于物品进行过滤的方式明显要比基于用户的过滤更快,但维护物品相似度表需要额外开销;
  • 对于小众群体偏好,大概率存在稀疏数据集,基于物品的过滤方法从计算消耗上优于基于用户的过滤方法。

the advantages of user_based collaborative filtering:

  • 对于密集数据集,效果和基于物品的推荐系统差不多;
  • 更易于实现,无需额外步骤(维护物品相似度表),更适用于规模较小的、变化非常频繁的内存数据集;
  • 在一些应用中,告诉用户有哪些人与自己有着相近偏好是有一定价值的,例如交友推荐。

提示:要了解更多有关算法在执行效率上的差异,可以参考《基于物品的协作型过滤推荐算法》(Item_based Collaborative Flitering Recommendation Algorithms)

你可能感兴趣的:(Programming Collective Intelligence notes)