生成基于内容推荐系统的用户-电影组合时遭遇内存错误
解决方案:避免内存溢出的MovieLens全量用户-电影评分处理方案
针对你的内存问题,核心原因是全量用户-电影组合的稠密数据量过大(比如MovieLens 10M数据集有72k用户+10k电影,全组合达720M行),直接生成或转换为稠密格式必然超出个人电脑内存。以下是无需扩容的可行方案:
方案1:始终使用稀疏矩阵操作(推荐)
稀疏矩阵仅存储非零值(已评分条目),内存占用极低,且多数机器学习库支持稀疏矩阵输入。注意先将非连续的用户/电影ID映射为连续索引,避免矩阵维度浪费:
import pandas as pd from scipy.sparse import csr_matrix # 映射用户/电影ID到连续整数索引(解决原始ID不连续导致的矩阵冗余) user_id_map = {uid: idx for idx, uid in enumerate(df['userId'].unique())} movie_id_map = {mid: idx for idx, mid in enumerate(df['movieId'].unique())} # 获取映射后的索引值 user_indices = df['userId'].map(user_id_map).values movie_indices = df['movieId'].map(movie_id_map).values # 创建稀疏评分矩阵(行=用户索引,列=电影索引,值=评分) sparse_rating_matrix = csr_matrix( (df['rating'].values, (user_indices, movie_indices)), shape=(len(user_id_map), len(movie_id_map)) ) # 后续基于内容的推荐操作直接使用该稀疏矩阵,无需转换为稠密格式
方案2:分用户按需生成评分数据
如果需要处理用户-未观看电影的组合,无需一次性生成全量数据,可按用户分批处理:
import pandas as pd # 预存每个用户的已评分电影及评分 user_rated_dict = df.groupby('userId').apply( lambda x: x.set_index('movieId')['rating'] ).to_dict() all_movies = df['movieId'].unique() # 逐个用户生成其全电影评分(已评分留原值,未评分设0) for user_id, rated_series in user_rated_dict.items(): # 初始化该用户所有电影评分为0 user_full_ratings = pd.Series(0, index=all_movies) # 更新已评分的电影值 user_full_ratings.loc[rated_series.index] = rated_series.values # 在此处对该用户的评分数据执行后续推荐逻辑 # process_recommendation(user_id, user_full_ratings)
方案3:用Categorical类型压缩长格式DataFrame内存
如果必须生成全量长格式(用户-电影-评分)DataFrame,可通过Categorical类型压缩ID列的内存占用:
import pandas as pd from itertools import product # 将用户/电影ID转为Categorical类型,用整数编码替代原始ID,减少内存占用 df['userId'] = pd.Categorical(df['userId']) df['movieId'] = pd.Categorical(df['movieId']) all_users = df['userId'].cat.categories all_movies = df['movieId'].cat.categories # 生成全组合并合并评分 all_combinations = product(all_users, all_movies) result_df = pd.DataFrame(all_combinations, columns=['userId', 'movieId']) result_df = pd.merge(result_df, df, on=['userId', 'movieId'], how='left') result_df['rating'] = result_df['rating'].fillna(0) # 如需恢复原始ID类型,可最后转换 result_df['userId'] = result_df['userId'].astype(int) result_df['movieId'] = result_df['movieId'].astype(int)
关键提示
基于内容的推荐系统不需要全量稠密的用户-电影评分矩阵,常规流程是:
- 提取电影内容特征(如类型、导演、演员等)
- 基于用户已评分电影生成用户偏好特征(如特征加权平均)
- 分用户计算其偏好与未观看电影的特征相似度,排序得到推荐
全程可分批处理,完全规避全量稠密数据的内存压力。
内容的提问来源于stack exchange,提问作者Mohamed Amine
相关产品推荐
相关产品推荐

