Почему loadmat SciPy выдает ошибку MemoryError при чтении структуры Matlab размером 200 МБ

Я использую следующий код, чтобы попытаться загрузить файл MAT в Python. Я могу без проблем загрузить его в MATLAB.

from scipy.io import loadmat
test_filename = 'test_data.mat' #This is a struct
data =loadmat(test_filename, struct_as_record=True)

Запуск этого кода приводит к этой ошибке:

Traceback (most recent call last):
  File "C:\Users\mac389\workspace\nexUtils\src\qA.py", line 16, in <module>
data =loadmat(test_filename, struct_as_record=True)
  File "C:\Python27\lib\site-packages\scipy\io\matlab\mio.py", line 175, in loadmat
matfile_dict = MR.get_variables(variable_names)
  File "C:\Python27\lib\site-packages\scipy\io\matlab\mio5.py", line 272, in get_variables
hdr, next_position = self.read_var_header()
  File "C:\Python27\lib\site-packages\scipy\io\matlab\mio5.py", line 224, in read_var_header
stream = BytesIO(dcor.decompress(data))
MemoryError

Для справки, test_data.mat — это структура со следующими полями (из консоли MATLAB):

 version: 101
 comment: 'molecular layer 4/17'
    freq: 40000
    tbeg: 0
    tend: 1.3950e+003
  events: {3x1 cell}
 neurons: {50x1 cell}
   waves: {102x1 cell}
contvars: {64x1 cell}

Test_data.mat составляет 217 МБ. У меня 4 ГБ оперативной памяти. Я использую SciPy 0.10.0 и NumPy 1.6.1. Изменение поля struct_as_record ничего не дает.

Как я могу загрузить структуру, в которой поля представляют собой массивы ячеек?


person mac389    schedule 15.06.2012    source источник
comment
У тебя закончилась память. Хотя размер файла может составлять всего 200 МБ, требования к оперативной памяти могут быть больше.   -  person David Heffernan    schedule 16.06.2012
comment
Сжат ли файл .mat? Вы используете 32-битный процесс Python? Является ли ваш процесс MATLAB 64-битным?   -  person David Heffernan    schedule 16.06.2012
comment
@David: файл mat не подвергается дальнейшему сжатию за пределами двоичного формата Matlab. Оба процесса 32-битные. Мой вопрос в том, почему загрузка небольшого файла съедает память в Python, а не в Matlab, и что я могу сделать, чтобы обойти это.   -  person mac389    schedule 16.06.2012
comment
@David Я думаю, основываясь на трассировке стека, что loadmat застревает при чтении имен полей структуры. Это может быть не просто слишком большой файл.   -  person mac389    schedule 16.06.2012


Ответы (2)


Я нашел ответ.

Loadmat не может работать с сильно вложенными структурами. В наборе данных, который мне дали, три поля структуры («волны», «нейроны», «контвары») были массивами ячеек. Каждый член этого массива ячеек был структурой. Некоторые из полей этих структур сами были массивами ячеек. В этих массивах ячеек было одно поле, содержащее данные. Этот нестандартный способ организации данных в сочетании с отсутствием документации создал проблему.

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

person mac389    schedule 16.06.2012

Я думаю, что в Python требуется больше памяти из-за того, как реализована распаковка. Попробуйте сохранить в Matlab без сжатия (используя -v6, формат версии 6 не имеет функции сжатия).

person robince    schedule 16.06.2012
comment
Это поможет определить, связана ли проблема с памятью. Спасибо за полезный совет по диагностике. Но что тогда делать? - person mac389; 16.06.2012
comment
Ну, вы мало что можете сделать. Если это работает, вы можете использовать v6 на стороне Matlab (вы можете установить его в качестве формата сохранения по умолчанию). В противном случае вам нужно будет обновить память на стороне Python и переключиться на 64-битную версию. Или вы могли бы посмотреть на использование другого формата. Matlab может писать в HDF5, который хорошо поддерживается в Python, поэтому, если вы можете преобразовать свои данные, чтобы они поместились в контейнер HDF5, возможно, это сработает для вас. - person robince; 17.06.2012