py2.7 《集体智慧编程》chapter2:提供推荐

一、搜集偏好(构造数据集):

#使用字典嵌套构造数据集:一个涉及影评者及其对几部影片评分情况的字典
critics={'Lisa Rose': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.5,
 'Just My Luck': 3.0, 'Superman Returns': 3.5, 'You, Me and Dupree': 2.5,
 'The Night Listener': 3.0},
'Gene Seymour': {'Lady in the Water': 3.0, 'Snakes on a Plane': 3.5,
 'Just My Luck': 1.5, 'Superman Returns': 5.0, 'The Night Listener': 3.0,
 'You, Me and Dupree': 3.5},
'Michael Phillips': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.0,
 'Superman Returns': 3.5, 'The Night Listener': 4.0},
'Claudia Puig': {'Snakes on a Plane': 3.5, 'Just My Luck': 3.0,
 'The Night Listener': 4.5, 'Superman Returns': 4.0,
 'You, Me and Dupree': 2.5},
'Mick LaSalle': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0,
 'Just My Luck': 2.0, 'Superman Returns': 3.0, 'The Night Listener': 3.0,
 'You, Me and Dupree': 2.0},
'Jack Matthews': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0,
 'The Night Listener': 3.0, 'Superman Returns': 5.0, 'You, Me and Dupree': 3.5},
'Toby': {'Snakes on a Plane':4.5,'You, Me and Dupree':1.0,'Superman Returns':4.0}}
#该字典使用了1~5的评分等级来代表用户对物品的喜爱程度

测试样例:

from recommendations import critics
print critics['Lisa Rose']['Lady in the Water']
print critics['Toby']

效果:

2.5
{'Snakes on a Plane': 4.5, 'Superman Returns': 4.0, 'You, Me and Dupree': 1.0}


二、寻找相近的用户:

1、欧几里得距离评价

解释:两个人在“偏好空间”中的距离越近,他们的兴趣偏好就越相似。但是当两个人中有一个人比较极端,或者严格每次比另外一个人大,得到的结果偏低,其实并不准确

#欧几里得距离评价
from math import *
def sim_distance(prefs , person1,person2): #返回p1和p2基于距离的相似度评价
    #得到一个shared_items的列表
    si = {}
    for item in prefs[person1]:
        if item in prefs[person2]:
            si[item] = 1
    if len(si) ==0 : return 0 #如果两者没有共同之处,返回0

    #计算所有差值的平方和
    sum_of_squares = sum([pow(prefs[person1][item]-prefs[person2][item],2)
                          for item in prefs[person1] if item in prefs[person2]])
    return 1/(1+sqrt(sum_of_squares)) #加1防止遇到除以0,被1除将相似度局限于0~1之间

测试:

import recommendations
print recommendations.sim_distance(recommendations.critics , 'Lisa Rose' , 'Gene Seymour')
输出:

0.294298055086

2、皮尔逊相关系数评价

解释:通过利用协方差的特性来描述两个事件是否相关,以及通过模拟皮尔逊相关系数的公式。优点是不受极限情况干扰

#皮尔逊相关系数:实质是协方差除以p1,p2标准差乘积
def sim_pearson(prefs , p1 , p2):
    #得到双方都曾经评价过的物品列表
    si = {}
    for item in prefs[p1]:
        if item in prefs[p2] : si[item] = 1
    #得到列表元素个数
    n = len(si)

    #如果没有共同爱好 返回1
    if n==0 : return 1

    #对所有偏好求和
    sum1 = sum([prefs[p1][it] for it in si]) #对于求期望而言,他们概率不是1就是0
    sum2 = sum([prefs[p2][it] for it in si])

    #对所有偏好求平方和
    sum1Sq = sum([pow(prefs[p1][it],2) for it in si])
    sum2Sq = sum([pow(prefs[p2][it],2) for it in si])

    #求乘积之和
    pSum = sum([prefs[p1][ti]*prefs[p2][ti] for ti in si])

    #计算皮尔逊相关系数
    num = pSum - (sum1*sum2/n)
    den = sqrt((sum1Sq - pow(sum1, 2)/ n) * (sum2Sq - pow(sum2, 2) / n))
    if den==0 : return 0
    r = num/den
    return r
测试:

import recommendations
print recommendations.sim_pearson(recommendations.critics, 'Lisa Rose', 'Gene Seymour')

输出:

0.396059017191

三、为评论者打分:

在上面的数据集我们已经知道了每个人对不同物品之间的打分,以及使用两种计算相似度的方法去计算两个人之间的相似度,这里我们整合起来给出已知的一个人,求出另外其他人中与他评论最相似的n个人(n为降序排列,默认为5)

#为评论者打分
#从反映偏好的字典里返回最佳匹配者
#让返回结果的个数和相似度函数均为可选参数
def topMatches(prefs,person,n=5,similarity=sim_pearson): #数据集,需要观察的人,默认降序的5个人,默认使用皮尔逊相关系数
    scores = [(similarity(prefs,person,other),other)
              for other in prefs if other!= person] #在列表中找到不是自己的人进行similarity方法
    #对列表进行排序,评价最高的排在前面
    scores.sort()
    scores.reverse()
    return scores[0:n]
测试

import recommendations
print recommendations.topMatches(recommendations.critics,'Toby',n=3)
结果:

[(0.9912407071619299, 'Lisa Rose'), (0.9244734516419049, 'Mick LaSalle'), (0.8934051474415647, 'Claudia Puig')]

四、推荐物品:

这部分我们想得到一份影片的推荐,但是存在:1.别人没评价我们很喜欢 2.热衷某类影片的古怪评论者,但大部分人都不喜欢的影片从而干扰推荐

因此对所有影片进行加权评价来打分。我们先经过评价结果得到相似度,在对相似度乘以他们的评价值,得到加权后的评价值

#利用所有他人评价值的加权平均,为某人提供建议
def getReconmmendations(prefs,person,similarity=sim_pearson):
    total = {}
    simSums = {}
    for other in prefs:#循环查找prefs字典的其他人,与参数person得到影片相似度
        #不和自己比较
        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:
                #相似度*评价值
                total.setdefault(item,0)#setdefault方法:如果键不存在则设为默认值0
                total[item]+=prefs[other][item]*sim #每一项的评价值*相似度并且累加
                #相似度之和
                simSums.setdefault(item,0)
                simSums[item]+=sim
    #建立一个归一化的表
    rankings = [(total/simSums[item],item) for item,total in total.items()]
    #返回排序列表
    rankings.sort()
    rankings.reverse()
    return rankings

测试:

from recommendations import *
print getReconmmendations(critics,'Toby') 
效果:

[(3.3477895267131013, 'The Night Listener'), (2.8325499182641614, 'Lady in the Water'), (2.5309807037655645, 'Just My Luck')]

在这里采用的是皮尔逊方法,用欧几里得评价也是可以的





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kelisita

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值