将 HDF5 文件读入 numpy 数组
Posted
技术标签:
【中文标题】将 HDF5 文件读入 numpy 数组【英文标题】:Read HDF5 file into numpy array 【发布时间】:2018-03-25 18:36:13 【问题描述】:我有以下代码将 hdf5 文件作为 numpy 数组读取:
hf = h5py.File('path/to/file', 'r')
n1 = hf.get('dataset_name')
n2 = np.array(n1)
当我打印 n2
时,我得到了这个:
Out[15]:
array([[<HDF5 object reference>, <HDF5 object reference>,
<HDF5 object reference>, <HDF5 object reference>...
如何读取HDF5 object reference
以查看其中存储的数据?
【问题讨论】:
【参考方案1】:最简单的方法是使用 HDF5 数据集的.value
属性。
>>> hf = h5py.File('/path/to/file', 'r')
>>> data = hf.get('dataset_name').value # `data` is now an ndarray.
您还可以对数据集进行切片,这会生成一个包含请求数据的实际 ndarray:
>>> hf['dataset_name'][:10] # produces ndarray as well
但请记住,h5py
数据集在许多方面的行为类似于ndarray
。因此,您可以将数据集本身原封不动地传递给大多数(如果不是全部)NumPy 函数。因此,例如,这很好用:np.mean(hf.get('dataset_name'))
。
编辑:
我最初误解了这个问题。问题不在于加载数字数据,而是数据集实际上包含 HDF5 引用。这是一个奇怪的设置,在h5py
中阅读有点尴尬。您需要取消引用数据集中的每个引用。我将只为其中一个展示它。
首先,让我们创建一个文件和一个临时数据集:
>>> f = h5py.File('tmp.h5', 'w')
>>> ds = f.create_dataset('data', data=np.zeros(10,))
接下来,创建对它的引用并将其中一些存储在数据集中。
>>> ref_dtype = h5py.special_dtype(ref=h5py.Reference)
>>> ref_ds = f.create_dataset('data_refs', data=(ds.ref, ds.ref), dtype=ref_dtype)
然后,您可以通过获取其名称,然后从引用的实际数据集中读取其中一个,以一种迂回的方式读取。
>>> name = h5py.h5r.get_name(ref_ds[0], f.id) # 2nd argument is the file identifier
>>> print(name)
b'/data'
>>> out = f[name]
>>> print(out.shape)
(10,)
这是迂回的,但它似乎工作。 TL;DR 是:获取引用数据集的名称,并直接从中读取。
注意:
h5py.h5r.dereference
函数在这里似乎没什么用,尽管有这个名字。它返回被引用对象的 ID。这可以直接读取,但在这种情况下很容易导致崩溃(我在这个人为的例子中做了几次)。获取名称并从中读取要容易得多。
注2:
如release notes for h5py 2.1 中所述,不推荐使用Dataset.value
属性,应酌情使用mydataset[...]
或mydataset[()]
替换。
可追溯到 h5py 1.0 的属性
Dataset.value
已被弃用,并将在以后的版本中删除。此属性将整个数据集转储到 NumPy 数组中。使用.value
的代码应更新为使用NumPy 索引,并酌情使用mydataset[...]
或mydataset[()]
。
【讨论】:
我正在尝试,但当我打印data
变量时,我仍然得到相同的 HDF5 object reference
啊,我想我知道发生了什么事。您尝试加载的数据集实际上由 HDF5 引用组成。这不是数字数据。您可以通过对文件执行h5ls
或h5dump
来验证这一点。在这种情况下,我不知道如何从h5py
中的引用数据集中读取。
看来您可以使用h5py.H5R
模块来取消引用数据集。你可以试试:h5py.h5r.dereference(hf['dataset_name'])
?
当我尝试这样做时,我收到此错误消息TypeError: dereference() takes exactly 2 positional arguments (1 given)
当我通过with h5py.File('path/to/file, 'r') as hdf: ls = list(hdf.keys()) print('List of datasets in this file: \n', ls)
列出密钥时,我得到List of datasets in this file: ['#refs#', 'data_set']
不确定这是否有帮助【参考方案2】:
你好,这是我用来读取hdf5数据的方式,希望对你有用
with h5py.File('name-of-file.h5', 'r') as hf:
data = hf['name-of-dataset'][:]
【讨论】:
【参考方案3】:HDF5 有一个简单的对象模型,用于存储datasets(粗略地说,相当于“文件数组”)并将它们组织成组(想想目录)。除了这两种对象类型之外,还有更强大的功能需要多层次的理解。
手头是“Reference”。是HDF5存储模型中的内部地址。
h5py 将为您完成所有工作,而无需调用任何晦涩的例程,因为它尽可能地遵循类似 dict 的接口(但对于引用,使其透明有点复杂)。
在文档中查找的位置是Object and Region References。它指出要访问引用 ref
指向的对象,您可以这样做
my_object = my_file[ref]
在您的问题中,有两个步骤: 1.获取参考 2. 获取数据集
# Open the file
hf = h5py.File('path/to/file', 'r')
# Obtain the dataset of references
n1 = hf['dataset_name']
# Obtain the dataset pointed to by the first reference
ds = hf[n1[0]]
# Obtain the data in ds
data = ds[:]
如果包含参考的数据集是二维的,例如,你必须使用
ds = hf[n1[0,0]]
如果数据集是标量,则必须使用
data = ds[()]
一次获取所有数据集:
all_data = [hf[ref] for ref in n1[:]]
假设 n1 的一维数据集。对于 2D,这个想法是成立的,但我没有看到写它的捷径。
为了全面了解如何使用引用来往返数据,我编写了简短的“写入程序”和一个简短的“读取程序”:
import numpy as np
import h5py
# Open file
myfile = h5py.File('myfile.hdf5', 'w')
# Create dataset
ds_0 = myfile.create_dataset('dataset_0', data=np.arange(10))
ds_1 = myfile.create_dataset('dataset_1', data=9-np.arange(10))
# Create a data
ref_dtype = h5py.special_dtype(ref=h5py.Reference)
ds_refs = myfile.create_dataset('ref_to_dataset', shape=(2,), dtype=ref_dtype)
ds_refs[0] = ds_0.ref
ds_refs[1] = ds_1.ref
myfile.close()
和
import numpy as np
import h5py
# Open file
myfile = h5py.File('myfile.hdf5', 'r')
# Read the references
ref_to_ds_0 = myfile['ref_to_dataset'][0]
ref_to_ds_1 = myfile['ref_to_dataset'][1]
# Read the dataset
ds_0 = myfile[ref_to_ds_0]
ds_1 = myfile[ref_to_ds_1]
# Read the value in the dataset
data_0 = ds_0[:]
data_1 = ds_1[:]
myfile.close()
print(data_0)
print(data_1)
您会注意到,对于参考数据集,您不能使用标准的方便易用的 NumPy 语法。这是因为 HDF5 引用不能用 NumPy 数据类型表示。它们必须一次读取和写入。
【讨论】:
【参考方案4】:这是将 hdf5 文件读取为 numpy 数组的直接方法:
import numpy as np
import h5py
hf = h5py.File('path/to/file.h5', 'r')
n1 = np.array(hf["dataset_name"][:]) #dataset_name is same as hdf5 object name
print(n1)
【讨论】:
【参考方案5】:h5py 为此类任务提供了内在方法:read_direct()
hf = h5py.File('path/to/file', 'r')
n1 = np.zeros(shape, dtype=numpy_type)
hf['dataset_name'].read_direct(n1)
hf.close()
如果您使用%timeit
,组合步骤仍然比n1 = np.array(hf['dataset_name'])
快。唯一的缺点是,需要事先知道数据集的形状,数据提供者可以将其分配为属性。
【讨论】:
【参考方案6】:我尝试了之前建议的所有答案,但没有一个对我有用。 例如,read_direct() 方法给出错误“未为数据类型类定义操作”。 .value 方法也不起作用。经过一番挣扎后,我可以使用引用本身来获取 numpy 数组。
import numpy as np
import h5py
f = h5py.File('file.mat','r')
data2get = f.get('data2get')[:]
data = np.zeros([data2get.shape[1]])
for i in range(data2get.shape[1]):
data[i] = np.array(f[data2get[0][i]])[0][0]
【讨论】:
以上是关于将 HDF5 文件读入 numpy 数组的主要内容,如果未能解决你的问题,请参考以下文章
将 HDF5 文件中的大型数据集读入 x_train 并在 keras 模型中使用