使用h5py(或其他方法)高效保存和加载数据
Efficiently saving and loading data using h5py (or other methods)
我正在测试使用 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,以便将来附加更多的训练数据。 (参见 )
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 秒,对于第二种方法,它是 1216 秒,其中我的想法没有意义。谁能帮我弄清楚为什么?
此外,我还尝试 saving/loading 使用 torch.save
和 torch.load
将其作为火炬文件,并在设置加载程序之前将数据传递给 Data.TensorDataset
。此实现运行速度明显更快(大约 3.7 s),但缺点是必须在训练前加载文件,这可能很快就会被我的记忆所限制。
有没有更好的方法可以让我训练得更快,同时不必在训练前加载所有数据?
这看起来像是 I/O 性能问题。为了进行测试,我创建了一个非常简单的示例来比较您的 2 种方法。 (我的代码在 post 的末尾。)我发现了完全相反的行为(假设我的代码模仿了您的过程)。当我 不 使用 maxshape=() 参数时,写入数据集的速度较慢:62 秒创建 w/out maxshape 与 16 秒创建 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 ')
我正在测试使用 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,以便将来附加更多的训练数据。 (参见
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 秒,对于第二种方法,它是 1216 秒,其中我的想法没有意义。谁能帮我弄清楚为什么?
此外,我还尝试 saving/loading 使用 torch.save
和 torch.load
将其作为火炬文件,并在设置加载程序之前将数据传递给 Data.TensorDataset
。此实现运行速度明显更快(大约 3.7 s),但缺点是必须在训练前加载文件,这可能很快就会被我的记忆所限制。
有没有更好的方法可以让我训练得更快,同时不必在训练前加载所有数据?
这看起来像是 I/O 性能问题。为了进行测试,我创建了一个非常简单的示例来比较您的 2 种方法。 (我的代码在 post 的末尾。)我发现了完全相反的行为(假设我的代码模仿了您的过程)。当我 不 使用 maxshape=() 参数时,写入数据集的速度较慢:62 秒创建 w/out maxshape 与 16 秒创建 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 ')