【问题标题】:How to update an Earray in pytables?如何更新 pytables 中的 Earray?
【发布时间】:2019-02-11 21:11:31
【问题描述】:

我的 np.array 太大而无法存储在内存中(34000、34000),因此我需要 PyTables 将其存储为 Earray。由于内存有限,我将矩阵乘法分解为分段乘法,然后将其附加到 Earray。

这里我有一个更简单的示例,其中 Earray 由 (300, 30000) 组成,其中每个元素为 9。我试图通过插入整个数组来更新它。

 [[9. 9. 9. ... 9. 9. 9.]
 [9. 9. 9. ... 9. 9. 9.]
 [9. 9. 9. ... 9. 9. 9.]
 ...
 [9. 9. 9. ... 9. 9. 9.]
 [9. 9. 9. ... 9. 9. 9.]
 [9. 9. 9. ... 9. 9. 9.]]

但是,我需要不断更新数组元素。我意识到 Earray 应该在重新分配中工作,因为它具有从 tables.array 继承的 .setitems 方法。下面是一个简单的代码来说明我如何更新行。

我遇到了重新分配在关闭时不持久的问题。

hdf5_epath = 'extendable.hdf5'
hdf5_update = tables.open_file(hdf5_epath, mode='r+')
extended_data = hdf5_update.root.data[:]

sess = tf.Session()
for each in range(len(extended_data)):
    print(extended_data[each])
    abc = tf.ones(34716, tf.float32)
    ones = sess.run(abc)
    extended_data[each] = ones

hdf5_update.close()

是我做错了什么,还是 PyTables 不适合这种用例?

【问题讨论】:

标签: python pytables hdfstore


【解决方案1】:

我对 TensorFlow 不熟悉,因此只能帮助处理代码中的 Pytables 调用。是的,您可以在 EArray 中添加或更新数据。我没有使用EArray.setitems() 方法修改数据。有一种更简单的方法;只需像使用 Numpy 索引一样索引 EArray 值。如果要向 EArray 添加数据(行),请使用 EArray.append() 方法。在 Pytables 文档网站上有这两个例子。查看这些参考以获取简短教程:
pytables.org: Modifying data in tables
pytables.org: Appending data to an existing table

在您的代码中,extended_data 是一个 Numpy 数组,hdf5_update.root.data[:] 指向磁盘上的 HDF5 EArray 数据。它是副本而不是视图。修改 extended_data 不会修改 hdf5_update.root.data[:]。这就是数据不持久的原因。

我创建了一个简单的示例来展示它是如何工作的。下面的代码将修改磁盘数据。上面的输出将显示修改 EArray 后 extended_datahdf5_update.root.data[:] 的值不同。磁盘数据被修改。内存中的数据不是。向下滚动代码以创建示例 HDF5 文件。

就地修改 HDF5 EARRAY 的代码:

import tables as tb, numpy as np
hdf5_epath = 'extendable.hdf5'
h5f = tb.open_file(hdf5_epath, mode='r+')

extended_data = h5f.root.MyData.X[:]

print (extended_data.dtype, extended_data.shape)

myarray = 9.*np.ones(3*300).reshape((3,300))

h5f.root.MyData.X[0:3, : ] = myarray 
print (extended_data[0,0], extended_data[2,299])
print (h5f.root.MyData.X[0,0], h5f.root.MyData.X[2,299])

h5f.root.MyData.X[-3:, : ] = myarray 
print (extended_data[-1,0], extended_data[-1,299])
print (h5f.root.MyData.X[-1,0], h5f.root.MyData.X[-1,299])

h5f.close()

上面使用的创建 HDF5 的代码:
运行它来创建上面使用的extendable.hdf5。我建议您在运行每个代码段之前和之后使用 HDFView 检查数据。

import tables as tb, numpy as np
hdf5_epath = 'extendable.hdf5'
h5f = tb.open_file(hdf5_epath, mode='a')
dataGroup = h5f.create_group(h5f.root, 'MyData')

myarray = np.arange(30.*300.).reshape((30,300))

X = h5f.create_earray(dataGroup,"X", obj=myarray)                  
print ('flavor =', X.flavor )
print ('dim=', X.ndim, ', rows = ', X.nrows)

myarray = np.arange(30*300+30*300,30*300,-1).reshape((30,300))

X.append( myarray )
print ('dim=', X.ndim, ', rows = ', X.nrows)

Y_1 = X.read( 0 )
print (Y_1.dtype, Y_1.shape)

print (Y_1[0,0])
print (Y_1[-1,-1])

Y_2 = X.read( 1 )
print (Y_2[0,0])
print (Y_2[-1,-1])

h5f.close()

【讨论】: