在Google Colab中处理超出RAM容量的大规模数据集的解决方案咨询(基于2.25亿条图书评论用户-物品交互数据集的协同过滤推荐系统开发场景)
嘿,我太懂你碰到的这个头疼问题了——2.25亿条用户-物品交互数据直接用pd.read_json()加载,别说Colab的默认内存,就算是本地机器内存不够都得直接崩。下面给你几个实用的办法,一步步帮你搞定这个难题:
分块读取JSON数据,避免一次性占满内存
Pandas的read_json()其实自带分块加载的功能,不用硬把整个文件塞到内存里。你可以试试这样写:# 根据Colab的RAM调整分块大小,先试试100万条一块,不够再调小 chunk_size = 1_000_000 chunks = pd.read_json('/content/data/dataset.json', chunksize=chunk_size) # 遍历每个块,只保留协同过滤必需的列(比如用户ID、书籍ID、评分) processed_chunks = [] for idx, chunk in enumerate(chunks): # 过滤掉不需要的列,大幅减少内存占用 filtered_chunk = chunk[['user_id', 'book_id', 'rating']] processed_chunks.append(filtered_chunk) print(f"已处理第{idx+1}块,共{len(filtered_chunk)}条数据") # 如果合并后内存还够,就把块合并;不够的话后续就继续用分块方式处理 df = pd.concat(processed_chunks, ignore_index=True)每次只加载一小部分数据,处理完就释放内存,不会一下子把RAM榨干。
转成高效存储格式,后续加载更省心
JSON是文本格式,本来就占内存大,不如先把数据转成列式存储的Parquet格式——它压缩率高、加载速度快,还能大幅节省存储空间。结合分块读取来操作:chunk_size = 1_000_000 chunks = pd.read_json('/content/data/dataset.json', chunksize=chunk_size) # 逐块保存为Parquet文件 for idx, chunk in enumerate(chunks): filtered_chunk = chunk[['user_id', 'book_id', 'rating']] filtered_chunk.to_parquet(f'/content/data/processed_chunk_{idx}.parquet') print(f"已保存第{idx+1}块Parquet文件") # 后续加载所有Parquet文件,速度会快很多 import glob parquet_files = glob.glob('/content/data/processed_chunk_*.parquet') df = pd.concat([pd.read_parquet(file) for file in parquet_files], ignore_index=True)转成Parquet后,后续做协同过滤的预处理、模型训练都会顺畅不少。
用Dask替代Pandas,专门处理大数据
如果分块处理还是觉得麻烦,试试Dask吧——它是专门为大数据设计的库,API和Pandas几乎一模一样,但会自动把数据分成多个块,内存不够时就用磁盘缓存,完全不用担心溢出:import dask.dataframe as dd # Dask会自动分块读取JSON,不用手动设置chunksize ddf = dd.read_json('/content/data/dataset.json') # 只保留需要的列 ddf = ddf[['user_id', 'book_id', 'rating']] # 做预处理直接用Dask的方法,比如统计每个用户的评分数量 user_rating_count = ddf.groupby('user_id')['rating'].count().compute() # 训练协同过滤模型时,可以逐块喂数据,比如用Surprise库的话: for chunk in ddf.iterate_chunks(): train_data = chunk.to_pandas() # 这里写你的模型训练代码,比如Surprise的Dataset.load_from_df()Dask会自动帮你管理内存和磁盘,不用自己操心分块的细节。
升级Colab的RAM配置,临时扩容
你还可以试试申请Colab的高RAM模式:点击右上角的“RAM/磁盘”图标,选择“请求更多RAM”,如果你的账号有资格,会切换到高RAM实例(一般有25GB左右)。另外,切换到GPU/TPU实例也会搭配更大的内存——在“运行时”->“更改运行时类型”里选择GPU或TPU,说不定能直接加载整个数据集(不过2.25亿条还是建议结合前面的方法)。
最后提一句,针对协同过滤的场景,其实不需要把整个数据集都放在内存里:比如基于邻域的方法可以分块计算相似度,隐式反馈模型(比如Implicit库)支持分块训练,矩阵分解用随机梯度下降的话,也可以逐批处理数据,不用一次性加载全部数据。
备注:内容来源于stack exchange,提问作者ayushhh_13




