NumPy ndarray broadcast - shape(X,)vs(X,1)与(X,Y)一起操作

时间:2016-08-31 16:32:50

标签: python numpy multidimensional-array numpy-broadcasting

我有一个NumPy ndarray形状(32,1024)并保持32个信号测量值,我想将它组合成一个1024个元素的长阵列,每个32个不同的权重。正在使用numpy.average,但我的权重很复杂,average根据抛出结果的总和执行权重的标准化。

看一下平均代码,我意识到我可以通过将权重乘以信号数组然后在第一个轴上求和来完成同样的事情。然而,当我尝试将我的(32,)权重数组乘以(32,1024)信号数组时,我得到一个维度不匹配,因为(32,)不能广播到(32,1024)。如果我将权重数组重新整形为(32,1),那么一切都按预期工作,但这会导致相当丑陋的代码:

avg = (weights.reshape((32, 1)) * data).sum(axis=0)

有人可以解释为什么NumPy不会允许我的(32,)数组广播到(32,1024)和/或建议另一种更简洁的方式来执行加权平均值吗?

1 个答案:

答案 0 :(得分:5)

(X,)(X,Y)形状阵列之间对齐的通用设置

关于为什么(32,)无法广播到(32, 1024)的问题,这是因为形状没有正确对齐。把它放到原理图中,我们有:

weights :         32
data    :  32 x 1024 

我们需要对齐唯一的轴,即weights的第一个轴与data的第一个轴对齐。因此,正如您发现的一种方法是reshape2D,这样我们最终会以单个维度作为第二个轴。这可以通过引入带有None/np.newaxisweights[:,np.newaxis]weights[:,None]的新轴或简单的重塑来实现:weights.reshape(-1,1)。因此,回到原理图,我们将使用修改后的版本:

weights[:,None] :  32 x    1
data            :  32 x 1024

现在,形状是对齐的,我们可以在这两者之间执行任何通用的元素操作,结果示意图看起来像这样 -

weights[:,None] :  32 x    1
data            :  32 x 1024
result          :  32 x 1024

这将广播weights,并且将使用data执行相关的按元素操作,从而产生result

解决我们的具体案例和备选方案

按照上一节的讨论,为了解决我们的逐元素乘法的情况,它将是weights[:,None]*data,然后沿axis=0求和,即 -

(weights[:,None]*data).sum(axis=0)

让我们寻找合适的替代方案!

np.einsum -

可以采用一种简洁直观的方法
np.einsum('i,ij->j',weights,data)

另一种方法是使用np.dot进行矩阵乘法,因为我们将weights的第一个轴丢失到data的第一个轴上,就像这样 -

weights.dot(data)