使用Python实现基于协同过滤的电影推荐系统
免费快速起号(微信号)
coolyzf
在当今数字化时代,个性化推荐系统已经广泛应用于各个领域,如电子商务、社交媒体和娱乐产业。其中,基于用户行为数据的协同过滤算法是构建推荐系统的核心技术之一。本文将介绍如何使用 Python 实现一个简单的基于用户的协同过滤(User-based Collaborative Filtering)电影推荐系统,并通过代码实例展示整个过程。
协同过滤简介
协同过滤是一种根据用户的历史行为来预测其可能感兴趣项目的推荐方法。它主要分为两种类型:基于用户的协同过滤和基于物品的协同过滤。前者通过寻找与目标用户具有相似偏好的其他用户来进行推荐;后者则是基于用户对特定物品的评价,找出与其喜好相似的其他物品进行推荐。本文重点讨论基于用户的协同过滤。
数据准备
为了实现这个推荐系统,我们需要一份包含用户评分信息的数据集。这里我们选择 MovieLens 数据集中的一个小型版本,该数据集包含了约 100,000 条来自 943 名用户对 1682 部电影的评分记录。首先,确保你已经安装了 pandas 库用于处理 CSV 文件,以及 scikit-learn 库用于计算余弦相似度。
pip install pandas scikit-learn
接下来加载并查看部分数据:
import pandas as pd# 加载数据ratings = pd.read_csv('ml-100k/u.data', sep='\t', names=['user_id', 'item_id', 'rating', 'timestamp'])# 显示前几行数据print(ratings.head())
输出结果如下所示:
user_id item_id rating timestamp0 1 1 5 8749657581 1 2 3 8768931712 1 3 4 8785429633 1 4 3 8785429804 1 5 3 878542996
此外,我们还需要加载电影标题信息,以便于后续显示推荐结果时能够提供更友好的用户体验。
movies = pd.read_csv('ml-100k/u.item', sep='|', encoding='latin-1', usecols=[0, 1], names=['item_id', 'title'])print(movies.head())
这将输出类似以下的内容:
item_id title0 1 Toy Story (1995)1 2 GoldenEye (1995)2 3 Four Rooms (1995)3 4 Get Shorty (1995)4 5 Copycat (1995)
构建用户-物品矩阵
为了方便计算用户之间的相似度,我们需要构建一个用户-物品评分矩阵。在这个矩阵中,每一行代表一个用户,每一列表示一部电影,矩阵元素则为对应的评分值。对于没有评分的情况,默认设为 NaN。
# 合并两个数据框,使得每条记录都关联上了电影名称data = pd.merge(ratings, movies, on='item_id')# 创建用户-物品评分矩阵user_item_matrix = data.pivot_table(index='user_id', columns='title', values='rating')# 查看矩阵结构print(user_item_matrix.shape) # 输出矩阵大小print(user_item_matrix.head()) # 输出矩阵头部内容
计算用户相似度
在得到用户-物品矩阵后,下一步就是计算所有用户之间的相似度。这里采用的是皮尔逊相关系数(Pearson Correlation Coefficient),它可以衡量两个变量间的线性关系强度。对于给定的任意两位用户 A 和 B,如果他们对多部电影都有过共同评分,则可以计算两者之间的皮尔逊相关系数作为相似度得分。
from sklearn.metrics.pairwise import pairwise_distances# 计算用户间相似度矩阵user_similarity = 1 - pairwise_distances(user_item_matrix.fillna(0), metric='cosine')np.fill_diagonal(user_similarity, 0) # 将对角线元素置零,因为自己跟自己的相似度没有意义# 转换为 DataFrame 方便查看similarity_df = pd.DataFrame(user_similarity, index=user_item_matrix.index, columns=user_item_matrix.index)# 打印前几个用户的相似度情况print(similarity_df.head())
上述代码片段实现了用户相似度矩阵的计算,并将其转换为易于理解的形式。接下来,我们可以利用这些相似度信息来为指定用户生成个性化的电影推荐列表。
推荐算法实现
当我们要为某个用户 U 提供推荐时,首先需要找到与他最相似的一组用户集合 S(例如取前 K 个最相似的用户)。然后统计 S 中每个成员未曾观看过的电影,并结合他们对该电影给出的平均评分来确定最终推荐名单。具体步骤如下:
根据用户相似度矩阵选出前 K 个最接近的邻居。对于每个邻居 N,获取其尚未被用户 U 观看过的电影列表 L_N 及对应评分 R_N。综合考虑所有邻居的意见,计算每部候选电影 M 的加权评分 W_M = sum(R_N * sim(U, N)) / sum(|sim(U, N)|),其中 sim 表示用户间的相似度。按照 W_M 的高低顺序排列候选电影,选取排名靠前的若干项作为推荐结果。以下是完整的 Python 代码实现:
def recommend_movies(user_id, similarity_df, user_item_matrix, top_k=10): """ 为指定用户推荐电影 参数: user_id: 目标用户的ID similarity_df: 用户相似度矩阵 user_item_matrix: 用户-物品评分矩阵 top_k: 返回的推荐数量 返回: 推荐电影列表及其预期评分 """ # 获取当前用户的相似用户 similar_users = similarity_df[user_id].sort_values(ascending=False)[:top_k].index # 初始化字典存储推荐电影及其权重评分 recommendations = {} for other_user in similar_users: # 找到该相似用户看过但目标用户没看过的电影 unseen_movies = set(user_item_matrix.columns[user_item_matrix.loc[other_user].notnull()]) \ - set(user_item_matrix.columns[user_item_matrix.loc[user_id].notnull()]) for movie in unseen_movies: if movie not in recommendations: recommendations[movie] = 0 # 累积加权评分 recommendations[movie] += user_item_matrix.loc[other_user, movie] * similarity_df.loc[user_id, other_user] # 计算实际权重评分 for movie in recommendations.keys(): recommendations[movie] /= abs(similarity_df.loc[user_id, similar_users]).sum() # 按照评分排序并返回结果 sorted_recommendations = sorted(recommendations.items(), key=lambda x: x[1], reverse=True) return sorted_recommendations[:top_k]# 测试函数效果recommended_list = recommend_movies(1, similarity_df, user_item_matrix)for movie, score in recommended_list: print(f"{movie}: {score:.2f}")
这段代码定义了一个名为 recommend_movies
的函数,它接受目标用户的 ID 以及其他必要的输入参数,按照上述逻辑执行推荐操作,并以列表形式返回推荐结果。最后通过调用此函数并传入具体的用户编号来检验系统的推荐性能。
总结
本文介绍了如何使用 Python 实现一个简单的基于用户的协同过滤电影推荐系统。从数据预处理到模型构建,再到最终的推荐生成,每一个环节都离不开编程技巧的支持。当然,在实际应用中还需要考虑更多因素,比如冷启动问题、稀疏性处理等,但这已经为我们打开了一扇通往个性化推荐世界的大门。希望读者们能够在实践中不断探索和完善自己的推荐系统,创造出更加智能且人性化的服务体验。