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

前言

什么是集体智慧?

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

第二章:提供推荐

例子:影片推荐

一、名词:协作型过滤算法(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
这样就得到了一个经过排名的影片列表,还可以据此推测出自己对每部影片的评价。

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

需要的就是建立一个有人员、物品、评价的字典。然后度量相似度。最后按照相似度排序进行推荐。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值