Numpy: 对Axis的理解
- Axis 就是数组层级
- 设 axis=i,则 Numpy 沿着第 i 个下标变化的方向进行操作
- Axis 的应用
Axis 就是数组层级
要想理解 axis,首先我们先要弄清楚 “Numpy 中数组的维数” 和 “线性代数中矩阵的维数” 这两个概念以及它们之间的关系。在数学或者物理的概念中,dimensions 被认为是在空间中表示一个点所需要的最少坐标个数,但是在 Numpy 中,dimensions 指代的是数组的维数。比如下面这个例子:
1 | >>> import numpy as np |
这个 array 的维数只有 2,即 axis 轴有两个,分别是 axis=0 和 axis=1。如下图所示,该二维数组的第 0 维 (axis=0) 有三个元素 (左图),即 axis=0 轴的长度 length 为 3;第 1 维(axis=1) 也有三个元素(右图),即 axis=1 轴的长度 length 为 3。正是因为 axis=0、axis=1 的长度都为 3,矩阵横着竖着都有 3 个数,所以该矩阵在线性代数是 3 维的(rank 秩为 3)。
因此,axis 就是数组层级。
当 axis=0,该轴上的元素有 3 个 (数组的 size 为 3)
a[0]
、a[1]
、a[2]
当 axis=1,该轴上的元素有 3 个 (数组的 size 为 3)
a[0][0]
、a[0][1]
、a[0][2]
(或者a[1][0]
、a[1][1]
、a[1][2]
)
(或者a[2][0]
、a[2][1]
、a[2][2]
)
再比如下面 shape 为 (3,2,4) 的 array:
1 | >>> b = np.array([[[1,2,3,4],[1,3,4,5]],[[2,4,7,5],[8,4,3,5]],[[2,5,7,3],[1,5,3,7]]]) |
这个 shape(用 tuple 表示)可以理解为在每个轴(axis)上的 size,也即占有的长度(length)。为了更进一步理解,我们可以暂时把多个 axes 想象成多层 layers。axis=0 表示第一层 (下图黑色框框),该层数组的 size 为 3,对应轴上的元素 length = 3;axis=1 表示第二层 (下图红色框框),该层数组的 size 为 2,对应轴上的元素 length = 2;axis=2 表示第三层 (下图蓝色框框),对应轴上的元素 length = 4。
设 axis=i,则 Numpy 沿着第 i 个下标变化的方向进行操作
- 二维数组示例:
比如np.sum(a, axis=1)
,结合下面的数组, a[0][0]
=1、a[0][1]
=2、a[0][2]
=3 ,下标会发生变化的方向是数组的第一维。
我们往下标会变化的方向,把元素相加后即可得到最终结果:
1 | [ |
- 三维数组示例:
再举个例子,比如下边这个np.shape(a)=(3,2,4)
的 3 维数组,该数组第 0 维的长度为 3(黑色框框),再深入一层,第 1 维的长度为 2(红色框框),再深入一层,第 2 维的长度为 4(蓝色框框)。
如果我们要计算np.sum(a, axis=1)
,在第一个黑色框框中,
下标的变化方向如下所示:
所以,我们要把上下两个红色框框相加起来
按照同样的逻辑处理第二个和第三个黑色的框框,可以得出最终结果:
所以,依然是我们前边总结的那一句话,设 axis=i,则 Numpy 沿着第 i 个下标变化的方向进行操作。
- 四维数组示例:
比如下面这个巨复杂的 4 维数组,
1 | >>> data = np.random.randint(0, 5, [4,3,2,3]) |
当 axis=0 时,numpy 沿着第 0 维的方向进行求和,也就是第一个元素值 = a0000+a1000+a2000+a3000=11, 第二个元素 = a0001+a1001+a2001+a3001=5,同理可得最后的结果如下:
1 | >>> data.sum(axis=0) |
当 axis=3 时,numpy 沿着第 3 维的方向进行求和,也就是第一个元素值 = a0000+a0001+a0002=5, 第二个元素 = a0010+a0011+a0012=7,同理可得最后的结果如下:
1 | >>> data.sum(axis=3) |
Axis 的应用
例如现在我们收集了四个同学对苹果、榴莲、西瓜这三种水果的喜爱程度进行打分的数据(总分为 10),每个同学都有三个特征:
1 | >>> item = np.array([[1,4,8],[2,3,5],[2,5,1],[1,10,7]]) |
每一行包含了同一个人的三个特征,如果我们想看看哪个同学最喜欢吃水果,那就可以用:
1 | >>> item.sum(axis = 1) |
可以大概看出来同学 4 最喜欢吃水果。
如果我们想看看哪种水果最受欢迎,那就可以用:
1 | >>> item.sum(axis = 0) |
可以看出基本是榴莲最受欢迎。
低维度axis理解
一维数组
对于一维数组,只有一个轴:
axis=0
:这是唯一的轴,代表数组的唯一维度。
二维数组
二维数组(例如矩阵)有两个轴:
axis=0
:代表行。对于操作而言,这意味着会==沿着列的方向==进行,即跨越不同的行。axis=1
:代表列。操作将沿着行的方向进行,即跨越不同的列。
三维数组
对于三维数组,有三个轴:
axis=0
:可以想象为不同的==”页”==或”深度层”。axis=1
:在给定的页中,沿着”行”的方向。axis=2
:在给定的页中,沿着”列”的方向。
以三维数组为例,我们可以将其视为一个数据块,这个数据块由多个二维矩阵(页)堆叠而成。每个”页”是一个二维数组,有其自己的行和列。在这种情况下:
axis=0
表示沿着堆叠的方向,或者说是”深度”方向。==操作将跨越不同的页==。axis=1
表示在每个单独的页中,沿着行的方向。这意味着操作将在每页的所有行上进行,但是在同一页内。axis=2
表示在每个单独的页中,沿着列的方向。操作将在每页的所有列上进行,但是在同一页内。
假设我们有一个三维数组 arr
,它由 2 个 3x4 的二维数组(页)组成,形状为 (2, 3, 4)
。这意味着我们有 2 页,每页 3 行 4 列。
1 | import numpy as np |
- 使用
axis=0
对数组进行求和:np.sum(arr, axis=0)
会将两个 3x4 的矩阵对应位置的元素相加,结果是一个 3x4 的矩阵。 - 使用
axis=1
对数组进行求和:np.sum(arr, axis=1)
对每个二维数组(页)的所有行进行求和,结果是每页一个行向量,形状变为(2, 4)
。 - 使用
axis=2
对数组进行求和:np.sum(arr, axis=2)
对每个二维数组(页)的所有列进行求和,结果是每页一个列向量,形状变为(2, 3)
。