Python hdf5storage транспонирует мои данные? - PullRequest
0 голосов
/ 06 сентября 2018

Код Python:

import h5py
import hdf5storage
from functools import reduce
import numpy as np
from operator import mul

sz = 128,256,512
a = np.random.normal(size=reduce(mul,sz)).reshape(sz)
save_dict = {'data':a}

spath = r"test.mat"
hdf5storage.savemat(spath, mdict=save_dict, append_mat=False, 
                    store_python_metadata=True, format='7.3')

with h5py.File(spath, 'r') as file:
    b = np.array(file['data'])

# Reads in the correct shape, but is F-contiguous. Scipy doesn't work with v7.3 files.
c = hdf5storage.loadmat(spath)['data']

Когда объект создан, он имеет форму (128,256,512). Однако когда я сохраняю a в файл .mat с помощью hdf5storage, а затем загружаю его в b с помощью h5py, b транспонируется так, как имеет форму (512,256,128). Оба массива являются C-смежными при проверке их флагов.

Есть ли какой-нибудь способ предотвратить это транспонирование? У меня сложилось впечатление, что формат hdf5 сохраняет row-major.

1 Ответ

0 голосов
/ 06 сентября 2018

Я снова посмотрел на файл abc.h5, описанный в:

как импортировать файл .mat-v7.3 с использованием h5py

Он был создан в Октаве с:

>> A = [1,2,3;4,5,6];
>> B = [1,2,3,4];
>> save -hdf5 abc.h5 A B

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

In [102]: f = h5py.File('abc.h5','r')
In [103]: A = f['A']['value'][:]
In [104]: A
Out[104]: 
array([[1., 4.],
       [2., 5.],
       [3., 6.]])
In [105]: A.shape
Out[105]: (3, 2)
In [106]: A.flags
Out[106]: 
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  ...
In [107]: A.ravel()
Out[107]: array([1., 4., 2., 5., 3., 6.])

Итак, это транспонированный массив порядка C. Очевидно, именно так разработчики MATLAB решили хранить свои матрицы в HDF5.

Я мог бы перенести это в numpy:

In [108]: At = A.T
In [109]: At
Out[109]: 
array([[1., 2., 3.],
       [4., 5., 6.]])
In [110]: At.flags
Out[110]: 
  C_CONTIGUOUS : False
  F_CONTIGUOUS : True
  ....

Как обычно, массив C-порядка становится F-порядком при транспонировании.

Матрицы Octave, сохраненные в более старом формате .mat

In [115]: data = io.loadmat('../abc.mat')
In [116]: data['A']
Out[116]: 
array([[1., 2., 3.],
       [4., 5., 6.]])
In [117]: _.flags
Out[117]: 
  C_CONTIGUOUS : False
  F_CONTIGUOUS : True

Таким образом, транспонированный массив h5py соответствует соглашению, которое io.loadmat использовало довольно долгое время.

У меня не установлена ​​hdf5storage в этой ОС. Но по вашим тестам, он следует соглашению io.loadmat - правильная форма, но порядок F.

...