在 HDF5 (PyTables) 中存储 numpy 稀疏矩阵
Posted
技术标签:
【中文标题】在 HDF5 (PyTables) 中存储 numpy 稀疏矩阵【英文标题】:Storing numpy sparse matrix in HDF5 (PyTables) 【发布时间】:2012-06-23 04:08:16 【问题描述】:我在使用 PyTables 存储 numpy csr_matrix 时遇到问题。我收到此错误:
TypeError: objects of type ``csr_matrix`` are not supported in this context, sorry; supported objects are: NumPy array, record or scalar; homogeneous list or tuple, integer, float, complex or string
我的代码:
f = tables.openFile(path,'w')
atom = tables.Atom.from_dtype(self.count_vector.dtype)
ds = f.createCArray(f.root, 'count', atom, self.count_vector.shape)
ds[:] = self.count_vector
f.close()
有什么想法吗?
谢谢
【问题讨论】:
您是否担心磁盘上的数据大小?我认为 hdf5 文件可以以压缩格式存储,在这种情况下,您可能只需存储密集矩阵即可。 见***.com/questions/8895120/…,好像没有对稀疏矩阵的pytables支持。 【参考方案1】:CSR 矩阵可以从其data
、indices
和indptr
属性完全重构。这些只是常规的 numpy 数组,因此将它们作为 3 个单独的数组存储在 pytables 中应该没有问题,然后将它们传递回csr_matrix
的构造函数。请参阅scipy docs。
编辑:Pietro 的回答指出shape
成员也应该被存储
【讨论】:
不过,我相信重点是像使用密集矩阵一样使用它。如何将 csr_matrix 转换为“密集格式”的 pytables 实例? 您可以使用其成员函数toarray将csr_matrix转换为密集数组,然后可以将其保存在pytables中。当然,这可能会浪费大量文件空间,尽管 hdf5 有文件压缩选项可能会有所帮助。 NumPytoarray()
无法处理将巨大的转换为密集的。我希望直接从 CSR 构建表格。【参考方案2】:
DaveP 的答案几乎是正确的...但可能会导致非常稀疏的矩阵出现问题:如果最后一列或最后一行为空,则它们将被删除。因此,为了确保一切正常,“shape”属性也必须存储。
这是我经常使用的代码:
import tables as tb
from numpy import array
from scipy import sparse
def store_sparse_mat(m, name, store='store.h5'):
msg = "This code only works for csr matrices"
assert(m.__class__ == sparse.csr.csr_matrix), msg
with tb.openFile(store,'a') as f:
for par in ('data', 'indices', 'indptr', 'shape'):
full_name = '%s_%s' % (name, par)
try:
n = getattr(f.root, full_name)
n._f_remove()
except AttributeError:
pass
arr = array(getattr(m, par))
atom = tb.Atom.from_dtype(arr.dtype)
ds = f.createCArray(f.root, full_name, atom, arr.shape)
ds[:] = arr
def load_sparse_mat(name, store='store.h5'):
with tb.openFile(store) as f:
pars = []
for par in ('data', 'indices', 'indptr', 'shape'):
pars.append(getattr(f.root, '%s_%s' % (name, par)).read())
m = sparse.csr_matrix(tuple(pars[:3]), shape=pars[3])
return m
使其适应 csc 矩阵很简单。
【讨论】:
以上答案中name
变量对应什么?
@Rama:只是存储对象的键。任意,你只需要它来检索它(在同一个 HDF 存储中,你可以存储大量不同的对象)。【参考方案3】:
我已经更新了 Pietro Battiston 对 Python 3.6 和 PyTables 3.x 的出色回答,因为一些 PyTables 函数名称在从 2.x 升级时发生了变化。
import numpy as np
from scipy import sparse
import tables
def store_sparse_mat(M, name, filename='store.h5'):
"""
Store a csr matrix in HDF5
Parameters
----------
M : scipy.sparse.csr.csr_matrix
sparse matrix to be stored
name: str
node prefix in HDF5 hierarchy
filename: str
HDF5 filename
"""
assert(M.__class__ == sparse.csr.csr_matrix), 'M must be a csr matrix'
with tables.open_file(filename, 'a') as f:
for attribute in ('data', 'indices', 'indptr', 'shape'):
full_name = f'name_attribute'
# remove existing nodes
try:
n = getattr(f.root, full_name)
n._f_remove()
except AttributeError:
pass
# add nodes
arr = np.array(getattr(M, attribute))
atom = tables.Atom.from_dtype(arr.dtype)
ds = f.create_carray(f.root, full_name, atom, arr.shape)
ds[:] = arr
def load_sparse_mat(name, filename='store.h5'):
"""
Load a csr matrix from HDF5
Parameters
----------
name: str
node prefix in HDF5 hierarchy
filename: str
HDF5 filename
Returns
----------
M : scipy.sparse.csr.csr_matrix
loaded sparse matrix
"""
with tables.open_file(filename) as f:
# get nodes
attributes = []
for attribute in ('data', 'indices', 'indptr', 'shape'):
attributes.append(getattr(f.root, f'name_attribute').read())
# construct sparse matrix
M = sparse.csr_matrix(tuple(attributes[:3]), shape=attributes[3])
return M
【讨论】:
以上是关于在 HDF5 (PyTables) 中存储 numpy 稀疏矩阵的主要内容,如果未能解决你的问题,请参考以下文章