我有一个张量的大小(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)
它在广播失败时抛出一个错误。我有一个麻木不仁的解决方案,它使斧头和制造(30,)最后,以便广播工作,但我想知道是否有一个方法来决定如何广播应该做。而且,为什么这不是自动完成的?
发布于 2019-07-16 23:54:58
默认情况下,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),所以从右边的最后两个轴的长度是冲突的。
若要在本例中成功广播,需要在右侧使用添加新的轴
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]有了shape (1000, 30, 1, 1),并且可以广播到(1000, 30, 16, 16)以使其与a的形状兼容。
医生们解释广播
根据广播规则排列这些数组后轴的大小,表明它们是兼容的:
Image (3d array): 256 x 256 x 3
Scale (1d array): 3
Result (3d array): 256 x 256 x 3注意,对齐是通过正确对齐形状来完成的。空轴充满1s。说在左边增加新的轴只是讨论同样的想法的另一种方式。
发布于 2019-07-16 23:49:10
与隐式广播不同,您可以创建用于显式广播的附加轴,方法是对要添加的每个轴进行None切片。
要广播(30,)到(1000,30,16),切片如下:
a[None,:,None,None]您可以看到,第二个轴被:切片,意思是“所有数据”,其余的轴是None,意思是“在这里创建一个用于广播的新轴”。
如果你想一想,这是好的,隐式广播有严格的规则,它如何运作。假设它可以自动以这种方式广播--如果这是真的,它将如何广播(30,30)?这是模棱两可的。就目前的规则而言,它并不含糊不清。
https://stackoverflow.com/questions/57066770
复制相似问题