【问题标题】:How to edit h5 files with h5py?如何使用 h5py 编辑 h5 文件?
【发布时间】:2017-09-09 02:12:38
【问题描述】:

关于使用 h5py 覆盖数组的问题并没有解决我的问题。 我想编辑 VGG16 模型的数组值。

f = h5py.File('C:/Users/yash/.keras/models/vgg16_weights_tf_dim_ordering_tf_kernels_2.h5', mode = 'a')
ab = list(h5py.AttributeManager.keys(f))
print(list(f.attrs.keys()))
print(ab)

上面的代码返回:

['layer_names']


['block1_conv1', 'block1_conv2', 'block1_pool', 'block2_conv1', 'block2_conv2', 'block2_pool', 'block3_conv1', 'block3_conv2', 'block3_conv3', 
'block3_pool', 'block4_conv1', 'block4_conv2', 'block4_conv3', 'block4_pool',
'block5_conv1', 'block5_conv2', 'block5_conv3', 'block5_pool', 'fc1', 'fc2', 

'flatten', 'predictions']

使用此代码后: print(f.attrs['layer_names'])

我得到以下信息:

[b'block1_conv1' b'block1_conv2' b'block1_pool' b'block2_conv1'
 b'block2_conv2' b'block2_pool' b'block3_conv1' b'block3_conv2'
 b'block3_conv3' b'block3_pool' b'block4_conv1' b'block4_conv2'
 b'block4_conv3' b'block4_pool' b'block5_conv1' b'block5_conv2'
 b'block5_conv3' b'block5_pool' b'flatten' b'fc1' b'fc2' b'predictions']

如何更改 f.attrs['layer_names'] 中包含的值?我无法编辑它们主要是因为使用: print(f.attrs['layer_names/block1_conv1']) 返回错误。

每个block(n)_conv(n)内部都有一个权重和偏差矩阵。

我想更改这些值。

我在 python 3 中这样做,没有文档帮助我编辑这些值。主要是因为我无法在不使用此代码的情况下访问这些:

layer = h5py.AttributeManager.get(f, key = str(layerstringlist[i]))
 nplayer = np.asarray(list(layer))

layerstringlist是这种方式的列表:

['block1_conv1/block1_conv1_W_1:0', 'block1_conv1/block1_conv1_b_1:0', .....
'predictions/predictions_W_1:0', 'predictions/predictions_b_1:0']

这会正确返回它,但我无法保存修改后的 h5 文件,因为我不知道如何在 python 3 中引用它。

提前致谢!

【问题讨论】:

  • 您不能使用f.attrs['layer_names'][0]f.attrs['layer_names'][1] 等访问内容吗?
  • 我试过了。 f.attrs['layer_names'][0][:] 返回 b'block1_conv1'。基本上它是一个列表,使用 [0] 对其进行索引。我需要访问“block1_conv1”中的组,这样我就可以使用该矩阵并对其进行编辑。有什么建议吗?
  • 字符串是一个字节序列,所以是的,您会在该位置看到字符的 (ASCII) 值(c 为 107)。但实际上,这对您没有帮助,因为它只访问层的名称,而不是它们的数据。
  • 我认为我无法访问子分支的原因是因为它们的名称是一个字节字符串,但是根 (layer_names) 只是一个字符串。所以使用这个: f.attrs['layer_names/block1_conv1'] 不起作用。你有什么技巧可以规避这个问题吗?谢谢。
  • 我不清楚,为什么你不能直接访问它们:f['block1_conv1']?因为'layer_names' 只是f 属性中的一个键。您还应该直接查看f.keys(),而不是f.attrs

标签: python arrays numpy h5py


【解决方案1】:

我之前没见过AttributeManager的用法,可能是因为文档不鼓励使用http://docs.h5py.org/en/latest/high/attr.html#reference

我得到了其他 SO 测试留下的文件:

In [480]: list(h5py.AttributeManager.keys(f))
Out[480]: ['agroup', 'agroup1', 'agroup2', 'arr']
In [481]: list(f.attrs.keys())
Out[481]: []
In [482]: list(f.keys())
Out[482]: ['agroup', 'agroup1', 'agroup2', 'arr']

在这种情况下,我没有为文件分配任何属性,因此f.attrs.keys() 为空。您的文件似乎有一个属性“layer_names”。它的值是一个名称列表,您可以使用print(f.attrs['layer_names']) 列出。

AttributeManager 列出了组和数据集,而不是 attrs。我得到了与f.keys() 相同的列表。

您应该通过以下方式访问这些组或数据集之一:

f['block1_conv1']

如果这是一个组,您需要向下索引另一个层。如果是数据集,则按照http://docs.h5py.org/en/latest/high/dataset.html#reading-writing-data中的描述对其进行读写

我认为f.attrs['layer_names'] 列表对您没有任何用处,因为它与 `list(f.keys()) 具有相同的信息。


根据您的评论,f['block1_conv1'] 是一个组,包含多个数据集。这些是索引集合的等效方法:

f['block1_conv1/block1_conv1_W_1:0'] 
f['block1_conv1']['block1_conv1_W_1:0']

在我的测试文件中

In [483]: f['arr']
Out[483]: <HDF5 dataset "arr": shape (3,), type "|V31">

我可以使用value[:] 将数据集作为数组加载到内存中:

In [485]: f['arr'].value
Out[485]: 
array([(123, 1, 1, 1, 1, 1, 1, 1), (  1, 1, 1, 1, 1, 1, 1, 1),
       (  1, 1, 1, 1, 1, 1, 1, 1)],
      dtype=[('Status', '<u8'), ('Segments', '<u4'), ('Characterized', '<u4'), ('More_Segments', '<u4'), ('ID', '<i4'), ('Releases', '<u2'), ('Type', 'u1'), ('Track', '<i4')])
In [486]: f['arr'][:]
Out[486]: 
array([(123, 1, 1, 1, 1, 1, 1, 1), (  1, 1, 1, 1, 1, 1, 1, 1),
       (  1, 1, 1, 1, 1, 1, 1, 1)],
      dtype=[('Status', '<u8'), ('Segments', '<u4'), ('Characterized', '<u4'), ('More_Segments', '<u4'), ('ID', '<i4'), ('Releases', '<u2'), ('Type', 'u1'), ('Track', '<i4')])

(对不起,这个例子是一个复杂的结构化数组。)

我可以像修改相同类型和形状的数组一样修改这个数据集的值

In [487]: f['arr']['Status']
Out[487]: array([123,   1,   1], dtype=uint64)
In [488]: f['arr']['Status'] = [1,2,3]

我无法替换它。 f['arr'] = np.arange(10) 给我一个错误(名称已经存在)。 f['arr'][:] = np.arange(10) 给出不同的错误(关于不兼容的形状)。

我可以创建一个不同名称的新数据集

In [492]: f.create_dataset('newarray', np.arange(10))
Out[492]: <HDF5 dataset "newarray": shape (0, 1, 2, 3, 4, 5, 6, 7, 8, 9), type "<f4">
In [493]: list(f.keys())
Out[493]: ['agroup', 'agroup1', 'agroup2', 'arr', 'newarray']

我可以通过以下方式删除数据集:

In [494]: del f['newarray']
In [495]: list(f.keys())
Out[495]: ['agroup', 'agroup1', 'agroup2', 'arr']

并定义一个具有相同名称的新名称:

In [500]: f.create_dataset('newarray', data=np.ones((3,4)))
Out[500]: <HDF5 dataset "newarray": shape (3, 4), type "<f8">

【讨论】:

  • 这行得通。 f['block1_conv1/block1_conv1_W_1:0'] 返回一个 ,当它转换为列表时,可以得到我想要的矩阵。我的问题是,如何将此矩阵更改为另一个 numpy 数组? (我想最后提交对 h5 文件的更改)文档对我来说太复杂了,所以我直接问你。谢谢!
  • 我添加了一些访问和修改数据集的示例。
  • 我看到了你所说的,我试过了:replace = np.zeros(shape = np.asarray(list(f['block1_conv1/block1_conv1_W_1:0'])).shape)f['block1_conv1/block1_conv1_W_1:0'] = replace 它给了我:无法创建链接(名称已存在)。所以我这样做的唯一方法是删除该特定引用,并创建一个新引用:f.create_dataset('block1_conv1/block1_conv1_W_1:0', replace) 在删除该 HDF5 对象后是吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-20
  • 2022-12-11
  • 2019-10-04
  • 2015-09-17
  • 2023-03-14
  • 2021-08-03
  • 2018-02-13
相关资源
最近更新 更多