前两天用h5py做图像训练的时候遇到了一个问题,在用HDF5存储大文件的时候报错:
OverflowError: cannot serialize a bytes object larger than 4 GiB
当时有大概35G的图像要存入h5文件,而代码又是网上借鉴的,没有弄清楚h5文件存储的具体方法。为了图快,就强行把文件减小到3.5G来训练。训练的时候研究一下是怎么回事,毕竟h5这种不可能只能存4G大小的文件的。
后来弄明白了。HDF5是可以用chunk来存储的,而每一个chunk的大小不能超过4G,数据总量大小好像是不限(具体没试过)。
HDF5可以把平铺的数据分割成chunk储存,这些chunks用一个serial file来索引。至于怎么分割chunk全在码农自己。比如下面的代码是我之前有问题的代码:
parser = argparse.ArgumentParser(description='')
... ...
parser.add_argument('--image_size', dest='image_size', default=512)
parser.add_argument('--data_size', dest='data_size', default=173356)
... ...
h5file = h5py.File(args.save_file, 'w')
train_img_h5 = h5file.create_dataset(shape=(args.data_size, args.image_size, args.image_size),
maxshape=(None, args.image_size, args.image_size),
dtype=np.float32, name='train_image', compression='gzip',
chunks=(args.data_size, args.image_size, args.image_size)
)
上面的问题就出在args.data_size上。在create_dataset()中,shape确定了文件的总大小和dimension,chunks是一块数据有多大。如果是512 x 512 x 173356一块那肯定报错啊。
所以我改成了下面这样:
parser = argparse.ArgumentParser(description='')
... ...
parser.add_argument('--image_size', dest='image_size', default=512)
parser.add_argument('--data_size', dest='data_size', default=173356)
parser.add_argument('--chunk_size', dest='chunk_size', default=2048)
... ...
h5file = h5py.File(args.save_file, 'w')
train_img_h5 = h5file.create_dataset(shape=(args.data_size, args.image_size, args.image_size),
maxshape=(None, args.image_size, args.image_size),
dtype=np.float32, name='train_image', compression='gzip',
chunks=(args.chunk_size, args.image_size, args.image_size)
)
512 x 512 x 2048是没有4g的。这样改过来17万张图片就都可以存下了。
ref:https://support.hdfgroup.org/HDF5/doc/H5.intro.html