1.初识协同过滤 (CF)
要理解什么是协同过滤 (Collaborative Filtering, 简称 CF),首先想一个简单的问题,如果你现在想看个电影,但你不知道具体看哪部,你会怎么做?大部分的人会问问周围的朋友,看看最近有什么好看的电影推荐,而我们一般更倾向于从口味比较类似的朋友那里得到推荐。这就是协同过滤的核心思想。
协同过滤一般是在海量的用户中发掘出一小部分和你品位比较类似的,在协同过滤中,这些用户成为邻居,然后根据他们喜欢的其他东西组织成一个排序的目录作为推荐给你。当然其中有一个核心的问题:
- 如何确定一个用户是不是和你有相似的品位?
- 如何将邻居们的喜好组织成一个排序的目录?
协同过滤相对于集体智慧而言,它从一定程度上保留了个体的特征,就是你的品位偏好,所以它更多可以作为个性化推荐的算法思想。可以想象,这种推荐策略在 Web 2.0 的长尾中是很重要的,将大众流行的东西推荐给长尾中的人怎么可能得到好的效果,这也回到推荐系统的一个核心问题:了解你的用户,然后才能给出更好的推荐。
2.协同过滤算法
协同过滤算法一般需要以下几个步骤
- 收集用户偏好
- 找到相似的用户或物品
- 计算推荐
协同过滤算法主要有基于用户的协同过滤和基于物品的协同过滤。
user_based_CF就是把与你有相同爱好的用户所喜欢的物品(并且你还没有评过分)推荐给你
item_based_CF则与之相反,把和你之前喜欢的物品近似的物品推荐给你
3.实战协同过滤算法
任务介绍:
数据集:MovieLens100k 的 u1数据
算法:item_based_CF
评价指标:RMSE
完整代码:
# -*- coding: utf-8 -*-
from __future__ import division #精准除法
from __future__ import print_function #引入python 3.x print函数
import numpy as np
def load_data(path):
data = []
with open(name=path,mode='r') as file:
for line in file:
(user_id,moive_id,rating,time_stamp) = line.strip().split('\t')
data.append([user_id,moive_id,rating])
data = np.array(data).astype(np.uint16)
return data
class item_based_cf:
def __init__(self,train_data):
self.train_data = np.array(train_data)
print("the input data size is ",self.train_data.shape)
self.movie_user = {}
self.user_movie = {}
self.avg = np.mean(self.train_data[:,2])
for i in range(self.train_data.shape[0]):
user_id = self.train_data[i][0]
moive_id = self.train_data[i][1]
rating = self.train_data[i][2]
self.movie_user.setdefault(moive_id,{})
self.user_movie.setdefault(user_id,{})
self.movie_user[moive_id][user_id]=rating
self.user_movie[user_id][moive_id]=rating
self.similarity={}
def sim_cal(self,m1,m2):
self.similarity.setdefault(m1,{})
self.similarity[m1][m2] = -1 #等价于self.similarity[m1].setdefault(m2,-1) 两层字典{m1:{m2:-1}}
self.similarity.setdefault(m2,{})
self.similarity[m2][m1] = -1
self.movie_user.setdefault(m1,{})
self.movie_user.setdefault(m2,{})
if self.similarity[m1][m2] != -1:
return self.similarity[m1][m2]
#都评价过m1,m2的用户
su = {}
for user in self.movie_user[m1]:
if user in self.movie_user[m2]:
su[user]=1
n = len(su)
if (n == 0):
self.similarity[m1][m2] = 1
self.similarity[m2][m1] = 1
return 1
s1 = np.array([self.movie_user[m1][u] for u in su]) #返回一个评分集合
s2 = np.array([self.movie_user[m2][u] for u in su])
#求和
sum1 = np.sum(s1)
sum2 = np.sum(s2)
#求平方和
sum1Sq = np.sum(s1**2)
sum2Sq = np.sum(s2**2)
#计算皮尔逊相关系数
pSum = np.sum(s1*s2)
num = pSum-(sum1*sum2/n)
den = np.sqrt((sum1Sq-sum1**2/n)*(sum2Sq-sum2**2/n))
if den==0:
self.similarity[m1][m2]=0
self.similarity[m2][m1]=0
return 0
self.similarity[m1][m2] = num/den
self.similarity[m2][m1] = num/den
return num/den
def predict(self,user_id,moive_id):
sim_accumulate=0.0
rat_acc=0.0
for item in self.user_movie[user_id]:
sim=self.sim_cal(item,moive_id)
if sim<0:
continue
rat_acc += sim*self.user_movie[user_id][item]
sim_accumulate += sim
#no same user rated,return average rates of the data
if sim_accumulate == 0:
return self.avg
return rat_acc/sim_accumulate
def test(self,test_X):
test_X = np.array(test_X)
output = []
sums = 0
print("the test data size is ",test_X.shape)
for i in range(test_X.shape[0]):
pre = self.predict(test_X[i][0],test_X[i][1])
output.append(pre)
sums += (pre-test_X[i][2])**2
rmse = np.sqrt(sums/test_X.shape[0])
print("the rmse on test data is ",rmse)
return output
train_data = load_data('./ml-100k/u1.base')
test_data = load_data('./ml-100k/u1.test')
ibc = item_based_cf(train_data)
pred = ibc.test(test_data)
代码运行结果:
4.基于mapreduce的item_based_CF算法
流程图
详细介绍
1.数据集字段:
- User_id: 用户ID
- Item_id: 物品ID
- preference:用户对该物品的评分
2.算法的思想:
(1)建立物品的同现矩阵A,即统计两两物品同时出现的次数
数据格式:Item_id1:Item_id2 次数
(2)建立用户对物品的评分矩阵B,即每一个用户对某一物品的评分
数据格式:Item_id user_id:preference
(3)推荐结果=物品的同现矩阵A * 用户对物品的评分矩阵B
数据格式:user_id item_id,推荐分值
(4)过滤用户已评分的物品项
(5)对推荐结果按推荐分值从高到低排序
3.步骤详解:
原始数据
1,101,5.0
1,102,3.0
1,103,2.5
2,101,2.0
2,102,2.5
2,103,5.0
2,104,2.0
3,101,2.0
3,104,4.0
3,105,4.5
3,107,5.0
4,101,5.0
4,103,3.0
4,104,4.5
4,106,4.0
5,101,4.0
5,102,3.0
5,103,2.0
5,104,4.0
5,105,3.5
5,106,4.0
6,102,4.0
6,103,2.0
6,105,3.5
6,107,4.0
Hadoop MapReduce程序分为四步:
第一步: 读取原始数据,按用户ID分组,输出文件数据格式为
1 103:2.5,101:5.0,102:3.0
2 101:2.0,102:2.5,103:5.0,104:2.0
3 107:5.0,101:2.0,104:4.0,105:4.5
4 103:3.0,106:4.0,104:4.5,101:5.0
5 101:4.0,102:3.0,103:2.0,104:4.0,105:3.5,106:4.0
6 102:4.0,103:2.0,105:3.5,107:4.0
第二步:统计两两物品同时出现的次数,输出文件数据格式为
101:101 5
101:102 3
101:103 4
101:104 4
101:105 2
101:106 2
101:107 1
102:101 3
102:102 4
102:103 4
102:104 2
102:105 2
102:106 1
102:107 1
103:101 4
103:102 4
103:103 5
103:104 3
103:105 2
103:106 2
103:107 1
104:101 4
104:102 2
104:103 3
104:104 4
104:105 2
104:106 2
104:107 1
105:101 2
105:102 2
105:103 2
105:104 2
105:105 3
105:106 1
105:107 2
106:101 2
106:102 1
106:103 2
106:104 2
106:105 1
106:106 2
107:101 1
107:102 1
107:103 1
107:104 1
107:105 2
107:107 2
第三步:生成用户评分矩阵和物品同现矩阵
第一个mapper结果为用户评分矩阵,结果如下:
101 2:2.0
101 5:4.0
101 4:5.0
101 3:2.0
101 1:5.0
102 2:2.5
102 1:3.0
102 6:4.0
102 5:3.0
103 6:2.0
103 5:2.0
103 1:2.5
103 4:3.0
103 2:5.0
104 5:4.0
104 2:2.0
104 3:4.0
104 4:4.5
105 5:3.5
105 3:4.5
105 6:3.5
106 4:4.0
106 5:4.0
107 3:5.0
107 6:4.0
第二个mapper生成物品同现矩阵,结果如下:
101:101 5
101:102 3
101:103 4
101:104 4
101:105 2
101:106 2
101:107 1
102:101 3
102:102 4
102:103 4
102:104 2
102:105 2
102:106 1
102:107 1
103:101 4
103:102 4
103:103 5
103:104 3
103:105 2
103:106 2
103:107 1
104:101 4
104:102 2
104:103 3
104:104 4
104:105 2
104:106 2
104:107 1
105:101 2
105:102 2
105:103 2
105:104 2
105:105 3
105:106 1
105:107 2
106:101 2
106:102 1
106:103 2
106:104 2
106:105 1
106:106 2
107:101 1
107:102 1
107:103 1
107:104 1
107:105 2
107:107 2
第四步:做矩阵乘法,推荐结果=物品的同现矩阵A * 用户对物品的评分矩阵B。结果如下:
引用《Mahout In Aaction》中示例帮助理解矩阵计算
即推荐给用户ID为3的用户的结果是(103,24.5),(102,18.5),(106,16.5)
1 107,10.5
1 106,18.0
1 105,21.0
1 104,33.5
1 103,44.5
1 102,37.0
1 101,44.0
2 107,11.5
2 106,20.5
2 105,23.0
2 104,36.0
2 103,49.0
2 102,40.0
2 101,45.5
3 107,25.0
3 106,16.5
3 105,35.5
3 104,38.0
3 103,34.0
3 102,28.0
3 101,40.0
4 107,12.5
4 106,33.0
4 105,29.0
4 104,55.0
4 103,56.5
4 102,40.0
4 101,63.0
5 107,20.0
5 106,34.5
5 105,40.5
5 104,59.0
5 103,65.0
5 102,51.0
5 101,68.0
6 107,21.0
6 106,11.5
6 105,30.5
6 104,25.0
6 103,37.0
6 102,35.0
6 101,31.0
更多资源推荐
(1)探索推荐引擎内部的秘密
(2)TOP 10 开源的推荐系统简介