运行NumPy、Pandas代码报MemoryError如何解决?需提升内存上限吗?
问题复现
运行如下代码加载本地用户-电影矩阵npy文件与类型csv文件时触发内存错误:
import pandas as pd import numpy as np userMovie = np.load('userMovieMatrixAction.npy') numberUsers, numberGenreMovies = userMovie.shape genreFilename = 'Action.csv' genre = pd.read_csv(genreFilename)
完整报错信息:
MemoryError: Unable to allocate 3.63 GiB for an array with shape (487495360,) and data type float64
即系统无法为形状为(487495360,)、数据类型为float64的数组分配3.63 GiB内存
排查思路
不需要第一时间调大内存限制,3.63GiB的连续内存需求属于非常低的量级,报错基本是配置或存储方式不合理导致的,按以下顺序排查即可:
- 确认矩阵维度是否符合预期:先以内存映射只读模式加载文件(不会占内存),打印矩阵形状,检查是不是生成npy时误将二维矩阵展平成了一维、或者维度计算错误,导致加载的矩阵远大于设计大小。
- 确认Python版本位数:32位Python单进程默认内存上限只有2GiB,哪怕机器物理内存充足也会触发这类报错,执行
import platform; print(platform.architecture())即可确认,若显示32bit直接重装64位Python即可。 - 检查内存碎片问题:如果当前Python进程之前运行过其他大内存任务、残留未释放的大数组,会出现总剩余内存足够但找不到连续3.63GiB内存块的情况,重启Python进程/IDE内核后单独运行加载代码验证即可。
解决方案
按优先级从高到低尝试,绝大多数场景前两种方法就能解决问题:
- 降低数组存储精度
用户-电影矩阵一般是0/1交互标记、整数评分这类数据,完全不需要用float64存储,加载时指定更低精度的dtype即可直接把内存占用砍半甚至降到1/8:
# 0/1交互标记用bool类型,同大小矩阵仅需约465MiB内存 # 整数评分用int8/int16,浮点评分用float32(仅需约1.8GiB内存) userMovie = np.load('userMovieMatrixAction.npy').astype(np.float32)
- 内存映射模式加载
如果矩阵精度确实不能降,加载时增加mmap_mode='r'参数,不会把整个矩阵一次性读入内存,访问到对应片段时才会加载,支持所有numpy常规切片、计算操作:
userMovie = np.load('userMovieMatrixAction.npy', mmap_mode='r')
- 改用稀疏矩阵存储
用户-电影交互矩阵本身是极度稀疏的(绝大多数用户仅交互过极少量电影),存成稠密numpy数组本身就会浪费90%以上的空间。可以在生成矩阵的环节直接转成scipy稀疏矩阵(推荐csr格式)存储,加载后内存占用通常能降到原稠密矩阵的1%~10%。 - 最后再调整内存配置
如果以上方法都验证过还是报错,再考虑调整内存限制:Windows环境直接换64位Python即可;Linux环境可以执行ulimit -v unlimited临时放开进程虚拟内存限制,或者适当增加机器物理内存、调大系统虚拟内存/交换分区大小。
踩坑提醒
后续存储用户-物品类交互矩阵优先用稀疏格式,不要直接存稠密npy;加载大文件前先确认dtype和矩阵维度,不要默认用float64存所有类型数据,能避免绝大多数内存问题。
内容的提问来源于stack exchange,提问作者Jacob Kim
相关产品推荐
相关产品推荐

