在使用Numpy进行矩阵运算时,常常会需要选择对哪一轴(axis)进行求平均值等操作,笔者由于对矩阵不是很敏感,因此很多时候还是需要通过测试的笨办法来确定参数设置到底是axis=0还是axis=1。但是这样终归效率很低,因此在之前的一些测试经验上,总结出了识别Numpy矩阵中axis较为实用的一些规律。
首先从最简单的二维矩阵开始:
x = np.array([
[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
])
首先查看axis=0时的均值
x.mean(axis=0)
结果为
array([2.5, 2.5, 2.5])
是对从最大的括号往里的第一级元素(即[1,1,1]这样的整体)进行了平均,得到的平均后的结果为一个3元素的矩阵,相当于是按列进行了平均;
再查看axis=1时的均值
x.mean(axis=1)
结果为
array([1., 2., 3., 4.])
是对从里往外第二级括号内的元素进行了平均,得到一个4元素的矩阵,相当于是按行进行了平均。
对于二维矩阵来说,如果是死记硬背的话,那么就有如下的结论:
axis = 0 :按列平均
axis = 1 :按行平均
但是如果Numpy矩阵是更高维度的,那么这样死记硬背的方法可能就不太实用了。下面以三维的情况为例,简单阐述一下笔者对于Numpy矩阵操作时指定axis规律的理解。
x = np.array([
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]],
[[2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2]],
[[3, 3, 3, 3], [3, 3, 3, 3], [3, 3, 3, 3], [3, 3, 3, 3], [3, 3, 3, 3]]
])
上面的代码中,x是一个3维矩阵,通过Numpy中提供的.shape属性来查看矩阵的形状:
x.shape
(3, 5, 4)
可以看到,x是一个形状的矩阵,而接下来要测试的axis分别取0、1、2时的输出,与矩阵的形状有很大关系。
首先给出axis分别取0、1、2时,对矩阵求均值的结果,以及相应的矩阵形状:
>> x.mean(axis=0)
array([[2., 2., 2., 2.],
[2., 2., 2., 2.],
[2., 2., 2., 2.],
[2., 2., 2., 2.],
[2., 2., 2., 2.]])
shape = (5, 4)
>> x.mean(axis=1)
array([[1., 1., 1., 1.],
[2., 2., 2., 2.],
[3., 3., 3., 3.]])
shape = (3, 4)
>> x.mean(axis=2)
array([[1., 1., 1., 1., 1.],
[2., 2., 2., 2., 2.],
[3., 3., 3., 3., 3.]])
shape = (3, 5)
在上述三种不同的axis参数设置下,得到的均值矩阵的形状具有一定的规律。对于axis=0的情况,结果shape=(5,4),相较于原矩阵(3,5,4)去除了shape[0]的3,代表结果中的每个值是由原来的3个值平均得到;axis=1的结果shape=(3,4),相较于原矩阵去除了shape[1]=5,代表结果中的每个值是由原来的5个值平均得到;axis=2的结果shape=(3,5),相较于原矩阵去除了shape[2]=4,代表结果中的每个值是由原来的4个值平均得到。
因此,对于求均值操作,设置axis的规律为:
先写出原矩阵的shape,axis=k,就去掉shape中的第k+1个元素,剩下的元素组成了结果矩阵的形状,矩阵中每个元素都是由原来的shape[k]个元素平均得到。
下面再来看一下具体的平均操作:
对于axis=0的情况,从最外层括号往内看一层,每个被平均的元素形式为
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
从上到下一共三个元素被平均,位置相加,最终得到5x4的结果中所有元素值均为2;
对于axis=1的情况,从最外层括号往内看两层,每个被平均的元素形式为
[1, 1, 1, 1]
在axis=0的基础上,每个最外层维度中一共包含5个[1, 1, 1, 1]形式的元素,对其进行平均,最终得到了3x4的结果;
对于axis=2的情况,从最外层括号往内看三层,每个被平均的元素形式为
1
同上,在axis=1的基础上,每个第二层维度中一共包含4个1形式的元素,对其进行平均,最终得到3x5的结果。