h5py写入:如何有效地将数百万个.npy数组写入.hdf5文件



我必须将大图像的子样本存储为大小为(20,20,5)的.npy阵列。为了在训练分类模型时统一采样,我正在寻找一种有效的方法来存储近1000万个子样本,以实现这一点。

如果我将它们存储为完整的图像,那么训练期间的采样就不能代表分布。我有存储空间,但我会用完试图存储那么多"索引节点"的索引节点;"小";文件。h5py/写入hdf5文件是解决我的问题的自然方法,但是这个过程非常缓慢。运行一个程序一天半的时间不足以编写所有的子样本。我是h5py的新手,我想知道是不是写得太多了。

如果是这样的话,我不确定如何正确地进行分组,以避免不均匀采样的问题。每个图像具有不同数量的子样本(例如,一个图像可以是(20000,20,0,5),另一个可以是(32123,20,2,5)。

这是我用来将每个样本写入.hdf5:的代码

#define possible groups
groups=['training_samples','validation_samples','test_samples']
f = h5py.File('~/.../TrainingData_.hdf5', 'a', libver='latest')

在这一点上,我运行了一个子采样函数,它返回一个NumPy数组trarray,大小为(x,20,20,5)。

然后:

label = np.array([1])
for i in range(trarray.shape[0]):
group_choice = random.choices(groups, weights = [65, 15, 20])
subarr = trarray[i,:,:,:]
if group_choice[0] == 'training_samples':
training_samples.create_dataset('ID-{}'.format(indx), data=subarr)
training_labels.create_dataset('ID-{}'.format(indx), data=label)
indx += 1
elif group_choice[0] =='validation_samples':
validation_samples.create_dataset('ID-{}'.format(indx), data=subarr)
validation_labels.create_dataset('ID-{}'.format(indx), data=label)
indx += 1
else:
test_samples.create_dataset('ID-{}'.format(indx), data=subarr)
test_labels.create_dataset('ID-{}'.format(indx), data=label)
indx += 1

我能做些什么来改善这一点吗?/在使用h5py方面,我正在做的事情从根本上是错误的吗?

03-22-2021:请参阅下面提到的属性更新
这是一个有趣的用例。我对上一个问题的回答涉及这个问题(在我对这个问题的第一个回答中提到)。显然,在编写大量小对象时,开销要比实际的编写过程大。我很好奇,所以我创建了一个原型来探索不同的数据写入过程。

我的起始场景:

  1. 我创建了一个形状为(NN,20,20,5)的随机整数的NumPy数组
  2. 然后,我按照您的逻辑一次切片1行,并分配为培训、验证或测试样本
  3. 我把切片作为一个新的数据集写在适当的组中
  4. 我向组添加了属性,以引用每个数据集的切片号

主要发现:

  1. 将每个数组切片写入新数据集的时间在整个过程中保持相对恒定
  2. 但是 ,写入时间随着属性(NN)数量的增加而呈指数级增长。这在我最初的时候是不理解的邮递对于NN的小值(<2000),添加属性是相对较快

每1000个切片(不带属性和带属性)的增量写入时间表。(乘以NN/1000表示总时间。)

<12.7>/table>
切片
计数 (带属性)
1-000 2_000 0.34
5_000 0.33 11.7
1_000 20_000 0.35

块存储是为优化超大数据集的I/O而设计的。你的数据集是(1,20,0,5),对吧?如果是这样的话,那就太小了(在HDF5的世界里),所以我认为分块不会有帮助。

如果我理解的话,您将根据trarray.shape[0]的大小为每个子样本创建一个新的数据集(给出20000到32123个子样本——您的循环长度)。这是很多个人写作。

几年前,我做了一些I/O测试,发现h5py(和PyTables)的写入性能主要取决于I/O操作的数量,而不是正在写入的数据集的大小。看看这个答案:pytables的写入速度比h5py快得多。为什么?它比较了在使用不同大小的I/O数据块写入相同总量的数据时的I/O性能(对于h5py和PyTables)。第一个关键发现适用于此:写入所有数据的总时间是循环数的线性函数(对于PyTables和h5py)

提高运行时间的方法是减少I/O循环的数量。一些想法:

  • 有没有一种方法可以收集培训、验证和测试NumPy数组中的样本,然后一次写入所有数据集
  • 如果不是,您是否可以调整并创建3个空数据集(用于训练、验证、测试),然后将每个循环中的数据写入适当的数据集和索引?这可能会节省时间,因为您只是在写而不是在分配。(需要测试才能确定)

相关内容

  • 没有找到相关文章

最新更新