高效构建.npz文件及Colab导入谷歌云端硬盘CNN图像数据集问题问询
问题根因
- 图像压缩格式与raw数组的大小差:你看到的192KB是JPG/PNG等压缩格式的存储大小,转成numpy数组时会被完全解压为raw像素数据,存储占用会膨胀几十到上百倍。比如1张1080P的3通道8位压缩图可能只有200KB,但解压为numpy数组后大小为192010803≈6MB,50张就会达到300MB,和你观测到的640MB基本吻合,更高位深、更高分辨率的图膨胀比例会更高。
- 存储方式未启用压缩:你用的
np.savez是无压缩存储,替换为np.savez_compressed可直接减少40%-70%的文件体积。 - 列表累加的内存冗余:用列表反复append numpy数组会产生额外的内存开销,远高于预分配固定形状的numpy数组。
- 未做预处理裁剪:如果你的CNN训练不需要用到原图分辨率,直接存原图的raw数组会浪费大量内存和存储空间。
最优导入方案
推荐按优先级选择以下方案:
方案1:直接解压数据集到Colab本地磁盘(操作最简单,性价比最高)
你的全量数据集压缩后总大小仅为20000*192KB≈3.8GB,完全可以直接打包为ZIP文件存在谷歌云盘,使用时执行以下操作:
- 挂载谷歌云盘后,将ZIP文件复制到
/content临时目录 - 执行
unzip命令解压到本地目录,Colab本地磁盘的读写速度是挂载云盘的几十倍,完全不存在小文件读取开销 - 训练时直接读取本地目录的图像即可,不需要全量加载到内存,配合PyTorch/TensorFlow的内置Dataset流式加载接口,内存占用可以控制在1GB以内
方案2:打包为训练框架专用的二进制格式(适合大批次长期训练)
如果需要更高的IO效率,可以将数据集打包为TFRecord(TensorFlow生态)或WebDataset(PyTorch生态)格式,这两种格式都是将多个小文件合并为二进制大文件,支持流式读取,不需要全量加载到内存,同时可以最大化减少云盘读取的IO开销。
方案3:分片存储压缩npz文件(如果必须使用numpy格式)
如果你的训练流程必须依赖numpy数组输入,可以按批次分片存储:
- 每处理1000-2000张图像就调用一次
np.savez_compressed存储为分片npz文件 - 训练时按需加载对应分片的npz,用完就释放内存,避免全量加载
代码优化建议
你现有代码可以做以下修改减少内存占用:
from PIL import Image import numpy as np # 先设定训练需要的图像分辨率 TARGET_SIZE = (224, 224) # 总样本数 SAMPLE_COUNT = len(x) # 预分配numpy数组,不要用列表append,节省内存 # uint8是图像默认位深,不需要用默认的float64,能减少7倍内存占用 X_array = np.zeros((SAMPLE_COUNT, TARGET_SIZE[0], TARGET_SIZE[1], 3), dtype=np.uint8) for idx in range(SAMPLE_COUNT): img = Image.open(x[idx]).resize(TARGET_SIZE) X_array[idx] = np.array(img, dtype=np.uint8) # 用savez_compressed替代savez np.savez_compressed('/content/drive/My Drive/dataset.npz', X=X_array)
注意:如果你的图像分辨率远大于训练需要的尺寸,一定要先resize再存入数组,能降低几十倍的内存占用。
内容的提问来源于stack exchange,提问作者junfanbl
相关产品推荐
相关产品推荐

