此系列为《集体智慧编程-python算法应用》的读书笔记,大概地了解一下机器学习里的东西以及熟悉熟悉python。。。

此章节目的:
根据群体偏好来为人们提供推荐,有两个关键点:
1.自己的兴趣偏好的数据
2.群众(多数人)的兴趣爱好的数据
通过这两个关键点为自己推荐感兴趣的链接

(一)搜集偏好

寻找表达不同人及其偏好的方法,python中可以使用嵌套的字典实现。

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}}

该字典的key为不同人的名字,value为一个嵌套字典,存放了他们各自对不同电影的评价

(二)寻找相近的用户

(1)欧几里得距离评价
将经过人们一致评价的物品作为坐标轴,然后将参与评价的人绘制到图上,并考查他们彼此间的距离远近,偏好越相似的人,其距离就越近
注:
1.这里使用了列表生成式
2.对字典来说,可直接添加元素
3.返回为相似度的评价值,在0到1间,越大代表相似度越高

#返回一个有关person1和person2的基于距离的相似度评价
#欧几里得距离
def sim_distance(prefs,person1,person2):
    #用来判断是否存在相同的评价指标项
    #注意字典的可以直接追加数据
    si={}
    for item in prefs[person1]:
        if item in prefs[person2]:
            si[item]=1
    
    if len(item)==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+sqrt(sum_of_squares))

(2)皮尔逊相关度评价

皮尔逊相关度就是概率论里学的相关系数,直接看公式

python算法的五个特性 python算法的应用_相似度


python算法的五个特性 python算法的应用_python算法的五个特性_02


使用皮尔逊相关度分析可以修正“夸大分值”的情况(一个人总是倾向给出更高的分值),此时两者的品位应该是相似的,利用欧几里得距离评价会得到一个较低的评价。

注:

1.返回值在-1到1间,越接近1代表相似度越高

#皮尔逊相关度评价
#返回结果为两人的相关度指标
def sim_person(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][item] for item in si])
    sum2=sum([prefs[p2][item] for item in si])
    
    #求平方和
    sum1Sq=sum([pow(prefs[p1][item],2) for item in si])
    sum2Sq=sum([pow(prefs[p2][item],2) for item in si])
    
    #求乘积之和
    pSum=sum([prefs[p1][item]*prefs[p2][item] for item 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

(三)为评论者打分

此例我们通过上述方法,寻找与自己具有相似品位的影评者,并从高到低进行排序
注:
1.形参中有两个默认参数,n为返回的从高到低的人数,similarity代表使用的相关度评价的方法(皮尔逊or欧几里得)
2.返回的是一个list

#从反映偏好的字典中返回最为匹配者
#返回的个数和相似度函数均为可选参数
def topMatches(prefs,person,n=5,similarity=sim_person):
    scores=[(similarity(prefs,person,other),other) for other in prefs if other !=person]
    
    #对列表进行排序
    scores.sort()
    scores.reverse()
    return scores[0:n]

(四)推荐物品

我们可以根据与自己品位最相近的一个影评者的电影推荐来选择我们自己看的电影,但是,这样可能会存在一些问题,我们需要综合所有影评者的评价
算法很简单:某电影的推荐度=∑(相似度*评分)/(∑相似度)
注:
1.这里字典添加新元素时不能直接插入新元素,要用字典的setdefault(),调用该方法时传入key和default,若存在key的元素,则返回key对应的value;若不存在key的元素,则添加值为default的key。用来这里可以避免重复添加导致的覆盖。

#利用所有他人评价值的加权平均,为某人提供建议
#返回值为对person来说推荐的电影从高到低
def getRecommendations(prefs,person,similarity=sim_person):
    totals={}
    simSum={}
    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:
                #若不存在key则放入value,存在则返回value,避免重复建立覆盖
                #添加元素仅在第一个other处生效
                totals.setdefault(item,0)
                #相似度*评价值求和
                totals[item]+=prefs[other][item]*sim
                simSum.setdefault(item,0)
                simSum[item]+=sim
    
    #建立一个归一化的列表
    rankings=[(total/simSum[item],item) for item ,total in totals.items()]
    rankings.sort()
    rankings.reverse()
    return rankings

(五)匹配商品

上述的过程是寻找品位相似的评价者,而我们依旧可以通过上述的信息寻找相似的商品,只需要将人员与物品对换即可
注:
1.推荐的是最适合的评论者

#将电影与评价者反转,字典的key为电影名,value为各个评价者的评分组成的字典
def transformPrefs(prefs):
    result={}
    for person in prefs:
        for item in prefs[person]:
            result.setdefault(item,{})
        
            result[item][person]=prefs[person][item]
    return result

movie=transformPrefs(critics)
print(getRecommendations(movie,'Just My Luck'))