Эффективное сохранение и загрузка данных с использованием h5py (или других методов) - PullRequest
1 голос
/ 23 марта 2020

Я тестирую способы эффективного сохранения и извлечения данных с использованием h5py. Но у меня проблемы со временем выполнения, когда я не использую всю мою память.

В моем первом методе я просто создаю файл * stati c 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 , чтобы добавить больше обучающих данных в будущем. (см. Как добавить данные к одному указанному c набору данных в файле hdf5 с 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 ГБ каждый. Я проверяю время пробега, используя:

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 с , а для второго оно составляет 1216 с , что в моем ум не имеет смысла. Может кто-нибудь помочь мне понять, почему?

Кроме того, я также попытался сохранить / загрузить его в виде файла факела, используя torch.save и torch.load и передав данные в Data.TensorDataset перед настройкой загрузчика. Эта реализация работает значительно быстрее (около 3,7 с ), но имеет недостаток, заключающийся в необходимости загружать файлы перед тренировкой, что может быть быстро ограничено моей памятью.

Есть ли лучший способ в котором я могу тренироваться несколько быстрее, не загружая все данные перед тренировкой?

1 Ответ

0 голосов
/ 25 марта 2020

Это похоже на проблему производительности ввода-вывода. Чтобы проверить, я создал очень простой пример, чтобы сравнить ваши 2 метода. (Мой код находится в конце поста.) Я обнаружил совершенно противоположное поведение (при условии, что мой код имитирует ваш процесс). Запись набора данных происходит медленнее, когда я не использует параметр maxshape = (): 62 se c для создания без maxshape против 16 se c создать с 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 ** 

Код для создания 2 файлы ниже:

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 ')
...