本文数据集和代码参考该博客:https://blog.csdn.net/qq_25948717/article/details/81839463
算法思想:
1. 找到与目标用户兴趣相似的用户集合,计算用户——电影矩阵的行向量之间的欧式距离(或者皮尔逊系数、余弦相似度)
2. 找到这个集合中用户喜欢的、并且目标用户没有听说过的物品推荐给目标用户
数据集: ml-latest-small(1MB): http://files.grouplens.org/datasets/movielens/ml-latest-small.zip
数据集中本次用到的两个文件为 movies.csv和ratings.csv
使用pandas中的merge函数将两个文件按照userID合并到一起,生成data.csv
import pandas as pd
# movies = pd.read_csv("F:\ml-latest-small\movies.csv")
# ratings = pd.read_csv("F:\ml-latest-small\\ratings.csv")##这里注意如果路径的中文件名开头是r,要转义。
# data = pd.merge(movies,ratings,on = 'movieId')#通过两数据框之间的movieId连接
# data[['userId','rating','movieId','title']].sort_values('userId').to_csv('F:\ml-latest-small\data.csv',index=False)
# left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
# 'A': ['A0', 'A1', 'A2', 'A3'],
# 'B': ['B0', 'B1', 'B2', 'B3']})
# right = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
# 'C': ['C0', 'C1', 'C2', 'C3'],
# 'D': ['D0', 'D1', 'D2', 'D3']})
# data = pd.merge(left,right,on='key')
# print(left)
# print(data)
file = open("F:\ml-latest-small\data.csv", 'r',encoding='UTF-8') # 记得读取文件时加‘r’, encoding='UTF-8'
##读取data.csv中每行中除了名字的数据
data = {} ##存放每位用户评论的电影和评分
# for line in file.readlines()[1:100]:
# # 注意这里不是readline()
# line = line.strip().split(',')
# # 如果字典中没有某位用户,则使用用户ID来创建这位用户
# if not line[0] in data.keys():
# data[line[0]] = {line[3]: line[1]}
# # 否则直接添加以该用户ID为key字典中
# else:
# data[line[0]][line[3]] = line[1]
for line in file.readlines()[1:22]:
line = line.strip().split(',')
# 如果字典中没有某位用户,则使用用户ID来创建这位用户
if not line[0] in data.keys():
data[line[0]] = {line[3]: line[1]}
# 否则直接添加以该用户ID为key字典中
else:
data[line[0]][line[3]] = line[1]
print(data)
"""计算任何两位用户之间的相似度,由于每位用户评论的电影不完全一样,所以兽先要找到两位用户共同评论过的电影
然后计算两者之间的欧式距离,最后算出两者之间的相似度
"""
from math import *
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)) # 这里返回值越小,相似度越大
# 计算某个用户与其他用户的相似度
def top10_simliar(userID):
res = []
for userid in data.keys():
# 排除与自己计算相似度
if not userid == userID:
simliar = Euclidean(userID, userid)
res.append((userid, simliar))
res.sort(key=lambda val: val[1])
print(res)
return res[:10]
# 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) # 按照评分排序
# 返回评分最高的10部电影
return recommendations[:10]
Recommendations = recommend('1')
print(Recommendations)