我必须将大图像的子样本存储为大小为(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:请参阅下面提到的属性更新
这是一个有趣的用例。我对上一个问题的回答涉及这个问题(在我对这个问题的第一个回答中提到)。显然,在编写大量小对象时,开销要比实际的编写过程大。我很好奇,所以我创建了一个原型来探索不同的数据写入过程。
我的起始场景:
- 我创建了一个形状为(NN,20,20,5)的随机整数的NumPy数组
- 然后,我按照您的逻辑一次切片1行,并分配为培训、验证或测试样本
- 我把切片作为一个新的数据集写在适当的组中
- 我向组添加了属性,以引用每个数据集的切片号
主要发现:
- 将每个数组切片写入新数据集的时间在整个过程中保持相对恒定
- 但是 ,写入时间随着属性(NN)数量的增加而呈指数级增长。这在我最初的时候是不理解的邮递对于NN的小值(<2000),添加属性是相对较快
每1000个切片(不带属性和带属性)的增量写入时间表。(乘以NN/1000表示总时间。)
切片 | |||
---|---|---|---|
计数 | (带属性) | ||
1-000 | 2_000 | 0.34 | <12.7>|
5_000 | 0.33 | 11.7 | |
1_000 | 20_000 | 0.35 | /table>
块存储是为优化超大数据集的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个空数据集(用于训练、验证、测试),然后将每个循环中的数据写入适当的数据集和索引?这可能会节省时间,因为您只是在写而不是在分配。(需要测试才能确定)