Python numpy-给定2d矩阵的列和行和
我有这个numpy矩阵(ndarray) 我想计算列和行的和 我知道这是通过分别打电话来完成的Python numpy-给定2d矩阵的列和行和,python,numpy,Python,Numpy,我有这个numpy矩阵(ndarray) 我想计算列和行的和 我知道这是通过分别打电话来完成的 np.sum(mat, axis=0) ### column-wise sums np.sum(mat, axis=1) ### row-wise sums 但我无法理解这两个电话 为什么轴0会一列一列地给我求和 难道不是相反吗 我以为行是轴0,列是轴1 我在这里看到的行为与直觉背道而驰 (但我肯定没关系,我想我只是错过了一些重要的事情) 我只是想在这里找到一些直观的解释 提前感谢。
np.sum(mat, axis=0) ### column-wise sums
np.sum(mat, axis=1) ### row-wise sums
但我无法理解这两个电话
为什么轴0会一列一列地给我求和难道不是相反吗 我以为行是轴0,列是轴1 我在这里看到的行为与直觉背道而驰
(但我肯定没关系,我想我只是错过了一些重要的事情) 我只是想在这里找到一些直观的解释
提前感谢。直观地说,“轴0”从上到下移动,“轴1”从左到右移动。因此,当沿“轴0”求和时,得到列和,沿“轴1”得到行和
沿“轴0”移动时,行数增加。沿着“轴1”移动时,列数会增加。让我们从一维示例开始:
a, b, c, d, e = 0, 1, 2, 3, 4
arr = np.array([a, b, c, d, e])
如果你这样做
arr.sum(0)
输出
10
[ 7 9 11 13 15]
[55 60 65 70 75]
[ 15 40 65 90 115]
这是数组元素的总和
a + b + c + d + e
现在在讨论二维示例之前。让我们澄清一下,在numpy中,两个一维数组的和是按元素进行的,例如:
a = np.array([1, 2, 3, 4, 5])
b = np.array([6, 7, 8, 9, 10])
print(a + b)
输出
10
[ 7 9 11 13 15]
[55 60 65 70 75]
[ 15 40 65 90 115]
现在,如果我们将初始变量改为数组,而不是标量,来创建一个二维数组并进行求和
a = np.array([1, 2, 3, 4, 5])
b = np.array([6, 7, 8, 9, 10])
c = np.array([11, 12, 13, 14, 15])
d = np.array([16, 17, 18, 19, 20])
e = np.array([21, 22, 23, 24, 25])
arr = np.array([a, b, c, d, e])
print(arr.sum(0))
输出
10
[ 7 9 11 13 15]
[55 60 65 70 75]
[ 15 40 65 90 115]
输出与一维示例相同,即数组元素的总和:
a + b + c + d + e
只是现在数组的元素是一维数组,这些元素的总和被应用。在解释结果之前,对于轴=1,让我们考虑横轴=0的符号的另一种表示法,基本上是:
np.array([arr[0, :], arr[1, :], arr[2, :], arr[3, :], arr[4, :]]).sum(0) # [55 60 65 70 75]
也就是说,我们对所有其他不是第一维度的索引进行了完整切片。如果我们换成:
res = np.array([arr[:, 0], arr[:, 1], arr[:, 2], arr[:, 3], arr[:, 4]]).sum(0)
print(res)
输出
10
[ 7 9 11 13 15]
[55 60 65 70 75]
[ 15 40 65 90 115]
我们得到沿轴的和=1的结果。所以总结起来,你总是要对数组中的元素求和。轴将指示这些元素的构造方式。想象一下一维数组:
mat=array([ 1, 2, 3, 4, 5])
其项由mat[0]、mat[1]、
等调用
如果您这样做:
np.sum(mat, axis=0)
它将返回15分钟
在后台,它用mat[0]、mat[1]、mat[2]、mat[3]、mat[4]对所有项目求和。
表示第一个索引(轴=0)
现在考虑二维数组:
mat=array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25]])
当你要求
np.sum(mat, axis=0)
它将再次基于第一个索引(axis=0)对所有项进行求和,并保持所有剩余项不变。这意味着
mat[0][1], mat[1][1], mat[2][1], mat[3][1], mat[4][1]
我给你一笔钱
mat[0][2], mat[1][2], mat[2][2], mat[3][2], mat[4][2]
我会再给你一个等
如果你考虑一个3-D数组,逻辑将是相同的。每个总和将在同一轴(索引)上计算,保持所有剩余部分不变。轴=0上的总和将由以下公式产生:
mat[0][1][1],mat[1][1][1],mat[2][1][1],mat[3][1][1],mat[4][1][1]
mat[2][3][0], mat[2][3][1], mat[2][3][2], mat[2][3][3], mat[2][3][4]
等
轴=2上的总和将由以下公式产生:
mat[0][1][1],mat[1][1][1],mat[2][1][1],mat[3][1][1],mat[4][1][1]
mat[2][3][0], mat[2][3][1], mat[2][3][2], mat[2][3][3], mat[2][3][4]
等
我希望你能理解其中的逻辑。为了让事情在头脑中保持简单,考虑轴=索引在链式索引中的位置,例如在7个数组中的轴=3将是:
mat[0][0][0][this is our axis][0][0][0]
围绕阵列和轴的直觉
我想在这里提供三种直觉
图形直觉 将numpy数组视为n维对象。此n维对象包含以下每个方向的元素 此表示中的轴是张量的方向。因此,2D矩阵只有2个轴,而4D张量有4个轴 给定轴上的总和基本上可以视为该方向上的减少。想象一个三维张量被挤压成平面(二维张量)。轴告诉我们挤压或缩小的方向
物理直觉 Numpy将其数据阵列存储为连续的内存块。在前一个元素之后,每n个字节以顺序方式存储一个元素 (此处引用的图像) 所以如果你的3D阵列看起来像这样- 然后在内存中存储为- 检索一个元素(或元素块)时,NumPy计算它需要遍历多少个
跨步
(字节)才能获得该方向/轴上的下一个元素。因此,对于上面的示例,对于axis=2
它必须遍历8个字节(取决于datatype
),但是对于axis=1
它必须遍历8*4
字节,并且axis=0
它需要8*8
字节
此表示中的轴基本上是给定的跨步
后的下一个元素的序列。考虑下面的数组-< /p>
print(X)
print(X.strides)
在上面的数组中,来自任何元素的56字节后的每个元素都是axis=0中的下一个元素,来自任何元素的8字节后的每个元素都是axis=1。(最后一个元素除外)
求和或在这方面的减少意味着对该跨步序列中的每个元素求和。因此,轴上求和=0意味着我需要求和[0,5,8,0,0,0],[2,0,0,0,0,0],…
轴上求和=1意味着只求和[0214000],[50000],…
逻辑直觉
这种解释与元素分组有关。numpy将其Ndarray存储为组的组的组。。。元素的数量
。元素分组在一起并包含最后一个轴(轴=-1)。然后,在它们上面的另一个分组在它前面创建另一个轴(轴=-2)。最后一个最外层组是轴=0
这是3组2组5个元素
类似地,NumPy数组的形状也由相同的参数确定
1D_array = [1,2,3]
2D_array = [[1,2,3]]
3D_array = [[[1,2,3]]]
...
此表示中的轴是存储元素的组。最外面的组是axis=0,最里面的组是axis=-1