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

时间: 2024-11-10 admin IT培训

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

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] = 1if 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)#如果没有共同爱好 返回1if n==0 : return 1#对所有偏好求和sum1 = sum([prefs[p1][it] for it in si]) #对于求期望而言,他们概率不是1就是0sum2 = 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 0r = num/denreturn 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:continuesim = similarity(prefs,person,other)#忽略评价值为0和负数的情况if sim<=0 : continuefor item in prefs[other]:#对自己未观看的影片做评价if item not in prefs[person] or prefs[person][item]==0:#相似度*评价值total.setdefault(item,0)#setdefault方法:如果键不存在则设为默认值0total[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')]

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