【问题标题】:How to append data to one specific dataset in a hdf5 file with h5py如何使用 h5py 将数据附加到 hdf5 文件中的一个特定数据集
【发布时间】:2018-04-14 19:59:49
【问题描述】:

我正在寻找一种可能性,可以使用 Python (h5py) 将数据附加到 .h5 文件中的现有数据集。

我的项目的简短介绍:我尝试使用医学图像数据训练 CNN。由于在将数据转换为 NumPy 数组的过程中数据量巨大且内存使用量很大,我需要将“转换”拆分为几个数据块:加载和预处理前 100 个医学图像并将 NumPy 数组保存到 hdf5文件,然后加载接下来的 100 个数据集并附加现有的 .h5 文件,依此类推。

现在,我尝试存储前 100 个转换后的 NumPy 数组,如下所示:

import h5py
from LoadIPV import LoadIPV

X_train_data, Y_train_data, X_test_data, Y_test_data = LoadIPV()

with h5py.File('.\PreprocessedData.h5', 'w') as hf:
    hf.create_dataset("X_train", data=X_train_data, maxshape=(None, 512, 512, 9))
    hf.create_dataset("X_test", data=X_test_data, maxshape=(None, 512, 512, 9))
    hf.create_dataset("Y_train", data=Y_train_data, maxshape=(None, 512, 512, 1))
    hf.create_dataset("Y_test", data=Y_test_data, maxshape=(None, 512, 512, 1))

可以看出,转换后的 NumPy 数组被分成四个不同的“组”,分别存储到四个 hdf5 数据集[X_train, X_test, Y_train, Y_test] 中。 LoadIPV() 函数执行医学图像数据的预处理。

我的问题是我想将接下来的 100 个 NumPy 数组存储到同一个 .h5 文件到现有数据集中:这意味着我想附加到,例如,形状的现有 X_train 数据集[100, 512, 512, 9] 和接下来的 100 个 NumPy 数组,这样 X_train 就变成了 [200, 512, 512, 9] 的形状。其他三个数据集 X_testY_trainY_test 也应如此。

【问题讨论】:

    标签: python numpy deep-learning hdf5 h5py


    【解决方案1】:

    @Midas.Inc 的回答效果很好。只是为感兴趣的人提供一个最小的工作示例:

    import numpy as np
    import h5py
    
    f = h5py.File('MyDataset.h5', 'a')
    for i in range(10):
    
      # Data to be appended
      new_data = np.ones(shape=(100,64,64)) * i
      new_label = np.ones(shape=(100,1)) * (i+1)
    
      if i == 0:
        # Create the dataset at first
        f.create_dataset('data', data=new_data, compression="gzip", chunks=True, maxshape=(None,64,64))
        f.create_dataset('label', data=new_label, compression="gzip", chunks=True, maxshape=(None,1)) 
      else:
        # Append new data to it
        f['data'].resize((f['data'].shape[0] + new_data.shape[0]), axis=0)
        f['data'][-new_data.shape[0]:] = new_data
    
        f['label'].resize((f['label'].shape[0] + new_label.shape[0]), axis=0)
        f['label'][-new_label.shape[0]:] = new_label
    
      print("I am on iteration {} and 'data' chunk has shape:{}".format(i,f['data'].shape))
    
    f.close()
    

    代码输出:

    #I am on iteration 0 and 'data' chunk has shape:(100, 64, 64)
    #I am on iteration 1 and 'data' chunk has shape:(200, 64, 64)
    #I am on iteration 2 and 'data' chunk has shape:(300, 64, 64)
    #I am on iteration 3 and 'data' chunk has shape:(400, 64, 64)
    #I am on iteration 4 and 'data' chunk has shape:(500, 64, 64)
    #I am on iteration 5 and 'data' chunk has shape:(600, 64, 64)
    #I am on iteration 6 and 'data' chunk has shape:(700, 64, 64)
    #I am on iteration 7 and 'data' chunk has shape:(800, 64, 64)
    #I am on iteration 8 and 'data' chunk has shape:(900, 64, 64)
    #I am on iteration 9 and 'data' chunk has shape:(1000, 64, 64)
    

    【讨论】:

      【解决方案2】:

      我找到了一个似乎可行的解决方案!

      看看这个:incremental writes to hdf5 with h5py!

      为了将数据附加到特定数据集,必须首先在相应轴上调整特定数据集的大小,然后将新数据附加到“旧”nparray 的末尾。

      因此,解决方案如下所示:

      with h5py.File('.\PreprocessedData.h5', 'a') as hf:
          hf["X_train"].resize((hf["X_train"].shape[0] + X_train_data.shape[0]), axis = 0)
          hf["X_train"][-X_train_data.shape[0]:] = X_train_data
      
          hf["X_test"].resize((hf["X_test"].shape[0] + X_test_data.shape[0]), axis = 0)
          hf["X_test"][-X_test_data.shape[0]:] = X_test_data
      
          hf["Y_train"].resize((hf["Y_train"].shape[0] + Y_train_data.shape[0]), axis = 0)
          hf["Y_train"][-Y_train_data.shape[0]:] = Y_train_data
      
          hf["Y_test"].resize((hf["Y_test"].shape[0] + Y_test_data.shape[0]), axis = 0)
          hf["Y_test"][-Y_test_data.shape[0]:] = Y_test_data
      

      但是,请注意,您应该使用maxshape=(None,) 创建数据集,例如

      h5f.create_dataset('X_train', data=orig_data, compression="gzip", chunks=True, maxshape=(None,)) 
      

      否则无法扩展数据集。

      【讨论】:

      • 为此,您还需要确保在创建数据集时设置了 maxshape 参数,否则 h5py 不会让您扩展它
      • 首先要非常清楚如何创建数据集,如下所示: h5f.create_dataset('X_train', data=orig_data, compression="gzip", chunks =True, maxshape=(None,)) 将 maxshape 设置为我所拥有的元组的关键部分。
      • 当您创建具有特定压缩和压缩级别的数据集时,新附加的数据是否也具有相同的压缩级别/?
      • 使用axis=0的目的是什么。对我来说,它返回一个错误SyntaxError: invalid syntax
      • 我需要测量性能上的差异,但我认为调整数组大小的常用方法是附加到它们直到它们满了,然后调整到当前长度的两倍以避免太多resize来电。不过,它可能只需要实时写入新数据的应用程序。
      猜你喜欢
      • 2022-11-14
      • 2015-10-29
      • 2013-02-26
      • 2018-02-22
      • 2019-04-26
      • 2015-04-17
      • 2014-07-19
      • 2016-03-23
      • 2014-10-26
      相关资源
      最近更新 更多