numpy 有 broadcast 机制,使用它可以让我们的代码更加方便。
TensorFlow 有不少操作支持 broadcast.
通常来说,我们对 numpy 的 ndarray 或者 TensorFlow 中的 tensor 进行 element-wise 操作都要求两个变量的
shape 保持一直。
a = np.random.rand(3, 4)
b = np.random.rand(5, 4)
c = a + b
ValueError Traceback (most recent call last)
in ()
—-> 1 c = a + b
ValueError: operands could not be broadcast together with shapes (3,4) (4,4)
对两个arrays / tensors 只有两种情况 element-wise 的操作是可行的:
1. 他们的 shape 一样
2. 其中有个一个 shape 为 1
下面看一些例子:
>>> a = np.random.randint(1, 10, [4, 1])
>>> b = np.random.randint(1, 10, [1, 5])
>>> a
array([[4],
[9],
[5],
[9]])
>>> b
array([[7, 4, 5, 3, 6]])
>>> c = a + b
>>> c.shape
(4, 5)
>>> c
array([[11, 8, 9, 7, 10],
[16, 13, 14, 12, 15],
[12, 9, 10, 8, 11],
[16, 13, 14, 12, 15]])
>>>
a 是一个 shape 为 (4, 1) 的列向量, b 的 shape 为 (1, 5)。
当执行加法的时候,结果的 shape 是 (4 ,5)。
broadcast 机制会把 a 的列“自动复制” 5 次,b 的行“自动复制” 4 次, 然后进行相加。
另外 Adrew Ng 在 deeplearning.ai 中的课程提到的变成技巧,谨慎处理 shape 为 (n, ) 的 array,因为它们既不是行向量也不是列向量。
>>> d = np.random.randn(5)
>>> d
array([-0.47976907, 0.1914602 , 0.26772239, -0.17560298, 1.13600281])
>>> d.shape
(5,)
>>> d.T
array([-0.47976907, 0.1914602 , 0.26772239, -0.17560298, 1.13600281])
>>> d.T + d
array([-0.95953815, 0.38292039, 0.53544479, -0.35120595, 2.27200562])
结果并不是之前预测的 (5, 5) 的 shape
>>> d1 = d.reshape(5, 1)
>>> d1 + d1.T
array([[-0.95953815, -0.28830888, -0.21204668, -0.65537205, 0.65623374],
[-0.28830888, 0.38292039, 0.45918259, 0.01585722, 1.32746301],
[-0.21204668, 0.45918259, 0.53544479, 0.09211942, 1.4037252 ],
[-0.65537205, 0.01585722, 0.09211942, -0.35120595, 0.96039983],
[ 0.65623374, 1.32746301, 1.4037252 , 0.96039983, 2.27200562]])
我们把 d reshape 为 (5, 1) 后,结果就正常了。
参考资料:numpy broadcasting