繁体   English   中英

在numpy数组中沿轴求和

[英]Sum along axis in numpy array

我想了解这个 ndarray.sum(axis=) 是如何工作的。 我知道axis=0 用于列,axis=1 用于行。 但是在 3 个维度(3 个轴)的情况下,很难解释以下结果。

arr = np.arange(0,30).reshape(2,3,5)

arr
Out[1]: 
array([[[ 0,  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, 26, 27, 28, 29]]])

arr.sum(axis=0)
Out[2]: 
array([[15, 17, 19, 21, 23],
       [25, 27, 29, 31, 33],
       [35, 37, 39, 41, 43]])


arr.sum(axis=1)
Out[8]: 
array([[15, 18, 21, 24, 27],
       [60, 63, 66, 69, 72]])

arr.sum(axis=2)
Out[3]: 
array([[ 10,  35,  60],
       [ 85, 110, 135]])

在这个形状为 (2,3,5) 的3 轴阵列示例中,有 3 行和 5 列。 但是如果我从整体上看这个数组,似乎只有两行(都有 3 个数组元素)。

任何人都可以解释这个总和如何在 3 个或更多轴(维度)的数组上工作。

如果要保留尺寸,可以指定keepdims

>>> arr = np.arange(0,30).reshape(2,3,5)
>>> arr.sum(axis=0, keepdims=True)
array([[[15, 17, 19, 21, 23],
        [25, 27, 29, 31, 33],
        [35, 37, 39, 41, 43]]])

否则,您求和的轴将从形状中删除。 跟踪此情况的一种简单方法是使用numpy.ndarray.shape属性:

>>> arr.shape
(2, 3, 5)

>>> arr.sum(axis=0).shape
(3, 5)  # the first entry (index = axis = 0) dimension was removed 

>>> arr.sum(axis=1).shape
(2, 5)  # the second entry (index = axis = 1) was removed

如果需要,您还可以沿多个轴求和(将维度减少指定轴的数量):

>>> arr.sum(axis=(0, 1))
array([75, 81, 87, 93, 99])
>>> arr.sum(axis=(0, 1)).shape
(5, )  # first and second entry is removed

这是解释这一点的另一种方式。 您可以将多维数组视为张量T[i][j][k] ,而 i, j, k 分别代表轴0,1,2

T.sum(axis = 0)数学上等同于:

在此处输入图片说明

类似地, T.sum(axis = 1)

在此处输入图片说明

并且, T.sum(axis = 2)

在此处输入图片说明

所以换句话说,轴将被求和,例如, axis = 0 ,第一个索引将被求和。 如果写在 for 循环中:

result[j][k] = sum(T[i][j][k] for i in range(T.shape[0])) for all j,k

对于axis = 1

result[i][k] = sum(T[i][j][k] for j in range(T.shape[1])) for all i,k

等等。

numpy将 (2,3,5) 数组显示为 2 个 3x5 数组块(3 行 5 列)。 或者称它们为“平面”(MATLAB 会将其显示为 5 个 2x3 块)。

numpy显示也匹配嵌套列表 - 两个子列表的列表; 每个有 3 个子列表。 每个元素的长度为 5 个元素。

在 3x5 2d 情况下,轴 0 沿尺寸3维度求和,从而产生 5 个元素的数组。 英语中的“sum over rows”或“sum沿列”的描述有点含糊。 关注结果、形状的变化以及求和的值,而不是描述。

回到3d案例:

使用axis=0 ,它沿第一个维度求和,有效地将其删除,留下一个 3x5 数组。 0+15=16, 1+16=17 etc

轴 1,压缩尺寸3维,结果为 2x5。 0+5+10=15, etc

轴2,压缩尺寸5维,结果为2x3, sum((0,1,2,3,4))

您的示例很好,因为 3 个维度不同,更容易看出求和过程中消除了哪个维度。

使用 2d 有一些歧义; “行总和” - 这是否意味着行被消除或保留? 使用 3d 没有歧义; 轴=0,你只能删除它,留下其他2。

您指定的轴是有效删除的轴。 因此,给定(2,3,5)的形状,轴 0 给出(3,5) ,轴 1 给出(2,5)等。这扩展到任意数量的维度。

您似乎对 numpy 数组的输出样式感到困惑。 输出的“行”几乎总是最后一个索引,而不是第一个。 例子:

x=np.arange(1,4)
y=np.arange(10,31,10)
z=np.arange(100,301,100)
xy=x[:,None]+y[None,:]

xy
Out[100]: 
array([[11, 21, 31],
       [12, 22, 32],
       [13, 23, 33]])

请注意行上的十位增量,而不是列,即使 y 是第二个索引。

xyz=x[:,None,None]+y[None,:,None]+z[None,None,:]
xyz
Out[102]: 
array([[[111, 211, 311],
        [121, 221, 321],
        [131, 231, 331]],

       [[112, 212, 312],
        [122, 222, 322],
        [132, 232, 332]],

       [[113, 213, 313],
        [123, 223, 323],
        [133, 233, 333]]])

现在行中的百位递增,即使 z 是最后一个索引。 这对初学者来说可能有点违反直觉。

因此,当您执行np.sum(x,index=-1)您将始终对“行”进行求和,如np.array([])格式所示。 查看arr.sum(axis=2)[0,0] ,即0+1+2+3+4=10

将多维数组视为一棵树。 每个维度都是树中的一个级别。 该级别的每个分组都是一个节点。 沿特定轴(例如轴 = 4)的总和意味着将该级别的所有节点合并(覆盖)为单个节点(在其各自的父节点下)。 以该级别的重叠节点为根的子树相互堆叠。 所有重叠节点的值都加在一起。
图片: https : //ibb.co/dg3P3w

使用更简单的 3D 阵列可能更容易查看。 用 1 填充数组后,总和中的数字就是特定维度的总和! 每种情况下的其他两个维度都保持不变。

arr = np.arange(0,60).reshape(4,3,5)
arr
Out[10]: 
array([[[ 0,  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, 26, 27, 28, 29]],

       [[30, 31, 32, 33, 34],
        [35, 36, 37, 38, 39],
        [40, 41, 42, 43, 44]],

       [[45, 46, 47, 48, 49],
        [50, 51, 52, 53, 54],
        [55, 56, 57, 58, 59]]])

arr=arr*0+1

arr
Out[12]: 
array([[[1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1]],

       [[1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1]],

       [[1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1]],

       [[1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1]]])

arr0=arr.sum(axis=0,keepdims=True)
arr2=arr.sum(axis=2,keepdims=True)
arr1=arr.sum(axis=1,keepdims=True)

arr0
Out[20]: 
array([[[4, 4, 4, 4, 4],
        [4, 4, 4, 4, 4],
        [4, 4, 4, 4, 4]]])

arr1
Out[21]: 
array([[[3, 3, 3, 3, 3]],

       [[3, 3, 3, 3, 3]],

       [[3, 3, 3, 3, 3]],

       [[3, 3, 3, 3, 3]]])

arr2
Out[22]: 
array([[[5],
        [5],
        [5]],

       [[5],
        [5],
        [5]],

       [[5],
        [5],
        [5]],

       [[5],
        [5],
        [5]]])

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM