2012-06-20 3 views
20

PyTables로 numpy csr_matrix를 저장하는 데 문제가 있습니다. 이 오류를 받고 있어요 :HDF5 (PyTables)에 numpy 스파 스 매트릭스 저장

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() 

어떤 아이디어가?

감사

+0

디스크의 데이터 크기가 걱정 되십니까? hdf5 파일을 압축 된 형식으로 저장할 수 있다고 생각합니다.이 경우 밀도가 높은 행렬 만 저장하면됩니다. – user545424

+2

http://stackoverflow.com/questions/8895120/using-pytables-which-is-more-efficient-scipy-sparse-or-numpy-dense-matrix, 스파 스 매트릭스에 대한 pytables 지원이없는 것처럼 보입니다. – user545424

답변

21

CSR의 행렬은 완전히 그 data, indicesindptr 속성에서 재구성 할 수 있습니다. 이것들은 보통의 numpy 배열 일 뿐이므로 pytables에 3 개의 개별 배열로 저장 한 다음 csr_matrix의 생성자로 다시 전달할 때 아무런 문제가 없어야합니다. scipy docs을 참조하십시오.

편집 : 피에트로의 대답은 shape 멤버도

을 보관해야한다고 지적했다
+0

그러나 나는이 점을 조밀 한 매트릭스처럼 사용하는 것이 중요하다고 생각합니다. 어떻게 csr_matrix를 "dense-format"pytables 인스턴스로 변환 할 수 있습니까? – Will

+0

멤버 함수 toarray를 사용하여 csr_matrix를 조밀 한 배열로 변환 할 수 있습니다.이 배열을 pytables에 저장할 수 있습니다. hdf5에는 도움이 될 수있는 파일 압축 옵션이 있지만 물론, 이것은 잠재적으로 많은 파일 공간을 낭비 할 수 있습니다. – DaveP

+1

NumPy'toarray()'는 거대한 변환을 처리 할 수 ​​없습니다. CSR에서 직접 테이블을 구성하기를 희망했습니다. – Will

33

DaveP에 의한 대답은 바로 거의입니다 ...하지만 매우 희소 행렬에 대한 문제가 발생할 수 있습니다 : 마지막 열 경우 행 또는 행이 비어 있으면 삭제됩니다. 따라서 모든 것이 제대로 작동하려면 "모양"속성도 저장해야합니다.

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에 적응하는 것이 간단하다 :

내가 정기적으로 사용하는 코드입니다.

+0

위의 답변에서 'name' 변수는 무엇에 해당합니까? – Rama

+1

@Rama : 개체를 저장하기위한 키. 임의로, 다시 검색하면됩니다 (동일한 HDF 상점에서 여러 개의 오브젝트를 저장할 수 있습니다). –

6

2.x에서 업그레이드 할 때 일부 PyTables 함수 이름이 변경되어 Pietro Battiston의 우수 답변이 Python 3.6 및 PyTables 3.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