使用h5py(或其他方法)有效保存和加载数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用h5py(或其他方法)有效保存和加载数据相关的知识,希望对你有一定的参考价值。

我正在测试使用h5py有效保存和检索数据的方法。但是在不占用我所有内存的情况下,运行时间遇到了麻烦。

在我的第一种方法中,我只是创建一个静态h5py文件

with h5py.File(fileName, 'w') as f:
        f.create_dataset('data_X', data = X, dtype = 'float32')
        f.create_dataset('data_y', data = y, dtype = 'float32')

在第二种方法中,我设置参数maxshape以便将来添加更多训练数据。 (请参阅How to append data to one specific dataset in a hdf5 file with h5py

with h5py.File(fileName2, 'w') as f:
            f.create_dataset('data_X', data = X, dtype = 'float32',maxshape=(None,4919))
            f.create_dataset('data_y', data = y, dtype = 'float32',maxshape=(None,6))

我正在使用PyTorch并按如下方式设置我的数据加载器:

class H5Dataset_all(torch.utils.data.Dataset):
    def __init__(self, h5_path):
        # super(dataset_h5, self).__init__()
        self.h5_path = h5_path
        self._h5_gen = None

    def __getitem__(self, index):
        if self._h5_gen is None:
            self._h5_gen = self._get_generator()
            next(self._h5_gen)
        return self._h5_gen.send(index)

    def _get_generator(self):
        with h5py.File( self.h5_path, 'r') as record:
            index = yield
            while True:
                X = record['data_X'][index]
                y = record['data_y'][index]
                index = yield X, y

    def __len__(self):
        with h5py.File(self.h5_path,'r') as record:
            length = record['data_X'].shape[0]
            return length

loader = Data.DataLoader(
        dataset=H5Dataset_all(filename), 
        batch_size=BATCH_SIZE, 
        shuffle=True, num_workers=0)

已经为每种方法保存了相同的数据,我希望它们在运行时会相似,但是事实并非如此。我使用的数据大小为X.shape=(200722,4919)y.shape=(200772,6)。每个文件约为3.6 GB。我使用以下方法测试运行时间:

import time
t0 = time.time()
for i, (X_batch, y_batch) in enumerate(loader):
    # assign a dummy value
    a = 0 
t1 = time.time()-t0
print(f'time: t1')

对于第一种方法,运行时间为83 s,对于第二种方法,运行时间为1216 s,在我看来,这没有任何意义。谁能帮我找出原因?

另外,在设置装载程序之前,我还尝试使用torch.savetorch.load将其保存/加载为割炬文件,并将数据传递到Data.TensorDataset。此实现的运行速度明显加快(约3.7 s),但缺点是必须在训练之前加载文件,这可能很快就被我的内存所限制。

有没有一种更好的方法可以使我更快地进行训练,而又不必在训练前不必加载所有数据?

答案

这看起来是I / O性能问题。为了进行测试,我创建了一个非常简单的示例来比较您的两种方法。 (我的代码在帖子的结尾。)我发现了完全相反的行为(假设我的代码模仿了您的过程)。当我使用maxshape =()参数时,写数据集的速度较慢:62秒创建w / out maxshape16秒创建maxshape相比。为了验证操作是否不依赖于顺序,我还先创建了_2,然后创建了_1,并获得了非常相似的结果。这是时序数据:

create data_X time: 62.60318350791931  
create data_y time: 0.010000228881835  
** file 1 Done **   

create data_X time: 16.416041135787964  
create data_y time: 0.0199999809265136  
** file 2 Done ** 

创建下面两个文件的代码:

import h5py
import numpy as np
import time

n_rows = 200722
X_cols = 4919
y_cols = 6

X = np.random.rand(n_rows,X_cols).astype('float32')
y = np.random.rand(n_rows,y_cols).astype('float32')

t0 = time.time() 
with h5py.File('SO_60818355_1.h5', 'w') as h5f:
     h5f.create_dataset('data_X', data = X)
     t1 = time.time()
     print(f'create data_X time: t1-t0')

     h5f.create_dataset('data_y', data = y)
     t2 = time.time()
     print(f'create data_y time: t2-t1')
print ('** file 1 Done ** \n ')

t0 = time.time() 
with h5py.File('SO_60818355_2.h5', 'w') as h5f:
     h5f.create_dataset('data_X', data = X, maxshape=(None,X_cols))
     t1 = time.time()
     print(f'create data_X time: t1-t0')

     h5f.create_dataset('data_y', data = y, maxshape=(None,y_cols))
     t2 = time.time()
     print(f'create data_y time: t2-t1')
print ('** file 2 Done ** \n ')

以上是关于使用h5py(或其他方法)有效保存和加载数据的主要内容,如果未能解决你的问题,请参考以下文章

使用 h5py 保存混合结构化数据

从 C++ 仿真中保存和加载数据的有效方法

将 HDF5 文件转换为其他格式

加载和保存矢量到文件

Qt - 在(从)文件中保存(或加载)qt 变量的最简单和最快的方法

如何在 Flutter 中使用 json 或其他内容保存我当前的状态