在 Python 中读取 .mat 文件。但是数据的形状发生了变化

Posted

技术标签:

【中文标题】在 Python 中读取 .mat 文件。但是数据的形状发生了变化【英文标题】:Read .mat file in Python. But the shape of the data changed 【发布时间】:2017-01-08 21:43:27 【问题描述】:
 % 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)。

我使用link 的指令在 Python 中加载 .mat 文件。

代码如下:

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 之间数据形状的变化。我的代码有错误吗?

【问题讨论】:

相关:***.com/q/24116713/1714410 对于早期的.mat 版本,scipy.io.loadmat 生成的数组形状与 MATLAB 相同,但 order='F'。因此它有点隐藏了这种差异。 @hpaulj:你说的早是什么意思? “后期” mat 版本的行为变化是什么? MATLAB save 采用版本选项。 V7 和更早的版本使用原生 MATLAB 文件格式,而不是 hdf5loadmat 处理这些。如果需要,我可以发布 Octave/numpy 示例。 【参考方案1】:

代码中没有任何错误。 Matlab 和 python 在处理多维数组的方式上存在根本区别。 Matalb 和 python 都将多维数组的所有元素作为单个连续块存储在内存中。不同之处在于元素的顺序:Matlab,(如 fortran)以列优先方式存储元素,即根据数组的维度存储元素,用于 2D :

 [1 3;
  2 4]

相比之下,Python 以行优先方式存储元素,即从数组的 last 维度开始:

[1 2;
 3 4];

因此,在 Matlab 中具有 size [m,n,k] 的内存块被 python 视为 shape [k,n,m] 的数组。

欲了解更多信息,请参阅this wiki page。

顺便说一句,您可以尝试将其顺序设置为“Fortran”顺序(如 Matlab 中的 col-major),而不是转置 train_set_x

 train_set_x = np.array(train_set_x, order='F')

【讨论】:

设置order='F'时结果和转置有区别吗?还是只影响内存使用? in numpy 转置是一个 O(1) 操作:它不会重新定位内存中的元素,只会挂起数组的元数据(它的 strides)。我想你可以比较 stridesshape 在阅读与 order="F" 和转置之间。我猜这两种方法相当于同一个对象。 谢谢!很高兴了解 order 参数,即使转置产生相同的结果。 @mwormser 我想在这种情况下使用order="F" 方式更“正确”,它清楚地表明由于外部程序存储约定,代码期望数据的顺序不同. 我尝试了order="F" 和转置。但是print(train_set_x.shape) 的输出是不同的。转置是(50L, 1L, 51L, 61L, 23L),而order="F"(23L, 61L, 51L, 1L, 50L)

以上是关于在 Python 中读取 .mat 文件。但是数据的形状发生了变化的主要内容,如果未能解决你的问题,请参考以下文章

python读取mat(v7.3)文件中的cell以及struct

python 笔记:读取mat文件

python中读取mat文件

Python读取mat文件

python读取mat文件

python写入和读取h5、pkl、mat 文件