Прочтите файл .mat в Python. Но форма данных изменилась

 % save .mat file in the matlab    
train_set_x=1:50*1*51*61*23;   
train_set_x=reshape(train_set_x,[50,1,51,61,23]);   
save(['pythonTest.mat'],'train_set_x','-v7.3');

Данные, полученные в Matlab, имеют размер (50,1,51,61,23).

Я загружаю файл .mat в Python с помощью инструкции по этой ссылке.

Код выглядит следующим образом:

import numpy as np, h5py
f = h5py.File('pythonTest.mat', 'r')
train_set_x = f.get('train_set_x')
train_set_x = np.array(train_set_x)

Результат train_set_x.shape - (23L, 61L, 51L, 1L, 50L). Ожидается, что это будет (50L, 1L, 51L, 61L, 23L). Так что я изменил форму на

train_set_x=np.transpose(train_set_x, (4,3,2,1,0))

Мне интересно узнать об изменении формы данных между Python и Matlab. В моем коде есть ошибки?


person sha li    schedule 01.09.2016    source источник
comment
связанные: stackoverflow.com/q/24116713/1714410   -  person Shai    schedule 01.09.2016
comment
Для более ранних версий .mat scipy.io.loadmat создает массивы той же формы, что и MATLAB, но order='F'. Таким образом, это как бы скрывает эту разницу.   -  person hpaulj    schedule 01.09.2016
comment
@hpaulj: Что вы имеете в виду под ранним сроком? Что изменилось в поведении поздних версий мата?   -  person Eric    schedule 01.09.2016
comment
MATLAB save принимает вариант версии. V7 и ранее используют собственный формат файла MATLAB, а не hdf5. loadmat этим занимается. При необходимости я могу опубликовать пример Octave / numpy.   -  person hpaulj    schedule 01.09.2016


Ответы (1)


У вас нет ошибок в коде. Между Matlab и python существует фундаментальная разница в том, как они обрабатывают многомерные массивы.
И Matalb, и python хранят все элементы многомерного массива как один непрерывный блок в памяти. Разница заключается в порядке элементов:
Matlab (например, fortran) хранит элементы в виде столбцов, то есть хранит элементы в соответствии с размерами массива для 2D :

 [1 3;
  2 4]

В отличие от этого, Python хранит элементы в порядке очереди, то есть начиная с последнего измерения массива:

[1 2;
 3 4];

Таким образом, блок в памяти с размером size [m,n,k] в Matlab рассматривается python как массив shape [k,n,m].

Для получения дополнительной информации см. эту страницу вики.

Кстати, вместо транспонирования train_set_x вы можете попробовать установить его порядок в порядке «Fortran» (col-major, как в Matlab):

 train_set_x = np.array(train_set_x, order='F')
person Shai    schedule 01.09.2016
comment
Отличается ли результат от транспонирования при установке order='F'? Или разница только в использовании памяти? - person Ian; 01.09.2016
comment
в numpy транспонирование - это операция O (1): она не перемещает элементы в памяти, а только изменяет метаданные массива (его _ 2_). Я полагаю, вы можете сравнить strides и shape между чтением с order="F" и транспонированием. Я предполагаю, что эти два метода составляют один и тот же объект. - person Shai; 01.09.2016
comment
Спасибо! Об аргументе order полезно знать, даже если транспонирование дает тот же результат. - person Ian; 01.09.2016
comment
@mwormser Я полагаю, что в этом сценарии правильнее использовать способ order="F", он дает понять, что код ожидает, что данные будут в другом порядке из-за соглашения о внешнем хранении программ. - person Shai; 01.09.2016
comment
Я пробовал order="F" и транспонирование. Но результат print(train_set_x.shape) отличается. Это (50L, 1L, 51L, 61L, 23L) для транспонирования, но (23L, 61L, 51L, 1L, 50L) для order="F". - person sha li; 01.09.2016