超内存字符串数组处理:Numpy Memmap调整尺寸后无法保存至磁盘的问题求助
解决Numpy Memmap resize后无法保存shape的问题
我来帮你解决这个numpy memmap的问题——你遇到的报错本质是因为.npy格式的内存映射文件没法动态更新shape信息,咱们一步步理清楚:
为什么你的操作会报错?
你用np.lib.format.open_memmap创建memmap时没有指定初始shape,得到的是一个无形状(shape=None)的内存映射对象。后续的resize操作只是在内存中修改了数组的视图,但不会更新磁盘上.npy文件的头信息——而.npy文件的头是固定写入的,创建后无法动态修改shape字段,所以再次打开时,numpy读不到有效的shape就抛出了ValueError: shape is not valid: None。
正确的Memmap使用方式(固定shape场景)
如果能提前预估处理结果的shape,创建memmap时直接指定shape、dtype等参数,后续修改内容后flush就能正常保存和读取:
# 直接创建指定shape和dtype的memmap文件 x = np.memmap('bla.npy', dtype='float64', mode='w+', shape=(10,)) # 修改内容 x[:] = np.arange(10) # 刷新到磁盘 x.flush() # 重新读取验证 y = np.memmap('bla.npy', dtype='float64', mode='r', shape=(10,)) print(y) # 输出: [0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
动态扩展数据集的替代方案(不确定最终shape)
如果处理后的结果大小不确定,numpy的memmap + .npy格式就不太适用了,推荐用HDF5格式(借助h5py库),它支持动态扩展数据集,完美适配超内存且大小不确定的场景:
import h5py import numpy as np # 创建HDF5文件并定义可扩展的数据集 with h5py.File('result.h5', 'w') as f: # maxshape=(None,)表示该维度可以无限扩展 dset = f.create_dataset('processed_data', shape=(0,), maxshape=(None,), dtype='float64') # 模拟分块处理数据并写入 for chunk in [np.arange(5), np.arange(5, 10)]: # 扩展数据集的长度 dset.resize(dset.shape[0] + chunk.shape[0], axis=0) # 将新块写入数据集末尾 dset[-chunk.shape[0]:] = chunk # 读取验证 with h5py.File('result.h5', 'r') as f: data = f['processed_data'][:] print(data) # 输出: [0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
额外建议
- 分块处理超内存数据时,尽量提前预估结果的大致规模,能减少动态调整带来的麻烦
- 如果必须用memmap,也可以先创建一个远大于预期的shape,后续只使用实际需要的部分,最后再裁剪(但会浪费一点磁盘空间)
内容的提问来源于stack exchange,提问作者Yorai Levi
相关产品推荐
相关产品推荐

