Загрузка разреженной матрицы Matlab, сохраненной с -v7.3 (HDF5), в Python и работа с ней

Я новичок в python, из Matlab. У меня есть большая разреженная матрица, сохраненная в формате Matlab v7.3 (HDF5). До сих пор я нашел два способа загрузки в файл, используя h5py и tables. Однако после этого работа с матрицей кажется чрезвычайно медленной. Например, в матлабе:

>> whos     
  Name           Size                   Bytes  Class     Attributes

  M      11337x133338            77124408  double    sparse    

>> tic, sum(M(:)); toc
Elapsed time is 0.086233 seconds.

Использование таблиц:

t = time.time()
sum(f.root.M.data)
elapsed = time.time() - t
print elapsed
35.929461956

Использование h5py:

t = time.time()
sum(f["M"]["data"])
elapsed = time.time() - t
print elapsed

(Я перестал ждать...)

[РЕДАКТИРОВАТЬ]

Основываясь на комментариях @bpgergo, я должен добавить, что пытался преобразовать результат, загруженный h5py (f), в массив numpy или разреженный массив scipy следующими двумя способами:

from scipy import sparse
A = sparse.csc_matrix((f["M"]["data"], f["M"]["ir"], f["tfidf"]["jc"]))

or

data = numpy.asarray(f["M"]["data"])
ir = numpy.asarray(f["M"]["ir"])
jc = numpy.asarray(f["M"]["jc"])    
    A = sparse.coo_matrix(data, (ir, jc))

но обе эти операции также чрезвычайно медленны.

Есть ли что-то, что мне здесь не хватает?


person tdc    schedule 06.12.2011    source источник


Ответы (3)


Большая часть вашей проблемы заключается в том, что вы используете python sum для того, что фактически представляет собой массив с отображением памяти (т.е. он находится на диске, а не в памяти).

Во-первых, вы сравниваете время, необходимое для чтения с диска, со временем, которое требуется для чтения из памяти. Сначала загрузите массив в память, если вы хотите сравнить с тем, что вы делаете в Matlab.

Во-вторых, встроенный в python sum очень неэффективен для массивов numpy. (Или, скорее, итерация по каждому элементу массива numpy независимо очень медленная, что и делает встроенный python sum.) Вместо этого используйте numpy.sum(yourarray) или yourarray.sum() для массивов numpy.

Например:

(Используя h5py, потому что я лучше знаком с ним.)

import h5py
import numpy as np

f = h5py.File('yourfile.hdf', 'r')
dataset = f['/M/data']

# Load the entire array into memory, like you're doing for matlab...
data = np.empty(dataset.shape, dataset.dtype)
dataset.read_direct(data)

print data.sum() #Or alternately, "np.sum(data)"
person Joe Kington    schedule 15.12.2011
comment
Загрузка файла в Matlab была почти мгновенной (‹ 1 секунды), поэтому я думаю, что сравнение было справедливым, но я принимаю ваше замечание о встроенной функции суммирования. Я думаю, что все больше и больше людей будут делать то, что делаю я (переходя с Matlab на Python), поэтому было бы хорошо, если бы было немного больше поддержки загрузки в файлы Matlab ИМХО... - person tdc; 16.12.2011
comment
Ну, я не могу проверить это без вашего файла, но на самом деле загрузка массива в python также должна быть очень быстрой. То, что вы сейчас делаете, на самом деле не загружает его. Он возвращает то, что фактически представляет собой массив с отображением памяти. Независимый доступ к нему будет очень медленным на любом языке, так как в основном это поиск по диску. Является ли приведенный выше пример кода все еще медленным? Также взгляните на scipy.io.loadmat docs.scipy.org/doc/scipy/reference/generated/ , хотя я не уверен, поддерживает ли он разреженные массивы. - person Joe Kington; 16.12.2011

Окончательный ответ для потомков:

import tables, warnings
from scipy import sparse

def load_sparse_matrix(fname) :
    warnings.simplefilter("ignore", UserWarning) 
    f = tables.openFile(fname)
    M = sparse.csc_matrix( (f.root.M.data[...], f.root.M.ir[...], f.root.M.jc[...]) )
    f.close()
    return M
person tdc    schedule 15.12.2011

Вам не хватает numpy http://www.scipy.org/NumPy_for_Matlab_Users

person bpgergo    schedule 06.12.2011
comment
Есть еще подсказки? Если я сделаю M = numpy.asarray(f["M"]["data"]), это, кажется, займет вечность... - person tdc; 06.12.2011
comment
@tdc, я даже не знаю, что такое f в твоем коде. Попробуйте обратиться к этой странице: docs.scipy.org /doc/scipy/reference/generated/. Хотя я читал это, вам все равно понадобится библиотека Python HDF5 для загрузки файлов Matlab версии 7.3. - person bpgergo; 06.12.2011
comment
Также там ничего нет о разреженных матрицах - person tdc; 06.12.2011
comment
Извините, f был загружен с помощью h5py: f = h5py.File('filename.mat') - person tdc; 06.12.2011
comment
Numpy также может обрабатывать разреженные матрицы. Если я правильно понимаю, вы даже не можете загрузить файл формата Matlab в матрицу numpy. В этом случае я действительно предлагаю начать новый вопрос по этой конкретной проблеме (по крайней мере, я не могу помочь в этом). Я надеюсь, что вы будете в порядке после того, как вы это сделаете. - person bpgergo; 06.12.2011
comment
Я думаю, что название вопроса уместно: загрузка разреженной матрицы Matlab, сохраненной с -v7.3 (HDF5), в Python и работа с ней. После того, как файл загружен (будь то через h5py или tables), выполнение любых операций с ним кажется бесконечным: либо работа непосредственно с объектами, либо преобразование с использованием numpy.asarray или scipy.sparse.coo_matrix. Я предполагаю, что кто-то сталкивался с этой конкретной проблемой раньше - файлы, сохраненные в этом формате, довольно распространены. - person tdc; 06.12.2011
comment
Ну да, ты прав. Извините, тем временем я увлекся кое-чем другим. Я надеюсь, что кто-то, кто сталкивался с этой проблемой, увидит и ответит на этот вопрос. - person bpgergo; 06.12.2011