所用数据:grouplens.org/datasets/mo…
数据读取
"""
@author: LiShiHang
@software: PyCharm
@file: data_preprocessing.py
@time: 2019/4/3 21:12
@desc:
"""
import pandas as pd
import numpy as np
np.set_printoptions(threshold=np.inf)
def read_data(dir="../data/ml-1m/"):
"""
将data/ml-1m文件夹中的dat文件转化为csv
:param dir:
:return:
"""
####################################
f_users = pd.read_table(
dir + "users.dat",
engine="python",
sep="::",
names=[
'userID',
'Gender',
'Age',
'Occupation',
'Zip-code'])
f_users.to_csv("users.csv", index=False)
f_users.info()
###########################################
f_ratings = pd.read_table(dir + "ratings.dat", engine="python", sep="::",
names=['UserID', 'MovieID', 'Rating', 'Timestamp'])
f_ratings.to_csv("ratings.csv", index=False)
f_ratings.info()
################################################
f_movies = pd.read_table(dir + "movies.dat", engine="python", sep="::",
names=['MovieID', 'Title', 'Genres'])
f_movies.to_csv("movies.csv", index=False)
f_movies.info()
print("finish.")
if __name__ == '__main__':
read_data()
模型构建
"""
@author: LiShiHang
@software: PyCharm
@file: user_cf.py
@time: 2019/4/4 8:31
@desc:
"""
import math
import data_preprocessing
import pandas as pd
class UserCF():
def __init__(self, path_rating):
self.data_rating = pd.read_csv(path_rating)
def calc_user_sim(self, item1, item2):
"""
计算相似度
:param item1:
:param item2:
:return:
"""
cosine = len(set(item1) & set(item2)) /
math.sqrt(len(item1) * len(item2))
return cosine
def get_users_topN(self, source_user_id, N):
"""
得到N个相似用户
:param source_user_id:
:param topN:
:return: [[用户ID,相似度]]
"""
source_user_movies = self.data_rating[self.data_rating['UserID']
== source_user_id]["MovieID"] # 目标用户看过的电影ID
others_id = [
i for i in set(
self.data_rating['UserID']) if i != source_user_id] # 其他用户ID
others_movies = [
self.data_rating[self.data_rating['UserID'] == i]["MovieID"] for i in others_id] # [[其他用户看的电影ID] 其他用户ID]
sim_list = [
self.calc_user_sim(
source_user_movies,
movies) for movies in others_movies] # 根据目标用户和其他用户 看过的电影ID计算相似度
sim_list = sorted(zip(others_id, sim_list),
key=lambda x: x[1], reverse=True)
return sim_list[:N]
def get_candidate(self, source_user_id):
"""
得到候选电影清单
:param source_user_id:
:return:
"""
source_user_movies = set(
self.data_rating[self.data_rating['UserID'] == source_user_id]["MovieID"]) # 目标用户看过的电影ID
others_movies = set(
self.data_rating[self.data_rating['UserID'] != source_user_id]["MovieID"])
candidate_movies = others_movies - source_user_movies
return candidate_movies
def get_item_topN(self, top_n_users, candidate_movies, topN):
"""
得到推荐电影列表
:param top_n_users:
:param candidate_movies:
:param topN:
:return:
"""
top_n_users_data = [self.data_rating[self.data_rating['UserID'] == i]
for i, _ in top_n_users] # 相似用户数据
interest_item = []
for cm in candidate_movies: # 候选电影
tmp = []
for user_data in top_n_users_data: # 相似用户,[[用户ID,相似度]]
if cm in user_data["MovieID"].values:
tmp.append(user_data[user_data["MovieID"]
== cm]['Rating'].values[0] / 5.0)
else:
tmp.append(0)
interest = sum([top_n_users[i][1] * tmp[i]
for i in range(len(top_n_users))]) # 相似用户对每个候选电影的感兴趣度(评分)
interest_item.append((cm, interest))
interest_item = sorted(interest_item, key=lambda x: x[1], reverse=True)
return interest_item[:topN]
if __name__ == '__main__':
ucf = UserCF("ratings.csv")
ui = 1
top_n_users = ucf.get_users_topN(ui, 10)
candidate = ucf.get_candidate(ui)
top_n_movies = ucf.get_item_topN(top_n_users, candidate, 10)
print(top_n_movies) # 推荐的电影ID,推荐程度
# 显示电影名
movies = pd.read_csv("movies.csv")
# print("*" * 20)
# for i in ucf.data_rating[ucf.data_rating["UserID"]==ui]["MovieID"]: # 目标用户看过的电影名称
# print(*movies[movies["MovieID"]==i].values[0])
print("*" * 20)
for i, j in top_n_movies: # 推荐看的电影名称
print(*movies[movies["MovieID"] == i].values[0], j)
由于最近较忙,博客不做说明。
参考链接:
blog.appearancecsdn.net/sinat_33741…
github.compython是什么意思/lpty/recomm…
www.cnblogs.com/tbiiann/
github.com/apachecn/Re…