简单的广播b
to 3D
然后沿着第二个轴连接 -
b3D = np.broadcast_to(b,(a.shape[0],1,len(b)))
out = np.concatenate((a,b3D),axis=1)
The broadcasting
与np.broadcast_to
并不实际复制或制作副本,而只是一个复制视图,然后在下一步中,我们进行串联以即时进行复制。
标杆管理
我们正在比较np.repeat来自 @cᴏʟᴅsᴘᴇᴇᴅ 解决方案的版本反对np.broadcast_to
一
本节重点关注性能。基于广播的在第二步中进行复制和串联,作为合并命令可以这么说,同时np.repeat
version 进行复制,然后在两个单独的步骤中连接。
整个方法的计时:
情况1 :a = (500,400,300)
and b = (300,)
In [321]: a = np.random.rand(500,400,300)
In [322]: b = np.random.rand(300)
In [323]: %%timeit
...: b3D = b.reshape(1, 1, -1).repeat(a.shape[0], axis=0)
...: r = np.concatenate((a, b3D), axis=1)
10 loops, best of 3: 72.1 ms per loop
In [325]: %%timeit
...: b3D = np.broadcast_to(b,(a.shape[0],1,len(b)))
...: out = np.concatenate((a,b3D),axis=1)
10 loops, best of 3: 72.5 ms per loop
对于较小的输入形状,请致电np.broadcast_to
需要的时间比np.repeat
鉴于设置广播所需的工作显然更加复杂,如下所示:
In [360]: a = np.random.rand(5,4,3)
In [361]: b = np.random.rand(3)
In [366]: %timeit np.broadcast_to(b,(a.shape[0],1,len(b)))
100000 loops, best of 3: 3.12 µs per loop
In [367]: %timeit b.reshape(1, 1, -1).repeat(a.shape[0], axis=0)
1000000 loops, best of 3: 957 ns per loop
但是,无论输入的形状如何,广播部分都将具有恒定的时间,即这3 u-sec
部分将停留在该标记附近。对方的时间安排:b.reshape(1, 1, -1).repeat(a.shape[0], axis=0)
取决于输入形状。因此,让我们更深入地研究一下这两种方法的串联步骤如何公平/行为。
深层发掘
尝试深入挖掘以了解串联部分消耗了多少:
In [353]: a = np.random.rand(500,400,300)
In [354]: b = np.random.rand(300)
In [355]: b3D = np.broadcast_to(b,(a.shape[0],1,len(b)))
In [356]: %timeit np.concatenate((a,b3D),axis=1)
10 loops, best of 3: 72 ms per loop
In [357]: b3D = b.reshape(1, 1, -1).repeat(a.shape[0], axis=0)
In [358]: %timeit np.concatenate((a,b3D),axis=1)
10 loops, best of 3: 72 ms per loop
结论:看起来并没有太大不同。
现在,让我们尝试一个需要复制的情况b
是一个更大的数字并且b
元素数量也非常多。
In [344]: a = np.random.rand(10000, 10, 1000)
In [345]: b = np.random.rand(1000)
In [346]: b3D = np.broadcast_to(b,(a.shape[0],1,len(b)))
In [347]: %timeit np.concatenate((a,b3D),axis=1)
10 loops, best of 3: 130 ms per loop
In [348]: b3D = b.reshape(1, 1, -1).repeat(a.shape[0], axis=0)
In [349]: %timeit np.concatenate((a,b3D),axis=1)
10 loops, best of 3: 141 ms per loop
结论:看起来像是合并的连接+复制np.broadcast_to
这里做得好一些。
我们来尝试一下原来的情况(5,4,3)
shape :
In [360]: a = np.random.rand(5,4,3)
In [361]: b = np.random.rand(3)
In [362]: b3D = np.broadcast_to(b,(a.shape[0],1,len(b)))
In [363]: %timeit np.concatenate((a,b3D),axis=1)
1000000 loops, best of 3: 948 ns per loop
In [364]: b3D = b.reshape(1, 1, -1).repeat(a.shape[0], axis=0)
In [365]: %timeit np.concatenate((a,b3D),axis=1)
1000000 loops, best of 3: 950 ns per loop
结论:同样,没有太大不同。
所以,最终的结论是,如果里面有很多元素b
如果第一个轴a
也是一个很大的数字(因为复制数就是那个),np.broadcast_to
将是一个不错的选择,否则np.repeat
基于版本很好地处理了其他情况。