天天看点

《MATLAB神经网络超级学习手册》——2.2 MATLAB中的数组

本节书摘来自异步社区《matlab神经网络超级学习手册》一书中的第2章,第2.2节,作者:matlab技术联盟 , 刘冰 , 郭海霞著,更多章节内容可以访问云栖社区“异步社区”公众号查看

matlab神经网络超级学习手册

matlab中数组可以说无处不在,任何变量在matlab中都是以数组形式存储和运算的。按照数组元素个数和排列方式,matlab中的数组可以分为以下几种。

没有元素的空数组(empty array)。

只有一个元素的标量(scalar),它实际上是一行一列的数组。

只有一行或者一列元素的向量(vecor),分别叫做行向量和列向量,也统称为一维数组。

普通的具有多行多列元素和二维数组。

超过二维的多维数组(具有行、列、页等多个维度)。

按照数组的存储方式,matlab中的数组可以分为:普通数组和稀疏数组(常称为稀疏矩阵)。稀疏矩阵适用于那些大部分元素为0,只有少部分非零元素的数组的存储。主要是为了提高数据存储和运算的效率。

2.2.1 数组的保存和装载

许多实际应用中的数组都是很庞大的,而且当操作步骤较多,不能在短期内完成,需要多次分时进行时,这些庞大的数组的保存和装载就是一个重要问题了,因为每次在进行操作前对数组进行声明和赋值,需要很庞大的输入工作量,一个好的解决方法是将数组保存在文件中,每次需要时进行装载。

matlab中提供了内置的把变量保存在文件中的方法,最简单易用的是将数组变量保存为二进制的.mat文件,用户可以通过save命令将工作区中指定的变量存储在.mat文件中。

(1)save命令的一般语法如下。

其作用是把var1 var2…varn指定的工作区变量存储在filename指定名称的.mat文件中。

通过save存储到.mat文件中的数组变量,在使用前可以用load命令装载到工作区。

(2)load命令的一般语法如下。

其作用是把当前目录下存储在filename.mat文件中的var1 var2…varn指定的变量装载到matlab工作区中。

2.2.2 数组索引和寻址

数组操作中最频繁遇到的就是对数组的某个具体位置上的元素进行访问和重新赋值。这涉及定位数组中元素的位置,也就是数组索引和寻址的问题。

matlab中数组元素的索引方式包括数字索引和逻辑索引两类。

1.数字索引方式

matlab中,普通二维数组元素的数字索引方式又可以分为两种:双下标(也叫全下标)索引和单下标索引。

双下标索引方式,顾名思义,就是用两个数字(自然数)来定位元素的位置。实际上就是用一个有序数对来表征元素位置,第一个数字指定元素所在的行位置,第二个数字指定元素所在的列。两个表示元素位置的索引数字之间用逗号分隔,并用圆括号括起来,紧跟在数组变量名后,就可以访问此数字索引指定的位置上的数组元素了。

例如,对于3行2列的数组a,a(3,1)表示数组a的第3行第1列的元素,a(1,2)表示数组a的第1行第2列的元素。

相应地,单下标索引方式就是用一个数字来定位数组元素。实际上,单下标索引和双下标索引是一一对应的,对一个已知尺寸的数组,任一个单下标索引数字都可以转换成确定的双下标索引。对于m行n列的数组a,a(x,y)实际上对应于a((y-1) m+x)。

例如,对于3行2列的数组a,a(3,1)用单下标索引表示就是a(3),a(1,2)用单下标索引表示就是a(4)。

matlab中单下标索引方式实际上采用了列元素优先的原则,即对于m行n列的数组a,第一列的元素的单下标索引依次为a(1),a(2),a(3),…,a(m)。第二列的元素的单下标索引依次为a(m+1),a(m+2),a(m+3),…,a(2m),依此类推。

这两种数字索引方式中的数字索引也可以是一个数列,从而实现访问多个数组元素的目的,这通常可以通过运用冒号或一维数组来实现。

【例2-5】数组元素的索引与寻址。

解:在command window窗口输入以下命令。

通过例题可以看到,利用下标索引的方法,用户可以访问特定位置上的数组元素的值,或者对特定位置的数组元素重新赋值。

2.单下标索引和双下标索引的转换

单下标索引和双下标索引之间,可以通过matlab提供的函数进行转换。

把双下标索引转换为单下标索引,需要用sub2ind命令,其语法如下。

其中siz是一个1行2列的数组,指定转换数组的行列尺寸,一般可以用size(a)来表示:i和j分别是双下标索引中的两个数字;ind则为转换后的单下标数字。

把单下标索引转换为双下标索引,需要用ind2sub命令,其语法如下。

各变量意义同上。

【例2-6】单-双下标转换。

解:在命令窗口输入以下命令。

可以看到,sub2ind函数和ind2sub函数实现了单-双下标的转换,需要注意的是,ind2sub函数需要指定两个输出参数的接收变量。但由于matlab中小写字母i,j默认是用作虚数单位,因此最好是不用小写字母i,j来接收转换后的下标数字。

3.逻辑索引方式

除了这种双下标和单下标的数字索引外,matlab中访问数组元素,还可以通过逻辑索引的方式,通常是通过比较关系运算产生一个满足比较关系的数组元素的索引数组(实际上是一个由0,1组成的逻辑数组),然后利用这个索引数组来访问原数组,并进行重新赋值等操作。

【例2-7】逻辑索引。

2.2.3 数组的扩展和裁剪

在许多操作过程中,需要对数组进行扩展或剪裁,数组扩展是指在超出数组现有尺寸的位置添加新元素;裁剪是指从现有数据中提取部分,产生一个新的小尺寸的数组。

1.array editor(变量编辑器)

array editor是matlab提供的对数组进行编辑的交互式图形界面工具。双击matlab默认界面下工作区面板下的某一变量,都能打开array editor,从而进行数组元素的编辑。

array editor界面类似于电子表格界面,每一个单元格就是一个数组元素。当单击超出数组当前尺寸的位置的单元格,并输入数据赋值时,实际上就是在该位置添加数组元素,即进行了数组的扩展操作,如图2-2所示。

《MATLAB神经网络超级学习手册》——2.2 MATLAB中的数组

通过鼠标双击workspace窗口下的2行2列的数组变量a,打开数组a的编辑器界面,如图2-2所示。

在其他位置单击鼠标或者按enter键,都可以使当前扩展操作即刻生效。如图2-3所示,在第6行第6列的位置单击单元格并输入数值2,数组a被扩展为6行6列的数组,原有元素不变,在第6行第6列的位置赋值为2,其他扩展的位置上元素被默认赋值为0。

《MATLAB神经网络超级学习手册》——2.2 MATLAB中的数组

通过array editor也可以裁减数组,这主要是对数组行、列的增加或删除操作,该操作需要通过鼠标右键菜单来实现。在array editor中单击某单元格后,单击鼠标右键,弹出图2-4所示菜单。

《MATLAB神经网络超级学习手册》——2.2 MATLAB中的数组

在图2-4所示的菜单中,选择删除子菜单“delete…”,就可以指定删除当前数组中选定位置元素所在的整行或者整列。图2-5所示为删除第2行数据之后的数组a。

提示:

如果想删除数组中单独一个值,可以选择图2-4中的“cut”命令。

《MATLAB神经网络超级学习手册》——2.2 MATLAB中的数组

图形用户界面的array editor使用简单,但如果对数组的扩展或裁剪操作实际比较复杂时,通过array editor实现是比较繁琐低效的。

2.数组扩展的cat函数

matlab中可以通过cat系列函数将多个小尺寸数组按照指定的连接方式,组合成大尺寸的数组。这些函数包括:cat,horzcat和vertcat。

cat函数可以按照指定的方向将多个数组连接成大尺寸数组。其基本语法格式如下。

c=cat(dim,a 1,a 2,a 3,a 4,…),dim用于指定连接方向,对于两个数组的连接,cat(1,a ,b)实际上相当于[a ;b],近似于把两个数组当作两个列元素连接。

horzcat(a 1,a 2,…)是水平方向连接数组,相当于cat(a 1,a 2,…);vercat(a 1,a 2,…)是垂直方向连接数组,相当于cat(1,a 1,a 2,…)。

不管哪个连接函数,都必须保证被操作的数组可以被连接,即在某个方向上尺寸一致,如horzcat函数要求被连接的所有数组都具有相同的行数,而vercat函数要求被连接的所有数组都具有相同的列数。

【例2-8】通过cat函数扩展数组。

解:在commond window窗口输入以下命令。

3.块操作函数

matlab中还有通过块操作实现数组扩展的函数。

(1)数组块状赋值函数repmat。

repmat(a,m,n)可以将a行b列的元素a当作“单个元素”,扩展出m行n列个由此“单个元素”组成的扩展数组,实际上新产生的数组共有m·a行,n·b列。

【例2-9】使用块状复制函数repmat。

(2)对角块生成函数blkdiag。

blkdiag(a,b,…)将数组a,b等当作“单个元素”,安排在新数组的主对角位置,其他位置用零数组块进行填充。

【例2-10】使用对角块生成函数blkdiag。

(3)块操作函数kron。

kron(x,y)把数组y当作一个“元素块”,先复制扩展出size(x)规模的元素块,然后每一个块元素与x的相应位置的元素值相乘。

例如,对2行3列的数组x和任意数组y,kron(x,y)返回的数组相当于[x(1,1) ·y x(1,2)· y x(1,3)·y ; x(1,3) ·y x(2,2)· y x(2,3) ·y]。

【例2-11】使用块操作函数kron。

4.索引扩展

索引扩展是对数组进行扩展中最常用也最易用的方法。前面讲到索引寻址时,其中的数字索引有一定的范围限制,比如m行n列的数组a,要索引寻址访问一个已有元素,通过单下标索引a(a)访问就要求a<=m,b<=n,因为a只有m行n列。

但索引扩展中使用的索引数字,就没有这些限制;相反,必然要用超出上述限制的索引数字,来指定当前数组尺寸外的一个位置,并对其进行赋值,以完成扩展操作。

通过索引扩展,一条语句只能增加一个元素,并同时在未指定的新添位置上默认赋值为0,因此,要扩展多个元素就需要组合运用多条索引扩展语句,并且经常也要通过索引寻址修改特定位置上被默认赋值为0的元素。

【例2-12】索引扩展。

通过例2-12可见,组合应用索引扩展和索引寻址重新赋值命令,在数组的索引扩展中是经常会遇到的。

5.通过冒号操作符裁剪数组

相对于数组扩展这种放大操作,数组的裁剪就是产生新的子数组的缩小操作,从已知的大数据集中挑出一个子集合,作为新的操作对象,这在各种应用领域都是常见的。

matlab中裁剪数组,最常用的就是冒号操作符,实际上,冒号操作符实现裁剪功能时,其意义和冒号用于创建一维数组的意义是一样的,都是实现一个递变效果。

例如,从100行100列的数组a中挑选偶数行偶数列的元素,相对位置不变的组成50行50列的新数组b,只需要通过b=a(2:2:100,2:2:100)就可以实现,实际上这是通过数组数字索引实现了部分数据的访问。

更一般的裁剪语法如下。

表示提取数组a的a 1,a 2,a 3,…等行,b 1,b 2,b 3,…等列的元素组成子数组b。

此外,冒号还有一个特别的用法。当通过数字索引访问数组元素时,如果某一索引位置上不是用数字表示,而是用冒号代替,则表示这一索引位置可以取所有可以取到的值。例如对5行3列的数组a,a(3,:)表示取a的第三行所有元素(从第1行到第3列),a(:,2)表示取a的第二列的所有元素(从第1行到第5行)。

【例2-13】数组裁剪。

6.数组元素删除

通过部分删除数组元素,也可以实现数组的裁剪,删除数组元素很简单,只需要对该位置元素赋值为空方括号([])即可。一般配合冒号,将数组的某些行、列元素删除。但是注意,进行删除时,索引结果必须是完整的行或完整的列,而不能是数组内部的块或单元格。

【例2-14】数组元素删除。

通过例2-14可见,数组元素的部分删除是直接在原始数组上进行的操作,在实际应用中,要考虑在数组元素删除前要不要先保存一个原始数组的拷贝,避免不小心造成对原始数据的破坏。另外,单独的一次删除操作只能删除某些行或某些列,因此一般需要通过两条语句才能实现行列两个方向的数组元素删除。

matlab中有大量内部函数可以对数组进行改变形状的操作,包括数组转置,数组平移和旋转,以及数组尺寸的重新调整。

2.2.4 数组形状的改变

1.数组的转置

matlab中进行数组转置最简单的是通过转置操作符(’)。需要注意以下几个方面。

(1)对于有复数元素的数组,转置操作符(’)在变化数组形状的同时,也会将复数元素转化为其共轭复数。

(2)如果要对复数数组进行非共轭转置,可以通过点转置操作符(.’)实现。

(3)共轭和非共轭转置也可以通过matlab函数完成,transpose实现非共轭转置,功能等同于点转置操作符(.’):ctranspose实现共轭转置,功能等同于转置操作符(’)。当然,这4种方法对于实数数组转置结果是一样的。

【例2-15】数组转置。

实际使用中,由于操作符的简便性,经常会使用操作符而不是转置函数来实现转置。但是在复杂的嵌套运算中,转置函数可能是唯一的可用方法。所以,两类转置方式读者都要掌握。

2.数组翻转

matlab中数组翻转的函数见表2-7。

《MATLAB神经网络超级学习手册》——2.2 MATLAB中的数组

【例2-16】数组翻转。

3.数组尺寸调整

改变数组形状,还有一个常用的函数reshape,它可以把已知数组改变成指定的行列尺寸。

对于m行n列的数组a,b=reshape(a,a,b)可以将其调整为a行b列的尺寸,并赋值为变量b,这里必须满足m·n=a ·b。在尺寸调整前后,两个数组的单下标索引不变,即a(x)必然等于b(x),只要x是符合取值范围要求的单下标数字。也就是说,按照列优先原则把a和b的元素排列成一列,那结果必然是一样的。

【例2-17】数组尺寸调整。

2.2.5 数组运算

本节介绍数组的各种数学运算。

1.数组—数组运算

最基本的就是数组和数组的加(+)、减(-)、乘(*)、乘方(^)等运算。要注意,数组的加、减,要求参与运算的两个数组具有相同的尺寸,而数组的乘法要求第一个数组的列数等于第二个数组的行数。

乘方运算在指数n为自然数时相当于n次自乘,这要求数组具有相同的行数和列数。关于指数为其他情况的乘方,本节不作讨论,读者可以参考有关高等代数书籍。

【例2-18】使用数组—数组运算。

数组除法实际上是乘法的逆运算,相当于参与运算的一个数组和另一个数组的逆(或伪逆)数组相乘。matlab中数组除法有左除(/)和右除()两种。

a/b相当于a ·inv(b)或a ·pinv(b)。

a b相当于inv (a)· b或pinv(a)· b。

其中inv是数组求逆函数,仅适用于行列数相同的方形数组(线性代数中,称为方阵);pinv是求数组广义逆的函数。关于逆矩阵和广义逆矩阵的知识,请读者参考有关高等代数书籍。

【例2-19】使用数组除法。

2.点运算

前面讲到的数组乘、除、乘方运算,都是专门针对数组定义的运算。在有些情况下,用户可能希望对两个尺寸相同的数组进行元素对元素的乘、除,或者对数组的逐个元素进行乘方,这就可以通过点运算实现。

a. *b,就可以实现两个同样尺寸的数组a和数组b对于元素的乘法,同样地,a./b或a. b实现元素对元素的除法,a .^n实现对逐个元素的乘方。

【例2-20】使用点运算。

特别要强调的是,许多matlab内置的运算函数,如sqrt,exp,log,sin等,都只能对数组进行逐个元素的相应运算。至于专门的数组的开方、指数等运算,都有专门的数组运算函数。

3.专门针对数组的运算函数

matlab中,专门针对数组的运算函数一般末尾都以m结尾(m代表matirx),如sqrtm和expm等,这些运算都是特别定义的数组运算,不同于针对单个数值的常规数学运算。这几个函数都要求参与运算的数组是行数和列数相等的方形数组。具体的运算方式请参考高等代数方面的书籍。

【例2-21】使用数组运算函数。

2.2.6 数组的查找

matlab中数组查找只有一个函数find。它能够查找数组中的非零元素并返回其下标索引。find配合各种关系运算和逻辑运算,能够实现很多查找功能。find函数有两种语法形式。

a=find(a)返回数组a中非零元素的单下标索引。

[a,b]=find(a)返回数组a中非零元素的双下标索引方式。

实际应用中,经常通过多重逻辑嵌套产生逻辑数组,判断数组元素是否符合某种比较关系,然后用find函数查找这个逻辑数组中的非零元素,返回符合比较关系的元素的索引,从而实现元素访问。find用于产生索引数组,过度实现最终的索引访问,因此经常不需要直接指定find函数的返回值。

【例2-22】使用数组查找函数find。

例2-22分步展示了find最常见用法的具体使用过程。

首先通过rand函数创建了待操作的随机数组a,然后通过比较运算a>0.3和a<0.5返回分别满足某一比较关系的逻辑数组。在这些逻辑数组中,1代表该位置元素复合比较关系,0则代表不符合比较关系。

然后通过逻辑运算(&)可以产生同时满足两个比较关系的逻辑数组,find操作这个逻辑数组,返回数组中非零元素的下标索引(本例中返回单下标索引),实际上就是返回原数组中符合两个比较关系的元素的位置索引,然后利用find返回的下标索引就可以寻址访问原来数组中符合比较关系的目标元素。

2.2.7 数组的排序

数组排序也是常用的数组操作,经常用在各种数据分析和处理中,matlab中的排序函数是sort。

sort函数可以对数组按照升序或降序进行排列,并返回排序后的元素在原始数组中的索引位置,sort函数有多种应用语法格式,都有重要的应用,见表2-8。

《MATLAB神经网络超级学习手册》——2.2 MATLAB中的数组

可以看到,sort都是对单独的一行或一列元素进行排序。即使对于二维数组,也是单独对每一行每一列进行排序,因此返回的索引只是单下标形式,表征排序后的元素在原来行或列中的位置。

【例2-23】数组排序。

通过例2-23可见,数组排序函数sort返回的索引,是表示了在排序方向上排序后元素在原数组中的位置。对于一维数组,这就是其单下标索引,但对二维数组,这只是双下标索引中的一个分量,因此不能简单地通过这个返回的索引值寻址产生排序的二维数组。

当然,利用这个索引结果,通过复杂一点的方法也可以得到排序数组,如例2-23中,就可以通过a(j)来产生排序数组,这种索引访问,一般只用在对部分数据的处理上。

2.2.8 高维数组的降维操作

【例2-24】使用squeeze命令来撤销“孤维”,使高维数组进行降维。

继续阅读