python - 使用 np.transpose 使数组广播
问题描述
我有一个广播错误,如下所示:
ValueError:操作数无法与形状一起广播 (84,36) (84,36,210,45)
有没有办法解决这个问题?我尝试使用 np.transpose() 来移动索引,以便遵守广播规则,但不知何故,我得到的答案不再正确。np.transpose() 在这里真正做了什么?
解决方案
您可以通过多种方式进行广播。
使用转置
较长的方式是您尝试使用的方式transpose
。在这里,由于array a
只有 2 个维度(它是最后 2 个维度),因此您也将 的前 2 个维度设置array b
为最后 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)
。这里更清楚。
通过添加轴进行标准广播
更有用的一种标准方法是将 2 维添加到array a
. 所以现在,这两个数组共享前两个用于广播的维度。
c = a[..., None, None] + b #(84,26,1,1) + (84, 36, 210, 45)
c.shape
(84, 36, 210, 45)
在这里澄清一下,a[..., None, None]
添加 2 个新轴并将 shape 的 2D 张量转换为 shape(84, 26)
的 4D 张量(84,26,1,1)
。这里更清楚。
最后,为了证明这两种方法是等效的,您可以像这样检查 -
np.all((b.transpose(2,3,0,1) + a).transpose(2,3,0,1) == a[...,None, None] + b)
True
大型阵列的基准测试 -
- 转置方法- 每个循环 1.88 秒 ± 977 毫秒(平均值 ± 标准偏差。7 次运行,每个循环 1 个)
- 标准广播- 每个循环 1.25 秒 ± 156 毫秒(平均值 ± 标准偏差。7 次运行,每个循环 1 个)
但是,我注意到一件有趣的事情 - 当广播维度很大时,使用标准方法可以获得更好的加速。但是当非广播维度的大小较大时
b
,转置方法似乎比简单广播要快一点!我会对此进行一些分析并更新我的答案,但我肯定在这里发现了一些新东西要学习:)
哪一个更好?
我遇到过一些情况,由于问题的性质,有必要同时使用这两种方法(例如,在这个赏金中,我需要同时使用这两种方法)。但是,我建议将重点放在标准方法上,因为它的用途要广泛得多。我将尝试在以后的编辑中评论两者的表现。
推荐阅读
- python - python的selenium Pageobject?
- python - 如何将来自多个模型的数据添加到 HTML 模板 - Django
- talend - Talend 中的动态过滤器行
- zbar - 来自 zbar 的奇怪警告:seg->finder 上的断言
- java - Count Groups of Objects in List
- javascript - 我如何附加到嵌套的输入数组。反应形式
- typescript - Babel TypeScript 预设不理解导入类型和导出类型
- python - plotly:水平条形图无法识别/显示 trace2
- opengl - 在绘制网格表面和多边形边缘时如何避免 OpenGL 中的 z-fighting?
- css - 在 woocommerce 中使用自定义 CSS 隐藏它