基于用户的协同过滤(user-based collaborative filtering)
2016-12-11 21:41
495 查看
姓名:wagsyang
日期:星期四, 08. 十二月 2016 03:25下午
一个协作型过滤算法通常是对一大群人进行搜索,并从中找出与我们品味相近的一小群人。算法会对这些人所偏爱的其它内容进行考察,并将它们组合起来构造出一个经过排名的推荐列表。
欧几里德距离
欧几里德距离就是两个点的空间距离:
distance=∑i=j=0n(xi−xj)2‾‾‾‾‾‾‾‾‾‾‾‾‾⎷(1)
(1)式可以计算出距离值,偏好越相似的人,其距离就越短。我们现在需要一个函数,表示偏好越相近这个函数值就越大。我们可以这样:
sim_distance=1distance(2)
但是万一当distance=0,(2)就有问题了,我们修正一下,再加一项:
sim_distance=11+distance(3)
下面我们用pyhton程序表示两个人基于欧几里德距离的相似度:
皮尔逊相关度
对于欧几里德距离的相似度评价标准,如果某个人总是倾向于给出比本来与他有极高相似度的人高(低)的分数,比如:
person1={film1:2.1,film2:3.1 ,film:4.1}
person2={film1:2.9,film2:3.9 ,film:4.9}
计算出的欧几里德距离的值是很大的,是不相似的(较person3 =(2.1,2.6,3.6)),计算出这样的结果是因为person1内心的标准较person2更为严(zhuang)苛(bi),每个电影都比其他人给分低。但实际上这两人是品味相同的。
所以,直接计算欧式距离确实煎蛋,但有不足。如果我们用一条直线能够很好拟合这俩人的数据,就像上面的俩人,这肯定是极好的。因此,我们可以定义一种度量拟合程度的东西。这个东西就是皮尔逊相关度:
ρ=Cov(X,Y)D(X)‾‾‾‾‾√D(X)‾‾‾‾‾√=E{(X−E(X))(Y−E(Y))}D(X)‾‾‾‾‾√D(X)‾‾‾‾‾√=E(XY)−E(X)E(Y)D(X)‾‾‾‾‾√D(X)‾‾‾‾‾√(4)
ρ={>0 ,正相关<0,负相关
关于皮尔逊相关度的定义和推导请参考概率论与数理统计。
代码实现:
还有其它相似度的评价准则,比如:Jaccard系数,曼哈顿距离,这里不做介绍。
排名结果如下:
其中,以S.开头的值等于和某个人的相似度乘以他对某一电影的评分,这样,和我们品味相同的人它们的相似度高,自然占的比重就大,这也正是推荐的本意了。其实我们可以直接用Total的值来进行推荐了,但是有一些人没有看过某个电影,其评分为空,如果我们还按Total值来推荐,势必会有这种结果:某一个电影很多人都看过,其Total值非常非常大,而一个小众的电影,很少人看过(但实际它很符合你的口味),其Total值就非常小,这个Total值小的电影就不会被推荐给你,这是你我都不会同意的。因此,考虑到没被看过的电影的空值项,我们可以将Total值除以看过这部电影的人的相似度之和,即:
TotalSim.Sum=∑i=1n相似度i∗电影评分i∑相似度i=电影推荐评分(5)
代码实现如下:
我&我看过的电影 根据相似度度量准则> 臭味相投的人(座次:甲乙丙丁)电影按公式(5)排座次>它们看过的电影(排名:子丑寅卯)推荐哪个?>第一个错不了
日期:星期四, 08. 十二月 2016 03:25下午
简介
本文是集体智慧编程一书的学习笔记。
一个协作型过滤算法通常是对一大群人进行搜索,并从中找出与我们品味相近的一小群人。算法会对这些人所偏爱的其它内容进行考察,并将它们组合起来构造出一个经过排名的推荐列表。
收集偏好
我们要对不同的人和他对某个事物的偏好找一种表达方式,这里的研究对象是某人对它看过的电影的评价,评分由1到5。#基于用户的协同过滤 critics={\ 'Lisa Rose':{'lady in 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 water':3.0,'snakes on a plane':3.5,'just my luck':1.5,'superman returns':5.0,'you,me and dupree':3.5,'the night listener':3.0}, 'Michael Phillips':{'lady in 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,'superman returns':4.0,'the night listener':4.5}, 'Mick Lasalle':{'lady in water':3.0,'snakes on a plane':4.0,'just my luck':2.0,'superman returns':3.0,'you,me and dupree':2.0,'the night listener':3.0}, 'Jack Matthews':{'lady in water':3.0,'snakes on a plane':4.0,'superman returns':5.0,'you,me and dupree':3.5,'the night listener':3.0}, 'Toby':{'snakes on a plane':4.5,'superman returns':4.0,'you,me and dupree':1.0}}
寻找相近的用户
我们已经有了以上的数据,现在我们给你一个人H以及H所看过的电影的评分,怎样判断H与以上哪些人相似度最高?度量相似度的准则又是什么?这里我们介绍两种计算相似度的评价准则。欧几里德距离和皮尔逊相关度。欧几里德距离
欧几里德距离就是两个点的空间距离:
distance=∑i=j=0n(xi−xj)2‾‾‾‾‾‾‾‾‾‾‾‾‾⎷(1)
(1)式可以计算出距离值,偏好越相似的人,其距离就越短。我们现在需要一个函数,表示偏好越相近这个函数值就越大。我们可以这样:
sim_distance=1distance(2)
但是万一当distance=0,(2)就有问题了,我们修正一下,再加一项:
sim_distance=11+distance(3)
下面我们用pyhton程序表示两个人基于欧几里德距离的相似度:
from math import sqrt #欧几里德距离 def sim_distance(prefs,p1,p2): si={} # find common items for item in prefs[p1]: if item in prefs[p2]: si[item]=1 if len(si)==0: return 0 #cal the distance sum_of_sqr=sum([pow(prefs[p1][item]-prefs[p2][item],2) for item in si]) return 1/(1+sqrt(sum_of_sqr))
皮尔逊相关度
对于欧几里德距离的相似度评价标准,如果某个人总是倾向于给出比本来与他有极高相似度的人高(低)的分数,比如:
person1={film1:2.1,film2:3.1 ,film:4.1}
person2={film1:2.9,film2:3.9 ,film:4.9}
计算出的欧几里德距离的值是很大的,是不相似的(较person3 =(2.1,2.6,3.6)),计算出这样的结果是因为person1内心的标准较person2更为严(zhuang)苛(bi),每个电影都比其他人给分低。但实际上这两人是品味相同的。
所以,直接计算欧式距离确实煎蛋,但有不足。如果我们用一条直线能够很好拟合这俩人的数据,就像上面的俩人,这肯定是极好的。因此,我们可以定义一种度量拟合程度的东西。这个东西就是皮尔逊相关度:
ρ=Cov(X,Y)D(X)‾‾‾‾‾√D(X)‾‾‾‾‾√=E{(X−E(X))(Y−E(Y))}D(X)‾‾‾‾‾√D(X)‾‾‾‾‾√=E(XY)−E(X)E(Y)D(X)‾‾‾‾‾√D(X)‾‾‾‾‾√(4)
ρ={>0 ,正相关<0,负相关
关于皮尔逊相关度的定义和推导请参考概率论与数理统计。
代码实现:
#皮尔逊相关度 def sim_pearson(prefs,p1,p2): si={} for item in prefs[p1]: if item in prefs[p2]: si[item]=1 if len(si)==0: return 0 # 对所有偏好求和 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/len(si) den=sqrt((sum1sq-pow(sum1,2)/len(si))*(sum2sq-pow(sum2, 2)/len(si))) if den==0: return 0 return num/den
还有其它相似度的评价准则,比如:Jaccard系数,曼哈顿距离,这里不做介绍。
为相近的人打分
我们知道了如何计算两个人的相关度,下面我们将所有的人同自己作相关度计算,算出和自己相关度从高到低的排名。这里我们的样本比较少,就不做排名了,将全部人当作品味相近的那一小群人。排名结果如下:
评论者 | 相似度 | Night | S.xNight | Lady | S.xLady | Luck | S.xLuck |
---|---|---|---|---|---|---|---|
Rose | 0.99 | 3.0 | 2.97 | 2.5 | 2.48 | 3.0 | 2.97 |
Seymour | 0.38 | 3.0 | 1.14 | 3.0 | 1.14 | 1.5 | 0.57 |
Puig | 0.89 | 4.5 | 4.02 | 3.0 | 2.68 | ||
LaSalle | 0.92 | 3.0 | 2.77 | 3.0 | 2.77 | 2.0 | 1.85 |
Matthews | 0.66 | 3.0 | 1.99 | 3.0 | 1.99 | ||
Total | 12.89 | 8.38 | 8.07 | ||||
Sim.Sum | 3.84 | 2.95 | 3.18 | ||||
Total/Sim.Sum | 3.35 | 2.83 | 2.53 |
TotalSim.Sum=∑i=1n相似度i∗电影评分i∑相似度i=电影推荐评分(5)
代码实现如下:
#获得推荐 def get_recommendations(prefs,person,similarity): totals={} simsum={} for other in prefs: #dont compare to myself if other==person: continue sim=similarity(prefs,person,other) #loop out if there is no similarity if sim<=0 : continue for item in prefs[other]: #recommend a film I have never watched if item not in prefs[person]: #value*sim totals.setdefault(item,0) totals[item]+=prefs[other][item]*sim #sum of sim simsum.setdefault(item,0) simsum[item]+=sim #recommand list rankings=[(value/simsum[item],item) for item, value in totals.items()]#recommand list rankings.sort(reverse=True) return rankings
总结
基于用户的协同过滤推荐思路是这样的:我&我看过的电影 根据相似度度量准则> 臭味相投的人(座次:甲乙丙丁)电影按公式(5)排座次>它们看过的电影(排名:子丑寅卯)推荐哪个?>第一个错不了
相关文章推荐
- 分享asp.net 网站部署一段时候后无法响应经验
- 389. Find the Difference#2(Done)
- 学习内容
- 《高胜算交易策略》读书笔记
- 50. Pow(x, n)
- 神经网络与深度学习(3):Backpropagation算法
- Linux电源管理-Runtime PM
- 1080. Graduate Admission (30)
- 郝斌的C语言基础 165,166 枚举
- CentoOS更换yum源
- [SSH]如何敲一条线
- 走进阿里,从提高自身开始
- 【工具】让开发更高效-Firefox Developer Edition
- 《Android群英传》---读书笔记5
- 高性能Mysql主从架构的复制原理及配置详解
- 用HTML中的列表标签做一个导航栏吧
- NG《Machine_Learning_Yearning》笔记
- [RegEx]识别路径中是否有本地盘符
- 漫漫考研路之C语言的位运算
- 124. Binary Tree Maximum Path Sum