加载大量npy文件时np.load()内存占用过高的问题求助
加载大量npy文件时np.load()内存占用过高的问题求助
嘿,刚接触Python和机器学习就碰到这种内存炸锅的问题,太能理解你的崩溃了!我当初做类似项目的时候也踩过一模一样的坑,咱们来一步步拆解问题解决它~
问题根源
你用了mmap_mode='r'本来是想延迟加载、避免一次性读进内存,但最后那句features = np.asarray(features_list)直接把所有内存映射的数组都实打实读到RAM里了!咱们算笔账:每个npy文件是(298,32,32,3),如果是float32类型的话,每个文件大概占3.6MB,9221个加起来就是30多GB,远远超过你的16G内存,不爆才怪呢😅
实用解决方案
1. 用生成器/分批加载(最推荐)
核心思路是永远只在内存里保留一批训练数据,不要一次性加载所有文件。可以写个自定义生成器,训练的时候每次加载指定数量的文件:
import numpy as np from sklearn.model_selection import train_test_split # 先拆分索引,而不是直接加载所有数据 indices = np.arange(9221) train_idx, test_idx = train_test_split(indices, test_size=0.25, shuffle=True, random_state=42) # 自定义数据生成器 def data_generator(indices, df, batch_size=32): while True: # 每次循环打乱索引(保证训练随机性) np.random.shuffle(indices) # 按批次截取索引 for start in range(0, len(indices), batch_size): batch_indices = indices[start:start+batch_size] batch_features = [] batch_labels = [] for idx in batch_indices: # 仅加载当前批次的单个文件 frames_array = np.load(f'E:/padFrames/video_{idx}.npy') batch_features.append(frames_array) # 读取对应标签 labels = df.iloc[idx][categoryEmotions].values batch_labels.append(labels) # 返回当前批次的特征和标签数组 yield np.array(batch_features), np.array(batch_labels) # 创建训练/测试生成器 train_generator = data_generator(train_idx, df, batch_size=32) test_generator = data_generator(test_idx, df, batch_size=32)
之后训练模型时(比如用Keras),直接传入生成器即可:model.fit(train_generator, epochs=10, validation_data=test_generator),这样内存占用只会维持在一个批次的大小,完全不会爆。
2. 用大内存映射文件替代全量数组
如果你一定要用完整的numpy数组格式,可以创建一个超大的磁盘内存映射文件,把每个npy的数据写入对应位置,全程不占内存:
# 定义总数据的形状和类型 total_shape = (9221, 298, 32, 32, 3) dtype = np.float32 # 根据你的实际数据类型调整 # 创建磁盘上的内存映射文件 features_mmap = np.memmap('total_features.npy', dtype=dtype, mode='w+', shape=total_shape) # 循环写入每个npy的数据 for i in range(9221): frames_array = np.load(f'E:/padFrames/video_{i}.npy') features_mmap[i] = frames_array # 写入后释放当前数组的内存 del frames_array # 写完后可以重新以只读模式打开,后续使用和普通numpy数组一样,但数据存在磁盘上 features_mmap = np.memmap('total_features.npy', dtype=dtype, mode='r', shape=total_shape)
这种方式的好处是你可以像操作普通数组一样处理数据,但实际数据存在磁盘,不会占用大量RAM。
3. 预处理时压缩数据
如果你的模型允许,对每个视频帧做降维/压缩:
- 比如把32x32的帧下采样到16x16,直接减少75%的体积
- 对帧特征做PCA降维,保留主要信息的同时缩小维度
- 把数据类型从float32改成float16(如果模型支持),直接减半内存占用
额外提醒
以后处理大文件时,一定要避免把所有数据都塞进一个numpy数组里,分批处理或者用内存映射才是高效的方式~
备注:内容来源于stack exchange,提问作者zhenru
相关产品推荐
相关产品推荐

