3

我有一个 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) 和/或建议一种替代的、更简洁的方法来执行加权平均?

4

1 回答 1

7

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

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

weights :         32
data    :  32 x 1024 

我们需要对齐唯一的轴,即 的第一个轴weights与 的第一个轴对齐data。因此,正如您发现的一种方法是 to reshape2D这样我们最终会得到一个单一维度作为第二个轴。这可以通过使用None/np.newaxis:weights[:,np.newaxis]weights[:,None]简单的 reshape :引入新轴来实现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)
于 2016-08-31T16:36:55.563 回答