您的位置:首页 > 编程语言

集体智慧编程学习笔记--第二章

2016-12-28 22:50 274 查看
前言

什么是集体智慧?

答:为了创造新的想法,而将一群人的行为、偏好或思想组合在一起。

第二章:提供推荐

例子:影片推荐

一、名词:协作型过滤算法(collaborative filtering)
对一大群人进行搜索,从中找到与我们品味相近的一小群人。
二、搜集偏好
非常简单的方法是使用一个嵌套的字典
三、寻找品味相近的人

步骤:

1、将属性的值对应到数值。如喜欢:1不喜欢-1;已购买2,已浏览1未购买0;进行评分1,2,3,4
2、相似度评价值:用来确定与其他人的相似程度的度量。

常用两种度量:

①【欧几里得距离】:欧式空间上两点之间的距离的模值。 

python中pow(m,n) m的n次方 sqrt(m)m的平方根。

在使用aqrt时要注意,from math import sqrt

距离越小,偏好越接近。不过为了使得总是返回0-1之间的值,对距离进行处理1/(1+sqrt(pow(a-b,2)+pow(c-d),2))),+1是为了避免被零整除。

这样,值越接近1就表示越相似。

代码

from math import sqrt

#返回一个person1和person2之间的基于距离的相似度评价
def sim_distance(prefs,person1,person2):
#得到shared_items 的列表
si = {}
for item in prefs[person1]:
if item in prefs[person2]:
si[item] = 1

#如果两者之间没有共同之处,返回0
if len(si) == 0:
return 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+sum_of_squares)

但是,如果影评者对影片的总体评价对于平均水平偏离很大,那么可能用距离的度量就不是很好。使用皮尔森系数会给出比较好的结果

②【皮尔逊相关系数】:就是线性相关程度。是介于-1与1之间的数,1完全正相关,-1完全负相关。

想想如果一个人对不同电影打分总是比另一个人偏高,而二者的分值只差又始终保持一致。

反应在坐标系上,数据会拟合成一条直线。两个的分数的相关程度越高,说明两人仍有着相对近似的偏好。



代码

#返回p1、p2的pearson相关系数
def sim_pearson(prefs,p1,p2):
#得到双方都评价过的物品
si = {}
for item in prefs[p1]:
if item in prefs[p2]:
si[item] = 1

#得到双方都评价过的物品的个数
n = len(si)
if n == 0:
return 1

#对所有偏好求和

sum1 = sum([prefs[p1][it] for it in si])
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][it]*prefs[p2][it] for it in si])

#计算pearson相关系数
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


③【其他度量】:jaccard系数、曼哈顿街区距离。

3、为评论者打分

就是将所有评论者的相似度进行列表排序,顺序由高到低。

#进行相似度评分,找出最佳匹配
def topMatches(prefs,person,n=5,similarity=sim_pearson):
scores = [(similarity(prefs,person,other),other) for other in prefs if other!=person]

#对列表进行排序,评价值高者排在最前面
scores.sort(reverse=True)
return scores[0:n]

代码中n代表显示趣味相投的前n个人

4、推荐物品
有一个问题是,有时候有的人对一部影片进行评论但未对另一部影片进行评论。还有一个问题是有的人会对一部影片进行比较偏激的评论。

为了解决这种问题,设置权值。把相似度看成权值,这样与被推荐人趣味相近的人对推荐做的贡献就大。

加权后的评价值= 评价值*相似度系数 ,影片得分=加权评价值之和 / 相似度系数之和

#利用所有他人的评价值的加权平均,为某人提供建议
def getRecommendations(prefs,person,similarity=sim_pearson):
totals = {}#存放加权后评分之和
simSums = {}#存放参与评价的相似度之和
for other in prefs:
if other == person: continue
sim = similarity(prefs,person,other)

#忽略评价值为零或者小于零的情况
if sim<=0: continue
for item in prefs[other]:

#只对自己还没有看过的电影进行评价
totals.setdefault(item,0)#如果某人没有评价,则将他的评价设置为0,不影响求和
totals[item]+=prefs[other][item]*sim
#相似度之和
simSums.setdefault(item,0)
simSums[item]+=sim
#建立一个归一化的列表
ranking = [(total/simSums[item],item) for item,total in totals.items()]
#返回经过排序的列表,列表内元素是元组,默认对元组内第一个元素排序吗?看来是的

#如果把item放在前面,会按照首字母排序
ranking.sort(reverse=True)
return ranking


这样就得到了一个经过排名的影片列表,还可以据此推测出自己对每部影片的评价。

现在,就建立起一个推荐系统,适用于任何类型的商品推荐或者网络连接。

需要的就是建立一个有人员、物品、评价的字典。然后度量相似度。最后按照相似度排序进行推荐。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息