如何将42000个numpy数组列表保存到磁盘?解决内存不足问题
嘿,我之前也碰到过这种超大numpy列表存不下的头疼问题,给你几个亲测有效的解决方案,肯定能帮你搞定内存瓶颈!
方案1:用h5py增量写入(最推荐,内存友好)
你之前以为HDF5不能存列表其实是个小误解!h5py完全支持逐个写入数组,不需要一次性把所有数据塞进内存,完美适配你的16GB内存情况。
实现步骤:
- 导入h5py库(如果没装先跑
pip install h5py) - 打开一个HDF5文件,用写模式
- 循环遍历你的数组列表,给每个数组分配一个带编号的数据集名称(比如
arr_00000) - 逐个写入数组,每次只占用单个数组的内存,写完就释放
import h5py import numpy as np # 假设你的数组列表叫arr_list arr_list = [np.random.rand(240,240) for _ in range(42000)] # 替换成你的真实数据 with h5py.File('large_data.h5', 'w') as f: for idx, arr in enumerate(arr_list): # 用格式化字符串命名,保证索引有序,方便后续读取 f.create_dataset(f'arr_{idx:05d}', data=arr, compression='gzip')
读取方式(按需加载,不占内存):
with h5py.File('large_data.h5', 'r') as f: # 读取第100个数组(索引从0开始) arr_100 = f['arr_00100'][()] # 或者遍历所有数组处理 for key in sorted(f.keys()): arr = f[key][()] # 这里写你的处理逻辑
方案2:用Zarr分块存储(更灵活的大数据格式)
Zarr是专门为超大数组设计的格式,支持分块压缩,内存占用极低,而且用法几乎和numpy一模一样,非常适合深度学习场景。
实现步骤:
- 安装zarr:
pip install zarr - 创建一个zarr数组,设置好总形状和分块大小(比如每个分块对应1个240x240的数组)
- 逐个写入数组,内存只占用单个数组的空间
import zarr import numpy as np arr_list = [np.random.rand(240,240) for _ in range(42000)] # 创建zarr数组,总形状(42000,240,240),分块设为(1,240,240),启用gzip压缩 zarr_arr = zarr.open('large_data.zarr', mode='w', shape=(42000,240,240), chunks=(1,240,240), compression='gzip') # 逐个写入,完全不占额外内存 for idx, arr in enumerate(arr_list): zarr_arr[idx] = arr
读取方式:
zarr_arr = zarr.open('large_data.zarr', mode='r') # 直接索引读取,比如第500个数组 arr_500 = zarr_arr[500] # 甚至可以像numpy一样切片:zarr_arr[100:200] 读取第100-199个数组
方案3:分拆成多个压缩NPZ文件(简单粗暴易上手)
如果不想学新库,这个方法最直接——把大列表拆成小批次,每个批次存一个npz文件,单个文件内存压力小,不会触发内存错误。比如每1000个数组存一个文件:
import numpy as np arr_list = [np.random.rand(240,240) for _ in range(42000)] batch_size = 1000 # 可以根据你的内存情况调整批次大小 for i in range(0, len(arr_list), batch_size): batch = arr_list[i:i+batch_size] # 把批次里的数组存成字典 batch_dict = {f'arr_{j}': arr for j, arr in enumerate(batch)} # 压缩保存 np.savez_compressed(f'data_batch_{i//batch_size:02d}.npz', **batch_dict)
读取方式:
# 加载第3个批次(索引从0开始) batch_data = np.load('data_batch_02.npz') # 获取批次里的第50个数组 arr = batch_data['arr_50']
为什么之前的方法会失败?
pickle和numpy.savez_compressed:这俩都需要把所有数据一次性加载到内存,再压缩写入。你的42000个240x240数组(如果是float32)总内存约9.2GB,加上压缩过程的临时内存,很容易超过16GB触发内存错误。- 单个大numpy数组:虽然总大小2.3GB(应该是用了uint8类型?),但处理时频繁切片、复制会产生大量临时内存,导致电脑崩溃。
总结下,h5py和zarr是最优解,支持增量写入/按需读取,完全不占额外内存;分拆NPZ是快速实现的备选方案,适合不想折腾新库的情况。
内容的提问来源于stack exchange,提问作者zucchinifries
相关产品推荐
相关产品推荐

