Python实现协同过滤推荐
协同过滤推荐系统在我们的日常生活之中无处不在,例如,在电子商城购物,系统会根据用户的记录或者其他的信息来推荐相应的产品给客户,是一种智能的生活方式。之所以叫协同过滤,是因为在实现过滤推荐的时候是根据其他人的行为来做预测的,基于相似用户的喜好来实现用户的喜好预测。
简要介绍:
通过找到兴趣相投,或者有共同经验的群体,来向用户推荐感兴趣的信息。
举例,如何协同过滤,来对用户A进行电影推荐?
答:简要步骤如下
- 找到用户A(user_id_1)的兴趣爱好
- 找到与用户A(user_id_1)具有相同电影兴趣爱好的用户群体集合Set<user_id>
- 找到该群体喜欢的电影集合Set<movie_id>
- 将这些电影Set<Movie_id>推荐给用户A(user_id_1)
具体实施步骤如何?
答:简要步骤如下
(1)画一个大表格,横坐标是所有的movie_id,纵坐标所有的user_id,交叉处代表这个用户喜爱这部电影
如上表:
横坐标,假设有10w部电影,所以横坐标有10w个movie_id,数据来源自数据库
纵坐标,假设有100w个用户,所以纵坐标有100w个user_id,数据也来自数据库
交叉处,“1”代表用户喜爱这部电影,数据来自日志
画外音:什么是“喜欢”,需要人为定义,例如浏览过,查找过,点赞过,反正日志里有这些数据
(2)找到用户A(user_id_1)的兴趣爱好
如上表,可以看到,用户A喜欢电影{m1, m2, m3}
(3)找到与用户A(user_id_1)具有相同电影兴趣爱好的用户群体集合Set<user_id>
如上表,可以看到,喜欢{m1, m2, m3}的用户,除了u1,还有{u2, u3}
(4)找到该群体喜欢的电影集合Set<movie_id>
如上表,具备相同喜好的用户群里{u2, u3},还喜好的电影集合是{m4, m5}
画外音:“协同”就体现在这里。
(5)未来用户A(use_id_1)来访问网站时,要推荐电影{m4, m5}给ta。
具体实现步骤:
第一步:计算两者之间的相似度
通常会先把二维表格绘制在一个图中总,每个用户数据表示一个点。
度量相似度计算的方法:a.曼哈顿距离计算(计算迅速,节省时间)
b.欧氏距离计算(计算两个点之间的直线距离)
数据预处理:
去网站:https://grouplens.org/datasets/movielens/下载movieLen数据集
或者
ml-latest-small(1MB): http://files.grouplens.org/datasets/movielens/ml-latest-small.zip
ml-latest(234.2MB): http://files.grouplens.org/datasets/movielens/ml-latest.zip
解压读取movies.csv和ratings.csv文件
通过如下程序提取数据:
# -*- coding:utf-8 -*-
import pandas as pd
movies = pd.read_csv(r'E:\PycharmProjects\devTest\data\movies.csv')
ratings = pd.read_csv(r'E:\PycharmProjects\devTest\data\ratings.csv')
data = pd.merge(movies,ratings,on='MovieID')
data[['UserID','Rating','MovieID','Title']].sort_values('UserID').to_csv(r'E:\PycharmProjects\devTest\data\data.csv',index=False,header=None)
推荐代码:
# -*- coding:utf-8 -*-
from math import sqrt
data = {}
with open(r'E:\PycharmProjects\devTest\data\data.csv', 'r', encoding='UTF-8') as fi:
for line in fi:
item = line.strip().split(',')
if not item[0] in data.keys():
data[item[0]] = {item[3]: item[1]}
else:
data[item[0]][item[3]] = item[1]
# print(data)
##皮尔逊相关系数
def pearson_sim(user1, user2):
# 取出两位用户评论过的电影和评分
user1_data = data[user1]
user2_data = data[user2]
distance = 0
common = {}
# 找到两位用户都评论过的电影
for key in user1_data.keys():
if key in user2_data.keys():
common[key] = 1
if len(common) == 0:
return 0 # 如果没有共同评论过的电影,则返回0
n = len(common) # 共同电影数目
# print(n, common)
##计算评分和
sum1 = sum([float(user1_data[movie]) for movie in common])
sum2 = sum([float(user2_data[movie]) for movie in common])
##计算评分平方和
sum1Sq = sum([pow(float(user1_data[movie]), 2) for movie in common])
sum2Sq = sum([pow(float(user2_data[movie]), 2) for movie in common])
##计算乘积和
PSum = sum([float(user1_data[it]) * float(user2_data[it]) for it in common])
##计算相关系数
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
##计算某个用户与其他用户的相似度
def top10_simliar(UserID):
res = []
for userid in data.keys():
#排除与自己计算相似度
if not userid == UserID:
simliar = pearson_sim(UserID, userid)
res.append((userid, simliar))
res.sort(key=lambda val: val[1])
return res[:4]
RES = top10_simliar('1')
print(RES)
##根据用户推荐给其他人
def recommend(user):
top_sim_user = top10_simliar(user)[0][0]
items = data[top_sim_user]
recommendations = []
for item in items.keys():
if item not in data[user].keys():
recommendations.append((item,items[item]))
recommendations.sort(key=lambda val:val[1],reverse=True)
return recommendations[:10]
Recommendations = recommend('1')
print(Recommendations)
结果:
[('Nutty Professor II: The Klumps (2000)', '5'), ('"Patriot', '5'), ('"Silence of the Lambs', '5'), ('Titan A.E. (2000)', '5'), ('Almost Famous (2000)', '5'), ('Dinosaur (2000)', '5'), ('Mission: Impossible 2 (2000)', '5'), ('Star Wars: Episode I - The Phantom Menace (1999)', '5'), ('X-Men (2000)', '5'), ('Mission to Mars (2000)', '5')]
##其他计算相似距离的
##欧式距离
def Euclidean(user1,user2):
#取出两位用户评论过的电影和评分
user1_data=data[user1]
user2_data=data[user2]
distance = 0
#找到两位用户都评论过的电影,并计算欧式距离
for key in user1_data.keys():
if key in user2_data.keys():
#注意,distance越大表示两者越相似
distance += pow(float(user1_data[key])-float(user2_data[key]),2)
return 1/(1+sqrt(distance))#这里返回值越小,相似度越大
参考:https://blog.csdn.net/qq_25948717/article/details/81839463