没有重复的Numpy广播示例

时间:2017-01-25 23:44:21

标签: python arrays numpy numpy-broadcasting

我试图在不使用np.repeat创建大尺寸的情况下找出执行以下添加操作的好方法。如果使用np.repeat并且添加是最好的解决方案,请告诉我。

我也很担心广播在这种情况下做了什么。基本上我有一个4d矩阵,我想在第一和第二个索引中添加一个2d矩阵,同时在索引0和索引3中执行此操作。

这可以正常使用

a = np.arange(64).reshape((2,4,4,2)).astype(float)
b = np.ones((2,2))
a[:, 0:2, 0:2, : ] += b

这会引发错误。这样做的好方法是什么?

a[:, 0:3, 0:3, :] += np.ones((3,3))

这有效,但不是我想做的事

c = np.arange(144).reshape(3,4,4,3).astype(float)
c[:, 0:3, 0:3, :] += np.ones((3,3))

2 个答案:

答案 0 :(得分:3)

您可以从头开始包含空轴:

a[:, 0:3, 0:3, :] += np.ones((3,3,1))  # 1 broadcasts against any axis

类似的你应该使用:

a[:, 0:2, 0:2, : ] += np.ones((2,2,1))

因为你(可能是无意中)在第三和第四轴上播放了这些。我想你想把它广播到第二和第三,对吗?

此外,您始终可以使用np.expand_dimsaxis=-1添加维度:

>>> np.expand_dims(np.ones((2, 2)), axis=-1).shape
(2, 2, 1)

或使用Nonenp.newaxis切片(它们是等效的!):

>>> np.ones((2, 2))[None, :, :, np.newaxis].shape
(1, 2, 2, 1)

第一个None不是正确广播所必需的,但最后一个是!

在这种情况下,重要的是要提到从最后一个维度开始的numpy广播。因此,如果您有两个数组,则每个维度从最后一个开始必须具有相同的形状,或者其中一个必须为1(如果一个为1则沿着此轴广播!)。这就是a[:, 0:2, 0:2, : ]工作的原因:

>>> a[:, 0:2, 0:2, : ].shape
(2, 2, 2, 2)
>>> b.shape
(2, 2)

所以最后一个维度相等(两个2),倒数第二个维度相等(两个2)。但是:

>>> np.ones((2,2,1)).shape
(2, 2, 1)

最后一个是21所以广播np.ones((2,2,1))的最后一个轴,而第二个和第三个维度相等(所有2)所以numpy使用了元素那里的运作。

答案 1 :(得分:2)

要对齐要添加的数组的轴,我们需要在末尾插入一个新轴,如下所示 -

a[:, 0:3, 0:3, :] += np.ones((3,3))[...,None]

让我们来研究这里的形状:

In [356]: a[:, 0:3, 0:3, :].shape
Out[356]: (2, 3, 3, 2)

In [357]: np.ones((3,3)).shape
Out[357]: (3, 3)

In [358]: np.ones((3,3))[...,None].shape
Out[358]: (3, 3, 1)


Input1 (a[:, 0:3, 0:3, :])        :     (2, 3, 3, 2) 
Input2 (np.ones((3,3))[...,None]) :        (3, 3, 1)

请记住,广播规则规定单例维度(带lengths = 1的维度)将广播到与其他非单例维度的长度匹配。此外,未列出的维度实际上默认长度为1

所以,这是可播放的,现在可以使用。

第2部分:为什么以下有效?

c = np.arange(144).reshape(3,4,4,3).astype(float)
c[:, 0:3, 0:3, :] += np.ones((3,3))

再次研究形状 -

In [363]: c[:, 0:3, 0:3, :].shape
Out[363]: (3, 3, 3, 3)

In [364]: np.ones((3,3)).shape
Out[364]: (3, 3)

Input1 (c[:, 0:3, 0:3, :])  :     (3, 3, 3, 3) 
Input2 (np.ones((3,3)))     :           (3, 3)

再次通过可播放的规则这很好,所以这里没有错误,但结果不是预期的。