python numpy库之ndarray对象 关于轴(axis)和形状(shape)的解读,以存储、二维数组、高维数组的视角进行分别解读

python numpy库之ndarray对象 关于轴(axis)和形状(shape)的解读,以存储、二维数组、高维数组的视角进行分别解读,第1张

python numpy库之ndarray对象 关于轴(axis)和形状(shape)的解读,以存储、二维数组、高维数组的视角进行分别解读

相信第一次学习使用ndarray对象的同学都会对轴和形状的概念不太理解,尤其对于形状(shape),可能一开始觉得理解了,但当遇到三维及以上维度数组时又会发现不太理解了,没有关系,本文将会解答这些疑惑。

首先我们来讲一下ndarray对于数组的存储/读取的逻辑,这一点对实际使用并无影响。因为计算机怎么存就会怎么读,编程人员获取的结果都是一样的。但这会对理解轴这个概念有所帮助。
ndarray对于数组的存储方式有两类,分别是C/C++语言模式(即行优先)和Fortran语言模式(即列优先),分别用order属性的’C’ 和’F’表示,默认以C语言模式存储。
下面以C模式为例:如果我们想要创建一个多维数组,一般可以采用嵌套的数组表示,如[[[1, 2],[3,5],[2,4]],[[2,4],[4,6],[2,9]],[[3,5],[1,3],[34,12]]],这是一个三维数组。根据行优先的存储模式,可以知道,计算机内存存储时的实际顺序便是上方数组的书写顺序。三维数组包含列、行、页三个维度。计算机存储三维数组的过程便是先存列,再存行,最后存页。等等,不是说好的行优先吗,为什么说先存列。其实行优先只是便于我们理解的一种描述,即存完一行再存下一行,而不是存完一列再存下一列。实际上从数组角度来看,存放时先放的是第0行第0列,然后是第0行第1列,第0行第2列,第0行存放完才轮到第1行第0列,以此类推。可以发现先发生改变的或者说先出现维度概念的是列,之后才是行。

当你熟悉了ndarray对象的使用后,你就可以完全摒弃到行列这种容易混淆理解的说法,而是以轴(axis)来进行理解和表达,因为对于高维数组是不存在真正的行和列的,只有轴(axis)是始终有意义的表达方式。当然为了便于初学者理解,下文仍使用行、列的描述,以展现它们和轴的关系。
**

一、轴(axis)

**
首先,对于ndarray,轴和维度的概念是通用的。为了便于理解,我们以三维数组为例。我们都知道一个三维数组包含列、行、页三个维度。再来看axis,对一个三维数组,它包括0、1、2三个轴(即axis=0、1、2)。这里0轴(axis=0)代表的就是页这一维,1轴代表行这一维,2轴代表列这一维。也就是说axis越小,其代表的层次越高。是不是发现轴的顺序恰好和计算机以默认模式——C模式存储数组时的顺序相同,即先2轴(列),再1轴(行),最后0轴(页)。
需要注意的是,即便采用F模式存储,也不会改变轴、形状的顺序,因为C模式才是默认方式,计算机默认以C模式顺序对轴、形状进行定义。

再以二维数组为例,来详细解释何为0轴、1轴,通过这个例子你将明白为何对axis=0进行sum,是将列向量进行加和。对于轴(axis)的概念,我们都知道笛卡尔坐标系,它包括x、y、z三个轴,在各个轴上都有坐标,对于数组的轴也是如此。

一个二维矩阵的轴就是如上图所示,为了便于区分1轴和0轴的坐标,采用的不同的表示方法。因为0轴处于列这个方向上,所以我们说0轴代表列,1轴同理。再看0轴上的坐标,0、1、2便代表三个坐标,指数组的第0行,第1行和第2行。所以我们在对axis=0进行sum时,实际是是对0轴的各个坐标代表的数据进行加和,也就是坐标0+1+2,即第0行+第1行+第2行,所以得到的是一个1行3列的矩阵。对axis=1进行sum也是同理,这样是不是就更好理解了一些呢。
**

二、形状(shape)

**
解释完了轴,形状(shape)就更好解释了。初学者接触二维数组比较多,可能下意识的认为(m,n)代表m行n列是自然而然的,因为这个符合线性代数对于矩阵行列的描述顺序。但实际上由于ndarray中默认行优先,正确的逻辑应该是n列m行(行优先为何是n列m行而不是m行n列的解释请看本文整篇的第三小段)。是不是有点迷惑这两种表达有什么区别,别着急,下面以高维数组为例,大家就会明白了。
首先要明确,shape是一个元组,它里面存放的元素便是各个维度(轴)的长度,可以通过shape[i]获取第i维的参数。
为了便于理解,还是以三维数组[[[1, 2],[3,5],[2,4],[5,3]],[[2,4],[4,6],[2,9],[4,2]],[[3,5],[1,3],[34,12],[23,13]]]为例,很容易知道他是4行2列3页的。那它的shape你知道是什么吗,是不是下意识的认为是(4,2,3);或者你理解了前一段所说的n列m行,而认为是(2,4,3),即(列,行,页)。但你只要运行一下程序就会发现他的shape是(3,4,2),即(页,行,列)。
实际上因为是shape内元素的排列顺序是按(轴)axis从小到大的顺序排列的。也就是先是0轴(axis=0)、再是1轴(axis=1)、最后是2轴(axis=2)。简单来说,shape就相当于(页,行,列)这样维度排列顺序。结合之前对于轴的解释,你就不难理解shape了。
总结一下,就是无论是axis(轴)还是shape(形状)都是按照层次从高到低的顺序排列的。这里的层次只是一个比喻,层次越高的轴,每改变一个单位量的坐标,存储空间内的地址(按C语言的说法,就是指针)移动越多。

最后再推荐一个NumPy库各种方法信息的查询网站https://docs.scipy.org/doc/numpy-1.10.1/index.html

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5595381.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存