协作型过滤
协同过滤是利用集体智慧的一个典型方法。要理解什么是协同过滤 (Collaborative Filtering, 简称CF),首先想一个简单的问题,如果你现在想看个电影,但你不知道具体看哪部,你会怎么做?大部分的人会问问周围的朋友,看看最近有什么好看的电影推荐,而我们一般更倾向于从口味比较类似的朋友那里得到推荐。这就是协同过滤的核心思想。
协同过滤一般是在海量的用户中发掘出一小部分和你品位比较类似的,在协同过滤中,这些用户成为邻居,然后根据他们喜欢的其他东西组织成一个排序的目录推荐给你。
要实现协同过滤,需要以下几个步骤:
- 搜集偏好
- 寻找相近用户
- 推荐物品
搜集偏好
首先,我们要寻找一种表达不同人及其偏好的方法。这里我们用python的嵌套字典来实现。
在本章中所用的数据,是从国外的网站grouplens下载的u.data。该数据总共四列,共分为用户ID、电影ID、用户评分、时间。我们只需根据前三列,生成相应的用户偏好字典。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#生成用户偏好字典 def make_data(): result={} f = open('data/u.data', 'r') lines = f.readlines() for line in lines: #按行分割数据 (userId , itemId , score,time ) = line.strip().split("\t") #字典要提前定义 if not result.has_key( userId ): result[userId]={} #注意float,不然后续的运算存在类型问题 result[userId][itemId] = float(score) return result |
另外如果想在字典中显示展现电影名,方便分析,也可以根据u.item中电影数据,预先生成电影的数据集。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#将id替换为电影名 构造数据集 def loadMovieLens(path='data'): # Get movie titles movies={} for line in open(path+'/u.item'): (id,title)=line.split('|')[0:2] movies[id]=title # Load data prefs={} for line in open(path+'/u.data'): (user,movieid,rating,ts)=line.split('\t') prefs.setdefault(user,{}) prefs[user][movies[movieid]]=float(rating) return prefs |
根据上面两个函数中的一种,到此我们的用户数据集已经构造好了,由于数据量不是非常大,暂时放在内存中即可。
由于以上数据集比较抽象,不方便讲解,至此我们定义一个简单的数据集来讲解一些例子,一个简单的嵌套字典:
1 2 3 4 5 6 7 8 9 10 11 |
#用户:{电影名称:评分} 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} } |
寻找相近用户
收集完用户信息后,我们通过一些方法来确定两个用户之间品味的相似程度,计算他们的相似度评价值。有很多方法可以计算,我们在此介绍两套常见的方法:欧几里得距离和皮尔逊相关度。
欧几里得距离
欧几里得距离(euclidea nmetric)(也称欧式距离)是一个通常采用的距离定义,指在m维空间中两个点之间的真实距离,或者向量的自然长度(即该点到原点的距离)。在二维和三维空间中的欧氏距离就是两点之间的实际距离。
数学定义:
已知两点 A = (x_1,x_2,…,x_n)和B = (y_1,y_2,…,y_n),则两点间距离:
),首先想一个简单的问题,如果你现在想看个电影,但你不知道具体看哪部,你会怎么做?大部分的人会问问周围的朋友,看看最近有什么好看的电影推荐,而我们一般更倾向于从口味比较类似的朋友那里得到推荐。这就是协同过滤的核心思想。
协同过滤一般是在海量的用户中发掘出一小部分和你品位比较类似的,在协同过滤中,这些用户成为邻居,然后根据他们喜欢的其他东西组织成一个排序的目录推荐给你。
要实现协同过滤,需要以下几个步骤:
- 搜集偏好
- 寻找相近用户
- 推荐物品
搜集偏好
首先,我们要寻找一种表达不同人及其偏好的方法。这里我们用python的嵌套字典来实现。
在本章中所用的数据,是从国外的网站grouplens下载的u.data。该数据总共四列,共分为用户ID、电影ID、用户评分、时间。我们只需根据前三列,生成相应的用户偏好字典。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#生成用户偏好字典 def make_data(): result={} f = open('data/u.data', 'r') lines = f.readlines() for line in lines: #按行分割数据 (userId , itemId , score,time ) = line.strip().split("\t") #字典要提前定义 if not result.has_key( userId ): result[userId]={} #注意float,不然后续的运算存在类型问题 result[userId][itemId] = float(score) return result |
另外如果想在字典中显示展现电影名,方便分析,也可以根据u.item中电影数据,预先生成电影的数据集。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#将id替换为电影名 构造数据集 def loadMovieLens(path='data'): # Get movie titles movies={} for line in open(path+'/u.item'): (id,title)=line.split('|')[0:2] movies[id]=title # Load data prefs={} for line in open(path+'/u.data'): (user,movieid,rating,ts)=line.split('\t') prefs.setdefault(user,{}) prefs[user][movies[movieid]]=float(rating) return prefs |
根据上面两个函数中的一种,到此我们的用户数据集已经构造好了,由于数据量不是非常大,暂时放在内存中即可。
由于以上数据集比较抽象,不方便讲解,至此我们定义一个简单的数据集来讲解一些例子,一个简单的嵌套字典:
1 2 3 4 5 6 7 8 9 10 11 |
#用户:{电影名称:评分} 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} } |
寻找相近用户
收集完用户信息后,我们通过一些方法来确定两个用户之间品味的相似程度,计算他们的相似度评价值。有很多方法可以计算,我们在此介绍两套常见的方法:欧几里得距离和皮尔逊相关度。
欧几里得距离
欧几里得距离(euclidea nmetric)(也称欧式距离)是一个通常采用的距离定义,指在m维空间中两个点之间的真实距离,或者向量的自然长度(即该点到原点的距离)。在二维和三维空间中的欧氏距离就是两点之间的实际距离。
数学定义:
已知两点