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

Python 使用h5py(或其他方法)高效地保存和加载数据,python,pytorch,h5py,Python,Pytorch,H5py,我正在测试使用h5py高效保存和检索数据的方法。但是我在运行时间方面遇到了问题,因为我没有用尽所有的内存 在我的第一个方法中,我只是创建一个静态h5py文件 将h5py.File(文件名'w')作为f的: f、 创建数据集('data_X',data=X,dtype='float32') f、 创建数据集('data\u y',data=y,dtype='float32') 在第二种方法中,我设置了参数maxshape,以便将来添加更多的训练数据。(见附件) 将h5py.File(fileNa

我正在测试使用h5py高效保存和检索数据的方法。但是我在运行时间方面遇到了问题,因为我没有用尽所有的内存

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

将h5py.File(文件名'w')作为f的
:
f、 创建数据集('data_X',data=X,dtype='float32')
f、 创建数据集('data\u y',data=y,dtype='float32')
在第二种方法中,我设置了参数maxshape,以便将来添加更多的训练数据。(见附件)

将h5py.File(fileName2,'w')作为f的
:
f、 创建数据集('data_X',data=X,dtype='float32',maxshape=(无,4919))
f、 创建数据集('data_y',data=y,dtype='float32',maxshape=(无,6))
我正在使用Pytork并将我的数据加载器设置为:

H5类数据集\u全部(torch.utils.data.Dataset):
定义初始化(自身,h5路径):
#超级(数据集_h5,自身)。_u初始化___()
self.h5_路径=h5_路径
自身。_h5_gen=无
定义uu获取项目uu(自身,索引):
如果self.\u h5\u gen为无:
self.\u h5\u gen=self.\u get\u generator()
下一个(自我介绍)
返回自发送(索引)
def_get_发生器(自身):
将h5py.File(self.h5_路径,'r')作为记录:
指数=收益率
尽管如此:
X=记录['data_X'][索引]
y=记录['data_y'][索引]
指数=收益率X,y
定义(自我):
将h5py.File(self.h5_路径,'r')作为记录:
长度=记录['data_X']。形状[0]
返回长度
loader=Data.DataLoader(
dataset=H5Dataset_all(文件名),
批次大小=批次大小,
shuffle=True,num\u workers=0)
在为每种方法保存相同的数据之后,我希望它们在运行时间上是相似的,但事实并非如此。我使用的数据有大小
X.shape=(2007224919)
y.shape=(200772,6)
。每个文件大约有3.6GB。 我使用以下方法测试运行时间:

导入时间
t0=时间。时间()
对于枚举(装入器)中的i,(X_批,y_批):
#指定一个虚拟值
a=0
t1=时间。时间()-t0
打印(f'时间:{t1}')
对于第一种方法,运行时间是83秒,对于第二种方法,运行时间是1216秒,这在我看来是没有意义的。有人能帮我找出原因吗

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


有没有更好的方法可以让我在训练前不必加载所有数据的情况下快速训练?

这看起来像是一个I/O性能问题。为了测试,我创建了一个非常简单的示例来比较这两种方法。(我的代码在文章的末尾)我发现了完全相反的行为(假设我的代码模仿了你的过程)。当我不使用maxshape=()参数时,写入数据集的速度较慢:62秒创建w/out maxshape,而使用maxshape创建数据集的速度较慢。为了验证操作是否与顺序无关,我还先运行了creating _2,然后运行created _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 ')

在我看来,第一种方法的数据集大小是固定的。(这是存储
data=X
data=Y
所需的大小)您如何扩展数据集的大小?我希望看到调用
Dataset.resize()
,从原始大小/形状分配中增加大小/形状。看看这个答案,看一看
Dataset.resize()
的例子。是的,第一个方法有一个固定的大小,我正在扩展第二个方法中数据集的大小,比如:
python f['data\ux'].resize(f['data\ux'].shape[0]+X.shape[0],axis=0)
然后
python f['data\ux'][-X.shape[0]:]=X
但在我报告的运行时间中,从未调用过此函数。您调用加载程序多少次?加载程序是否在每次调用时写入相同的HDF5文件和数据集?如果是这样,在方法1中,加载程序只是用新数据覆盖现有数据。您将在文件和数据集大小中看到这一点——在使用方法1多次调用加载程序后,它们不会改变。我不确定您的意思。我只调用加载程序一次,并使用它来迭代文件名中保存的数据。在方法1中,文件被覆盖,因此最大数据量由我一次可以保存的内存量来限制。第二种方法的思想是能够不断地向文件中添加数据。问题是,当每个方法只调用一次(相同数量的数据)时,第二个方法的加载程序比第一个方法的加载程序需要更长的时间进行迭代。