【问题标题】:NumPy ndarray broadcasting - shape (X,) vs (X, 1) to operate with (X,Y)NumPy ndarray 广播 - 形状(X,)与(X,1)与(X,Y)一起操作
【发布时间】:2017-01-08 08:20:58
【问题描述】:

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

【问题讨论】:

  • numpy 可以将 (32,) 扩展到 (1, 32)(1024,32);但是您必须授予它将(32,) 扩展为(32,1) 的权限。这避免了在其他情况下的歧义,例如,在将 (32,) 与 (1024,) 相乘时。在我最近的回答中了解更多信息,stackoverflow.com/a/39238203/901925

标签: python numpy multidimensional-array array-broadcasting


【解决方案1】:

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

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

weights :         32
data    :  32 x 1024 

我们需要对齐唯一的轴,即weights的第一个轴与data的第一个轴对齐。因此,正如您所发现的,一种方法是将reshape 转换为2D,这样我们最终会得到一个单一维度作为第二个轴。这可以通过引入带有None/np.newaxis 的新轴:weights[:,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)

【讨论】:

  • 清晰彻底的回答,谢谢。我不知道np.einsum - 虽然它无疑是一种巧妙的方法,但我认为这对于不熟悉语法的人来说并不明显。 np.dot 风格更接近于“恰到好处”并且非常紧凑的东西。
猜你喜欢
  • 2021-06-07
  • 2019-02-19
  • 2012-08-05
  • 2020-06-20
  • 1970-01-01
  • 2014-08-24
  • 2019-05-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多