使用np.transpose使数组广播



我有一个广播错误,如下所示:

ValueError:操作数无法与形状(84,36((84,36210,45(一起广播

有办法解决这个问题吗?我试着使用np.transpose((在索引周围移动,以便遵守广播规则,但不知何故,我得到的答案不再正确。np.transpose((在这里到底做什么?

有多种方法可以进行广播。

使用转置

较长的方式是您尝试使用transpose的方式。这里,由于array a只有2个维度(它是最后2个维度(,所以您也可以将array b的前2个维度设置为最后2个维-

a = np.random.random((84,36))
b = np.random.random((84,36,210,45))
c = b.transpose(2,3,0,1) + a  #(210, 45, 84, 36) + (84, 36)
c = c.transpose(2,3,0,1)      #transpose back to (84,36,210,45)
c.shape
(84, 36, 210, 45)

这里要澄清的是,b.transpose(2,3,0,1)意味着转置4D阵列,使得现在的形状是第2、第3、第0和第1维度。含义,来自(84, 36, 210, 45)->(210, 45, 84, 36)。这里更清楚。


通过添加轴进行标准广播

标准的方法,更有用的方法,是向array a添加2个维度。所以现在,两个阵列共享前两个维度进行广播。

c = a[..., None, None] + b #(84,26,1,1) + (84, 36, 210, 45)
c.shape
(84, 36, 210, 45)

为了在这里澄清,a[..., None, None]添加了2个新轴,并将形状为(84, 26)的2D张量转换为形状为(84,26,1,1)的4D张量。这里更清楚。

最后,为了证明这两种方法是等价的,你可以这样检查-

np.all((b.transpose(2,3,0,1) + a).transpose(2,3,0,1) == a[...,None, None] + b)
True

大型阵列的基准测试-

  1. 转座子法-1.88 s±977 ms/循环(7次运行的平均值±标准偏差,每次1个循环(
  2. 标准广播-每个循环1.25 s±156 ms(7次运行的平均值±标准偏差,每个循环1次(

然而,我注意到一件有趣的事情-当广播维度很大时,使用标准方法可以获得更好的加速。但当b的非广播维度较大时,转置方法似乎比简单广播快一点!我会对此进行一些分析并更新我的答案,但我肯定在这里找到了一些新的东西可以学习:(

哪一个更好

我遇到过一些情况,由于问题的性质,有必要同时使用两种方法(例如,在这种情况下,我需要同时使用这两种方法(。然而,我建议专注于标准方法,因为它的通用性要高得多。我将在稍后的编辑中尝试评论两者的表现。

In [340]: x = np.ones((3,4));
In [341]: x = np.ones((3,4))
In [342]: y = np.ones((3,4,2,2))

正在尝试可广播操作:

In [343]: x+y
Traceback (most recent call last):
File "<ipython-input-343-259706549f3d>", line 1, in <module>
x+y
ValueError: operands could not be broadcast together with shapes (3,4) (3,4,2,2) 

broadcasting可以将(3,4(的维度添加为(1,1,3,4。但这些不起作用。

相反,我们需要将维度添加到x:

In [344]: x[:,:,None,None].shape
Out[344]: (3, 4, 1, 1)

现在它与(3,4,2,2(一起工作:

In [346]: c=x[:,:,None,None]+y
In [347]: c.shape
Out[347]: (3, 4, 2, 2)

阅读我评论中的广播文档。

相关内容

  • 没有找到相关文章

最新更新