广播失败:如何确定广播的轴心?

时间:2019-07-16 23:43:30

标签: python numpy

我的张量大小为(1000、30、16、16)。我正在就如何对其进行标准化进行实验。我正在尝试对各种情况进行标准化,可能是频率轴等。

以下作品:

a = np.random.rand(1000, 30, 16, 16)
a - a.mean(axis=(0, )) #==> it works
a - a.mean(axis=(0, 1)) #==> successful broadcast
a - a.mean(axis=(0, 1, 2)) #==> works well
a - a.mean(axis=(0, 1, 2, 3)) #==> succesful broadcast of scalar mean to all a values


#Those however fail:
a - a.mean(axis=(2, 3)) 
#OR:
a - a.mean(axis=(0, 2, 3))

我得到:

  

ValueError:操作数不能与形状(1000,30,16,16)(30,)一起广播

在像这样的简单情况下,它似乎成功完成了缺失的轴 (30,16,16)

(16,16)

(16,)

(1,)

但是当缺少的轴位于右侧而不是左侧时失败,例如: (1000,30),并且无法将其广播到(1000,30,16,16)。

要具体说明我的问题,我该如何规定广播的进行方式? 例如,我有(30,),我想将其广播到(1000,30,16,16)

由于无法广播,将引发错误。我有一个 hacky 解决方案,该解决方案可以对轴进行排列并使得(30,)排在最后,以便广播能够正常工作,但是我想知道是否有一种方法可以指示应该如何进行广播。而且,为什么不自动执行此操作?

2 个答案:

答案 0 :(得分:2)

默认情况下,NumPy通过在左侧添加新轴 进行广播。例如,如果数组的形状为(30, 16, 16),则它可以自动广播到形状为(1, 30, 16, 16)。长度为1的新轴可以进一步广播,以匹配其要广播到的阵列所需的任何大小。

这说明了为什么广播在所有这些情况下都有效:

a = np.random.rand(1000, 30, 16, 16)
a - a.mean(axis=(0, )) #==> it works
a - a.mean(axis=(0, 1)) #==> successful broadcast
a - a.mean(axis=(0, 1, 2)) #==> works well
a - a.mean(axis=(0, 1, 2, 3)) #==> succesful broadcast of scalar mean to all a values

在每种情况下,a.mean(...)都会从左侧移出轴,(可能)在右侧移出轴。 因此广播没有问题,可以自动在左侧重新添加新轴。

相反,a - a.mean(axis=(2, 3))失败是因为a.mean(axis=(2,3))的形状为(1000, 30), 并且只能播放(1, 1000, 30)(1, 1, 1000, 30)之类的形状。由于a的形状为(1000, 30, 16, 16),因此从右边开始的最后两个轴的长度是冲突的。

在这种情况下,要成功广播,您需要使用{p>

a - a.mean(axis=(2, 3))[..., np.newaxis, np.newaxis]

a - a.mean(axis=(2, 3))[..., None, None]

现在a.mean(axis=(2, 3))[..., None, None]的形状为(1000, 30, 1, 1),最多可以广播(1000, 30, 16, 16),使其形状与a兼容。


explicitly add new axes通过说来解释广播

  

根据广播规则限制这些数组的尾轴大小,表明它们是兼容的:

    Image  (3d array): 256 x 256 x 3
    Scale  (1d array):             3
    Result (3d array): 256 x 256 x 3

请注意,对齐是通过右对齐形状来完成的。空轴填充为1s。说在左侧添加新轴只是谈论此想法的另一种方式。

答案 1 :(得分:1)

您可以创建要显式广播的其他轴,而不是隐式广播,方法是对要添加的每个轴使用None进行切片。

要广播(30,)至(1000,30,16,16),像这样切片:

a[None,:,None,None]

您会看到第二个轴被:切片,这意味着“所有数据”,其余的轴是None,这意味着“在此处创建一个新的轴进行广播”。

考虑一下,隐式广播最好具有严格的工作规则。想象一下,它可以以此方式自动广播-如果是这样,它将如何广播(30)到(30,30)?这将是模棱两可的。按照当前的规则,它并不是模棱两可的。