使用广播对 2D 和 3D 数组求和

Summing over 2D and 3D arrays using broadcasting

考虑以下 MWE:

import numpy as np
n=2
N = 6
a = np.random.randint(0,10,size=(N,1))
b = np.random.randint(0,10,size=(N,n))
c = np.random.randint(0,10,size=(n,N,5))

其中 c 例如(随机召回):

array([[[7 5 1 7 0]
  [2 8 2 1 4]
  [0 4 1 7 3]
  [1 6 6 9 6]
  [9 6 0 0 2]
  [9 6 0 6 7]]

 [[0 3 9 0 3]
  [4 7 5 3 8]
  [8 0 6 7 9]
  [5 4 9 5 2]
  [5 6 6 8 7]
  [7 7 2 6 0]]])

形状为 (2,6,5).

我们从中制作:

out = a+b
>>>out
array([[ 9,  7],
       [ 5,  7],
       [ 7,  3],
       [ 9,  9],
       [15, 10],
       [ 8,  9]])

形状为 (6,2).

现在我想做的是:我想将 out 的第一列添加到 c 的第一个矩阵(即矩阵由 c),out 的第二列到 c 的第二列等等(你明白了)。目前,我正在尝试使用广播来做到这一点,但我似乎对自己感到困惑。

我想不使用循环,因为我的实际问题非常大。

期望输出:

>>>np.stack([out[:,i][:,np.newaxis] + c[i] for i in range(2)])

array([[[16, 14, 10, 16,  9],
        [ 7, 13,  7,  6,  9],
        [ 7, 11,  8, 14, 10],
        [10, 15, 15, 18, 15],
        [24, 21, 15, 15, 17],
        [17, 14,  8, 14, 15]],

       [[ 7, 10, 16,  7, 10],
        [11, 14, 12, 10, 15],
        [11,  3,  9, 10, 12],
        [14, 13, 18, 14, 11],
        [15, 16, 16, 18, 17],
        [16, 16, 11, 15,  9]]])

形状为 (2,6,5).

尝试:

out[None, :,:] + c

这会导致以下错误:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-702-d54cfe51ec32> in <module>
----> 1 out[None, :,:] + c

ValueError: operands could not be broadcast together with shapes (1,6,2) (2,6,5)

将不胜感激。

您可以转置并添加一个维度,让广播来完成这项工作:

out.T[...,None]+c 

说明: .T 转置 out (形状 (2,6))并且 [...,None] 添加一个额外的维度作为 out 的最新维度(现在 out 是形状(2,6,1))。最后,广播到 c 的形状 (2,6,5) 将根据需要将所有元素广播到 c 的深度。

要将 out 的列与 c 的“矩阵”“对齐”,您应该转置 out,然后添加一个能够广播的维度,即:

import numpy as np
n=2
N = 6
a = np.random.randint(0,10,size=(N,1))
b = np.random.randint(0,10,size=(N,n))
c = np.random.randint(0,10,size=(n,N,5))

out = a+b

result = out.T[:, :, None] + c

完整性检查:

np.all(result == np.stack([out[:,i][:,np.newaxis] + c[i] for i in range(2)]))
True