Загрузка разреженной матрицы Matlab с использованием Python Pytables

Первоначально я задал связанный с этим вопрос ">здесь, но, похоже, никуда не денешься. Возможно, если я перефразирую часть этого более конкретно, это может помочь....

У меня есть файлы, хранящиеся в разреженном формате Matlab (HDF5, csc, я полагаю), и я пытаюсь использовать Pytables для работы с ними напрямую, но пока безуспешно. Используя h5py, я могу сделать следующее:

# Method 1: uses h5py (WORKS)
f1 = h5py.File(fname)
data = f1['M']['data']
ir = f1['M']['ir']
jc = f1['M']['jc']
M = scipy.sparse.csc_matrix((data, ir, jc))

но если я попытаюсь сделать эквивалент в Pytables:

# Method 2: uses pyTables (DOESN'T WORK)
f2 = tables.openFile(fname)
data = f2.root.M.data
ir = f2.root.M.ir
jc = f2.root.M.jc
M = scipy.sparse.csc_matrix( (data,ir,jc) )

это не удается (после долгого ожидания) с ошибкой:

TypeError                                 Traceback (most recent call last)

/home/tdiethe/BMJ/<ipython console> in <module>()

/usr/lib/python2.6/dist-packages/scipy/sparse/compressed.pyc in __init__(self, arg1, shape, dtype, copy, dims, nzmax)
    56                     self.indices = np.array(indices, copy=copy)
    57                     self.indptr  = np.array(indptr, copy=copy)
---> 58                     self.data    = np.array(data, copy=copy, dtype=getdtype(dtype, data))
    59                 else:
    60                     raise ValueError, "unrecognized %s_matrix constructor usage" %\

/usr/lib/python2.6/dist-packages/scipy/sparse/sputils.pyc in getdtype(dtype, a, default)
    69                 canCast = False
    70             else:
---> 71                 raise TypeError, "could not interpret data type"
    72     else:
    73         newdtype = np.dtype(dtype)

TypeError: could not interpret data type

Глядя на f2:

In [63]: f2.root.M.data
Out[63]: 
/M/data (CArray(4753606,), zlib(3)) ''
  atom := Float64Atom(shape=(), dflt=0.0)
  maindim := 0
  flavor := 'numpy'
  byteorder := 'little'
  chunkshape := (8181,)

In [64]: f2.root.M.ir
Out[64]: 
/M/ir (CArray(4753606,), zlib(3)) ''
  atom := UInt64Atom(shape=(), dflt=0)
  maindim := 0
  flavor := 'numpy'
  byteorder := 'little'
  chunkshape := (8181,)

In [65]: f2.root.M.jc
Out[65]: 
/M/jc (CArray(133339,), zlib(3)) ''
  atom := UInt64Atom(shape=(), dflt=0)
  maindim := 0
  flavor := 'numpy'
  byteorder := 'little'
  chunkshape := (7843,)

У меня есть два вопроса:

  • как загрузить этот файл с помощью pytables
  • мне нужно выполнить преобразование в scipy разреженную матрицу, чтобы иметь возможность выполнять над ней операции, или я могу выполнять операции непосредственно с файлами на диске (умножение матриц и т.д....) - т.е. без загрузки файла в память ( если нет, то какой смысл использовать pytables?)?

person tdc    schedule 09.12.2011    source источник
comment
Эти ошибки исходят из scipy. Можете ли вы проверить способность, скажем, просто numpy работать с data, ir или jc. Что numpy может сказать о данных (например, dtype, shape и т. д.)? Являются ли результаты такими, как вы ожидаете? Соответствуют ли они тому, что ожидается в scipy.sparse.csc_matrix для этой позывной?   -  person dtlussier    schedule 12.12.2011
comment
Ах да, кажется, все, что мне нужно было сделать, это: M = sparse.csc_matrix( (f2.root.M.data[...], f2.root.M.ir[...], f2.root.M.jc[...]) ) Еще не определились со вторым вопросом? Кажется, что в PyTables доступны только поэлементные операции?   -  person tdc    schedule 13.12.2011


Ответы (1)


Я пропустил это в вашем исходном сообщении, но я думаю, что ваша проблема связана с дизайном PyTables, который обеспечивает дополнительный уровень абстракции поверх базовых данных.

Рассмотрим следующее:

>>> import tables
>>> import numpy as np

>>> h5_file = tables.openFile(fname)
>>> data = f2.root.M.data

На данный момент data не является массивом numpy:

>>> type(data)
tables.array.Array

>>> isinstance(data, np.ndarray)
False

tables.array.Array немедленно загружает базовый массив или сразу предоставляет функциональность, подобную массиву. Именно это привело к ошибке, когда вы попытались использовать эти типы объектов для создания разреженного массива в scipy.

Вместо этого объект data, созданный PyTables, предназначен для предоставления доступа к данным с помощью дополнительных команд (т.е. вы сделали это, используя причудливую индексацию [...]). В этом подходе вы можете получить доступ к частям данных или ко всем, выполнив data[:] или data.read(). Только в этот момент создается знакомый массив numpy.

Для получения дополнительной информации о классе tables.array.Array см. http://pytables.github.com/usersguide/libref.html#the-array-class или раздел Getting actual data на странице http://www.pytables.org/moin/HowToUse, где приведены примеры доступа к базовым данным.

Для сравнения, pyh5 создает гораздо больше объектов, похожих на массивы, хотя и не numpy массивов. Учитывать:

>>> import pyh5
>>> f1 = h5py.File(fname)
>>> data = f1['M']['data']
>>> type(data)
h5py._hl.dataset.Dataset
>>> isinstance(data, np.ndarray)
>>> False

Однако вы можете сразу выполнить numpy операций над data, например, scipy, или более простых операций, таких как np.cos(data) или data + np.arange(len(data)). Также оказывается, что объект data имеет некоторые знакомые атрибуты, подобные numpy (например, shape), и что базовые данные (numpy.ndarray) хранятся в data.value. Однако я не знаком с pyh5, так как сам им не пользовался, поэтому не уверен, какие ограничения есть в этом отношении.

В целом кажется, что PyTables и pyh5 имеют разные цели проектирования и поэтому должны использоваться по-разному. pyh5 предлагает более похожий на Numpy интерфейс для файлов HDF, а PyTables предлагает гораздо более сложные операции с базами данных, такие как операции. См. обсуждение различий в документах pyh5, PyTables и в списке рассылки Enthought:

person dtlussier    schedule 13.12.2011
comment
Очень полезный ответ спасибо. Потихоньку с этим разбираюсь! Я думаю, что PyTables предоставит некоторую полезную функциональность для нашего проекта, так как важна масштабируемость. - person tdc; 13.12.2011