2012-06-20 4 views
20

У меня возникли проблемы с хранением nums csr_matrix с PyTables. Я получаю эту ошибку:Хранение малоразмерной матрицы в HDF5 (PyTables)

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

матрица КСО может быть полностью восстановлена ​​по своим data, indices и indptr атрибутов. Это просто регулярные массивы numpy, поэтому не должно быть проблем с их хранением в виде трех отдельных массивов в pytables, а затем их возврата к конструктору csr_matrix. См. scipy docs.

Edit: ответ Пьетро отметил, что shape элемент также должен храниться

+0

Я считаю, что смысл в том, чтобы использовать его как плотную матрицу. Как преобразовать csr_matrix в экземпляр pytables с плотным форматом? – Will

+0

Вы можете преобразовать csr_matrix в плотный массив, используя его функцию-член toarray, которая затем может быть сохранена в pytables. Конечно, это потенциально может привести к большому количеству файлового пространства, хотя hdf5 имеет параметры сжатия файлов, которые могут помочь. – DaveP

+1

NumPy 'toarray()' не может обрабатывать преобразование гигантских в плотные. Я надеялся построить таблицу непосредственно из CSR. – Will

33

Ответ на 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 матриц.

+0

Что соответствует переменной 'name' в приведенном выше ответе? – Rama

+1

@Rama: просто ключ для хранения объекта. Произвольно, вам просто нужно его вернуть (в том же хранилище HDF, вы можете хранить множество разных объектов). –

6

Я обновил отличный 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 
Смежные вопросы