1.数据集的准备
movies = pd.read_csv('movies.csv')
ratings = pd.read_csv('ratings.csv')
#合并数据集
df = pd.merge(ratings, movies, on='movieId')
#转为用户评分矩阵
user_movie_ratings = df.pivot_table(index='userId', columns='title', values='rating')
#未评分补充为0
user_movie_ratings = user_movie_ratings.fillna(0)
2.计算用户的相似矩阵(基于用户)
user_similarity = cosine_similarity(user_movie_ratings, user_movie_ratings)
#使用余弦相似度
余弦相似度:余弦相似度是通过计算两个向量之间的夹角的余弦值来度量它们的相似性。
用户评分表的行为用户的评分向量,计算结果表示对电影打分的相似程度。
3.使用K 最近邻算法模型计算临近用户
knn = NearestNeighbors(n_neighbors=5, metric='cosine', algorithm='brute')
knn.fit(user_movie_ratings)
·NearestNeighbors 类来自于 scikit-learn 库,它实现了K最近邻算法。在这里,我们创建了一个KNN模型对象 knn。
·n_neighbors=5:这个参数指定了在搜索时要考虑的最近邻居的数量。在这里,我们将考虑每个用户的5个最相似的用户。
·metric='cosine':这个参数指定了用于度量距离的度量方式。在这里,我们使用余弦距离作为度量方式,这与我们之前计算用户相似度时使用的度量方式相一致。
·algorithm='brute':这个参数指定了用于搜索最近邻的算法。在这里,我们使用 'brute' 算法,它会对所有的样本进行暴力搜索来找到最近邻。虽然这种方法可能效率较低,但对于较小的数据集来说是可行的。
得到相似用户
distances, indices = knn.kneighbors([user_movie_ratings.iloc[user_index]])
#distances:这是一个数组,包含了指定用户与其最近邻用户之间的距离。
#indices:这是一个数组,包含了指定用户的最近邻用户的索引。
4. 推荐逻辑
# 获取与指定用户最相似的用户列表
similar_users = indices[0]
# 修正相似用户的数量
num_similar_users = len(similar_users)
if num_similar_users > 0:
#这一行代码通过提取目标用户与最相似用户之间的相似度,创建了一个一维数组。
user_similarity = user_similarity[user_index, similar_users]
#转为向量,方便计算
user_similarity = user_similarity.reshape(1, num_similar_users)
# 获取相似用户的评分信息
similar_users_ratings = user_movie_ratings.iloc[similar_users]
print(similar_users_ratings)
# 处理用户未评分的电影
unrated_movies = user_movie_ratings.iloc[user_index] [user_movie_ratings.iloc[user_index] == 0].index
# 初始化一个字典来存储电影的推荐分数
recommendations = {}
# 遍历相似用户列表
for user in range(num_similar_users):
# 获取相似用户评分过的电影
similar_rated_movies = similar_users_ratings.columns[similar_users_ratings.iloc[user] != 0]
# 获取相似用户未评分的电影
similar_unrated_movies = similar_users_ratings.iloc[user][unrated_movies]
# 计算推荐分数,只考虑相似用户已经评分和目标用户未评分过的电影
common_movies = list(set(similar_rated_movies) & set(unrated_movies))
if len(common_movies) > 0:
#当前相似用户对推荐用户的推荐分数,通过相似度加权得到。
recommendation_scores = similar_users_ratings.iloc[user][common_movies].values.dot(
user_similarity[0, user])
# 更新推荐分数字典,将每个相似用户的推荐分数相加
for i, movie in enumerate(common_movies):
if movie not in recommendations:
recommendations[movie] = 0
recommendations[movie] += recommendation_scores[i]
# 对推荐分数进行排序,得到排名前几的电影
sorted_recommendations = sorted(recommendations.items(), key=lambda x: x[1], reverse=True)
# 获取最大和最小的推荐分数
max_score = max(sorted_recommendations, key=lambda x: x[1])[1]
min_score = min(sorted_recommendations, key=lambda x: x[1])[1]
# 归一化推荐分数到0到5之间
normalized_recommendations = [(movie, (score - min_score) / (max_score - min_score) * 5) for movie, score in
sorted_recommendations]
# 输出归一化后的推荐列表
print("归一化后的推荐电影列表:")
for movie, score in normalized_recommendations[:10]:
print(f"{movie}: {score}")
线性归一化