首页 > 解决方案 > 保存和加载大型 numpy 矩阵

问题描述

下面的代码是我如何保存 numpy 数组,保存后大约 27GB。有超过200K的图像数据,每个形状是(224,224,3)

hf = h5py.File('cropped data/features_train.h5', 'w')
for i,each in enumerate(features_train):
    hf.create_dataset(str(i), data=each)
hf.close()

这是我用来加载数据的方法,加载需要几个小时。

features_train = np.zeros(shape=(1,224,224,3))    
hf =  h5py.File('cropped data/features_train.h5', 'r') 
for key in hf.keys():
    x = hf.get(key)
    x = np.array(x)
    features_train = np.append(features_train,np.array([x]),axis=0) 
hf.close()

那么,对于这么大的数据量,有没有人有更好的解决方案呢?

标签: python-3.xnumpyh5py

解决方案


您没有告诉我们您的服务器有多少物理 RAM,但 27 GiB 听起来“很多”。考虑将您的运行分成几个较小的批次。

在 java 界有一个老锯子问“为什么这有二次运行时?”,即“为什么这么慢?”

String s = ""
for (int i = 0; i < 1e6, i++) {
    s += "x";
}

答案是接近尾声,在每次迭代中,我们读取大约一百万个字符,然后写入它们,然后附加一个字符。成本为 O(1e12)。标准解决方案是使用 StringBuilder,所以我们回到了预期的 O(1e6)。

在这里,我担心调用np.append()会将我们推入二次状态。

为了验证,将features_train赋值替换为 的简单评估np.array([x]),因此我们花一点时间计算,然后在每次迭代中立即丢弃该值。如果猜想是对的,那么运行时间会小很多。

要补救它,请避免调用.append(). np.zeros() 相反,使用(or )预分配 27 GiB,np.empty()然后在循环内将每个新读取的数组分配到其预分配槽的偏移量中。线性运行时将允许任务更快地完成。


推荐阅读