Matrix in Matlab中的矩阵约定
Matlab中的矩阵约定
Matlab这个名字,是Matrix Laboratory的缩写,以前(真的以前,互联网前时代)有一个清华还是北大的几个学生,做的魔性视频里,有个配音:马特拉博,马特拉波,我到现在还能随时想起来,每次想起来大脑里都要响起这个声音。所以我现在使用Matlab,简直是……
Matlab中倒是随处可见Mat,甚至数据文件的后缀名也是.mat
,这门所谓的语言,也称为M语言,因为脚本和函数的后缀名是.m
。
Matlab中,矩阵是其非常核心的概念和数据结构。就像是Python,在numpy之前,也是个弱鸡。Matlab能打,基础就是矩阵和相关的计算工具箱。
矩阵形状
Matlab仲可以表示N维数组,这里用数组,主要是表示一般编程语言中的非稀疏矩阵,类似于C#的MathNet.Numerics库中的DensityMatrix。因为Matlab还有一种稀疏矩阵的表示方式,以后再说。
N为数组,假设每个维度的长度分别为n1, n2, ..., nN
,那么这个数组就是一个n1 x n2 x ... x nN
的矩阵。数组的元素一共是n1 * n2 * ... * nN
个。Matlab专门有个函数size
来获取数组的维度信息,还有个函数numel
来获取数组元素总长度信息。
前者返回一个行向量,后者返回一个标量。
$$ m \equiv m_{n1\times n2 \times \cdots \times nN} \in \mathbb{R}^{n1 \times n2 \times ... \times nN} $$$$ \text{size}(m) = [n1, n2, ..., nN] $$$$ \text{numel}(m) = n1 \times n2 \times ... \times nN $$此外,还有一个函数ndims
,返回数组的维度数目。length
函数返回数组的最大维度长度。
矩阵元素访问
要访问矩阵的元素,在Matlab中,使用()
符号,里面是一个逗号分隔的下标列表。下标列表的长度应该等于数组的维度数目。
约定1:Matlab中的下标从1开始,不是从0开始。
对于程序员而言, 下标0开始是一个从C语言开始的传统. 并且下标0, 1, 2, 3, … 实际上也代表了内存中的偏移量. 但是, 前面反复说过, Matlab是一个工程计算器, 什么偏移量,我们知道个屁…我们就开始第一个元素,第二个元素,第三个元素…这样的逻辑. 所以, Matlab中的下标从1开始, 这个约定是非常合理的, 而且, Fortran也是这样的.
矩阵的全索引
上面我们在讨论向量的约定时,提到了行向量和列向量,这里再次强调一下,Matlab中的矩阵是列优先的。那么列对于矩阵来说什么意思呢?
对于二维数组(包含列向量和行向量),列优先的意思很简单,就是按照列来存储数据。对于如下的$m\times n$的矩阵,它在内存中就等同为$m\times n$的列向量。
$$ A_{m\times n} = \begin{matrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{matrix} $$$$ A(:) = \begin{matrix} a_{11} \\ a_{21} \\ \vdots \\ a_{m1} \\ a_{12} \\ a_{22} \\ \vdots \\ a_{m2} \\ \vdots \\ a_{1n} \\ a_{2n} \\ \vdots \\ a_{mn} \end{matrix} $$其实这里说到内存中存储,通常对于很多人来说没有任何意义。但是上面这个事实,对于矩阵的访问也有一定的影响。
实际上,如果我们对于上面那个矩阵:
1A = rand(m, n);
2A
打印出就是矩阵的形式。
1A(:)
打印出就是下面的列向量。
那么对于二维矩阵,这中列优先的方式实际上预期下标(size(A)
所获得值),[m, n]
是有内在的一致性的。
那个列向量其实也可以写成:
1[
2 A(1, 1);
3 A(2, 1);
4 ...
5 A(m, 1);
6 A(1, 2);
7 A(2, 2);
8 ...
9 A(m, 2);
10 ...
11 A(1, n);
12 A(2, n);
13 ...
14 A(m, n);
15]
使用:
符号,又可以写成
1[
2 A(:, 1)
3 A(:, 2)
4 ...
5 A(:, n)
6]
这个写法,对于二维数组就是列先,对于多维数组,就是排在size
返回的维度数组中的后面的维度优先。也就是,先确定最后一个维度,然后确定倒数第二个维度,然后确定倒数第三个维度,以此类推。
约定2:多维矩阵,高维优先。
对于上面的N维数组,A(:, :, ..., :, i_i, i_{i+1}, ..., i_{N})
确定了一个n1 x n2 x ... x n_{i-1}
的矩阵。也就是,i
维到N
全部确定,前面的维度都是:
,可以在内存中确定一个连续的区域。
如果我们对一个三维数组,采用如下的方式访问:
1A(1,1,:)
得到的是n3
个不连续的值。如果我们把size
函数得到的维度向量中后面的维称为高维,前面的维称为低维。从前到后对应第一维到最后一维。
那么高维的维度确定后,访问的效率会更高。
约定3:访问矩阵时,当某个维限定,比这个维度高的所有维度都应该被限定,计算会更有效率。
矩阵降维索引
Matalb中的多维数组,还可以采用降维索引的方式访问。
约定4:矩阵降维索引时,没有给定的高维,按高维优先的方式,连接到最后一个维度,这样最后一个维度 $i$ 的范围就是 $[1, \prod_{j=i}^N n_j]$ 。
这个也很好理解,当我们用一个索引来访问一个二维矩阵 $A_{m\times n}$ 时,我们只给定了一个索引,那么这个索引就是列优先的索引,也就是 $A(:)$ 的索引,它的范围就是 $[1, m\times n]$ 。
同理,这也可以推到到多维数组上。
矩阵左值和矩阵右值
在Matlab中,语句约定写为:
1A = B;
这里的=
是赋值操作符,A
是左值,B
是右值。这个语句的意思是,把右值B
的值赋给左值A
。
当我们按照矩阵的索来引用矩阵作为左值时,右值必须是一个和左值长度相同的数组。或者是一个标量,这个标量会被广播到左值的每一个元素上。当右值和左值长度一样,但是形状不一样,就会按照高维优先的方式,将右值的每个元素对应到左值的每个元素上。
约定5:矩阵作为左值,右值必须是一个和左值长度相同的矩阵,或者是一个标量。
在每个涉及数组(矩阵)的操作中,高维优先可以始终保持访问顺序的一致性。
结论
- Matlab矩阵索引从1开始(这个第0条是故意的)。
- Matlab中的矩阵是列优先的,多维数组是高维优先的。
- 访问矩阵时,当某个维限定,比这个维度高的所有维度都应该被限定,计算会更有效率。
- 矩阵作为左值,右值必须是一个和左值长度相同的矩阵,或者是一个标量。
- 在每个涉及数组(矩阵)的操作中,高维优先可以始终保持访问顺序的一致性。
文章标签
|-->Matlab |-->编程 |-->教程 |-->矩阵 |-->入门教程 |-->马特拉波
- 本站总访问量:次
- 本站总访客数:人
- 可通过邮件联系作者:Email大福
- 也可以访问技术博客:大福是小强
- 也可以在知乎搞抽象:知乎-大福
- Comments, requests, and/or opinions go to: Github Repository