2021 年 3 月 22 日:请参阅下面提到的属性更新。
这是一个有趣的用例。我对上一个问题的回答涉及到这个问题(在我对这个问题的第一个回答中引用)。显然,写入大量小对象时的开销大于实际的写入过程。我很好奇,所以我创建了一个原型来探索写入数据的不同过程。
我的起始场景:
- 我创建了一个形状为 (NN,20,20,5) 的随机整数的 NumPy 数组。
- 然后我按照您的逻辑一次切片 1 行并分配为
训练、验证或测试样本。
- 我将切片作为新数据集写入适当的组中。
- 我向组中添加了属性以引用每个数据集的切片 #。
主要发现:
- 将每个数组切片写入新数据集的时间在整个过程中保持相对恒定。
-
然而,随着属性 (NN) 数量的增加,写入时间呈指数增长。这在我最初的时候是不理解的
邮政。对于较小的 NN (
每 1,000 个切片的增量写入时间表(不带和带属性)。 (总时间乘以 NN/1000。)
| Slice |
Time (sec) |
Time (sec) |
| Count |
(w/out attrs) |
(with attrs) |
| 1_000 |
0.34 |
2.4 |
| 2_000 |
0.34 |
12.7 |
| 5_000 |
0.33 |
111.7 |
| 10_000 |
0.34 |
1783.3 |
| 20_000 |
0.35 |
n/a |
显然使用属性不是保存切片索引的有效方法。相反,我捕获了数据集名称的一部分。这显示在下面的“原始”代码中。包含添加属性的代码,以备不时之需。
我创建了一个新流程,首先进行所有切片,然后分 3 步写入所有数据(训练、验证和测试样本各 1 步)。由于您无法从数据集名称中获取切片索引,因此我测试了 2 种不同的方法来保存该数据:1)作为每个“样本”数据集的第二个“索引”数据集和 2)作为组属性。两种方法都明显更快。将索引作为索引数据集编写对性能几乎没有影响。将它们写为属性要慢得多。数据:
所有切片的总写入时间表(不带和带属性)。
| Slice |
Time (secs) |
Time (secs) |
Time (secs) |
| Count |
(no indices) |
(index dataset) |
(with attrs) |
| 10_000 |
0.43 |
0.57 |
141.05 |
| 20_000 |
1.17 |
1.27 |
n/a |
这种方法看起来是一种很有前途的方法,可以在合理的时间内将数据切片并写入 HDF5。您将不得不处理索引符号。
启动场景代码:
#define possible groups
groups=['training','validation','test']
# one image may be (20000,20,20,5)
trarray = np.random.randint(1,255, (20_000,20,20,5) )
label = np.array([1])
with h5py.File('TrainingData_orig.hdf5', 'w') as h5f :
#At this point I run a sub-sampling function that returns a NumPy array,
#trarray, of size (x,20,20,5).
for group in groups:
h5f.create_group(group+'_samples')
h5f.create_group(group+'_labels')
time0 = timeit.default_timer()
for i in range(trarray.shape[0]):
group_choice = random.choices(groups, weights = [65, 15, 20])
h5f[group_choice[0]+'_samples'].create_dataset(f'ID-{i:04}', data=trarray[i,:,:,:])
#h5f[group_choice[0]+'_labels'].create_dataset(f'ID-{i:04}', data=label)
#h5f[group_choice[0]+'_samples'].attrs[f'ID-{i:04}'] = label
if (i+1) % 1000 == 0:
exe_time = timeit.default_timer() - time0
print(f'incremental time to write {i+1} datasets = {exe_time:.2f} secs')
time0 = timeit.default_timer()
测试场景代码:
注意:将属性写入组的调用已被注释掉。
#define possible groups
groups=['training_samples','validation_samples','test_samples']
# one image may be (20000,20,20,5)
trarray = np.random.randint(1,255, (20_000,20,20,5) )
training = np.empty(trarray.shape,dtype=np.int32)
validation = np.empty(trarray.shape,dtype=np.int32)
test = np.empty(trarray.shape,dtype=np.int32)
indx1, indx2, indx3 = 0, 0, 0
training_list = []
validation_list = []
test_list = []
training_idx = np.empty( (trarray.shape[0],2) ,dtype=np.int32)
validation_idx = np.empty( (trarray.shape[0],2) ,dtype=np.int32)
test_idx = np.empty( (trarray.shape[0],2) ,dtype=np.int32)
start = timeit.default_timer()
#At this point I run a sub-sampling function that returns a NumPy array,
#trarray, of size (x,20,20,5).
for i in range(trarray.shape[0]):
group_choice = random.choices(groups, weights = [65, 15, 20])
if group_choice[0] == 'training_samples':
training[indx1,:,:,:] = data=trarray[i,:,:,:]
training_list.append( (f'ID-{indx1:04}', i) )
training_idx[indx1,:]= [indx1,i]
indx1 += 1
elif group_choice[0] == 'validation_samples':
validation[indx2,:,:,:] = data=trarray[i,:,:,:]
validation_list.append( (f'ID-{indx2:04}', i) )
validation_idx[indx2,:]= [indx2,i]
indx2 += 1
else:
test[indx3,:,:,:] = data=trarray[i,:,:,:]
test_list.append( (f'ID-{indx3:04}', i) )
test_idx[indx3,:]= [indx3,i]
indx3 += 1
with h5py.File('TrainingData1_.hdf5', 'w') as h5f :
h5f.create_group('training')
h5f['training'].create_dataset('training_samples', data=training[0:indx1,:,:,:])
h5f['training'].create_dataset('training_indices', data=training_idx[0:indx1,:])
# for label, idx in training_list:
# h5f['training']['training_samples'].attrs[label] = idx
h5f.create_group('validation')
h5f['validation'].create_dataset('validation_samples', data=validation[0:indx2,:,:,:])
h5f['validation'].create_dataset('validation_indices', data=validation_idx[0:indx2,:])
# for label, idx in validation_list:
# h5f['validation']['validation_samples'].attrs[label] = idx
h5f.create_group('test')
h5f['test'].create_dataset('test_samples', data=test[0:indx3,:,:,:])
h5f['test'].create_dataset('test_indices', data=test_idx[0:indx3,:])
# for label, idx in test_list:
# h5f['test']['test_samples'].attrs[label] = idx
exe_time = timeit.default_timer() - start
print(f'Write time for {trarray.shape[0]} images slices = {exe_time:.2f} secs')