Broadcasting机制是张量维度扩张的手段,但是没有在数据层面上的复制。
是一种数据优化的手段。高效且直观。
其过程:
给需要位置插入 1 个维度(dim)。
给 dim 为 1 的扩展成所需的数量。
例如:
- Feature maps: [4, 32, 32, 3]
- Bias: [3] → [1, 1, 1, 3] → [4, 32, 32, 3]
![CSDN图标](https://img-blog.csdnimg.cn/20200321180112154.png)
解释
1、如果没有这个维度
1)建立一个新的概念
2)[classes, students, scores] + [scores]
2、当存在 dim 为 1 的维度。
1)当成所需的量
2)[classes, students, scores] + [students, 1]
优点
1、真实需求
2、减少内存消耗
判断是否可以Broadcasting
从最低维匹配
1)如果当前维度 dim =1 ,扩张。
2)如果没有当前维度,插入一个维度,再扩张。
3)否则,不能 Broadcasting。且,如果最小维匹配的维度值不相同,也不扩张
举例
举例1
-
[4, 32, 14, 14]
-
[1, 32, 1, 1] → [4, 32, 14, 14]
举例2
-
[4, 32, 14, 14]
-
[14, 14] → [1, 1, 14, 14] → [4, 32, 14, 14]
举例3
- [4, 32, 14, 14]
- [2, 32, 14, 14] [报错]
示例代码
- 隐式的Broadcasting
x = tf.random.normal([4, 32, 32, 3])
(x +tf.random.normal([3])).shape
Out[120]: TensorShape([4, 32, 32, 3])
(x +tf.random.normal([32, 32, 1])).shape
Out[121]: TensorShape([4, 32, 32, 3])
(x +tf.random.normal([4, 1, 1, 1])).shape
Out[122]: TensorShape([4, 32, 32, 3])
(x + tf.random.normal([1, 4, 1, 1])).shape # 报错
tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [4,32,32,3] vs. [1,4,1,1] [Op:AddV2] name: add/
- 显式的broadcast_to
x.shape
Out[124]: TensorShape([4, 32, 32, 3])
(x + tf.random.normal([4, 1, 1, 1])).shape
Out[125]: TensorShape([4, 32, 32, 3])
b = tf.broadcast_to(tf.random.normal([4, 1, 1, 1]), [4, 32, 32, 3])
b.shape
Out[127]: TensorShape([4, 32, 32, 3])
b = tf.broadcast_to(tf.random.normal([4, 1, 1, 1]), [3, 32, 32, 3]) # 报错
tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [4,1,1,1] vs. [3,32,32,3] [Op:BroadcastTo]
- Broadcasting VS Tile
tensorflow中的tile()函数是用来对张量(Tensor)进行扩展的,其特点是对当前张量内的数据进行一定规则的复制。最终的输出张量维度不变。
tf.tile
(
input,
multiples,
name=None
)
input - 是待扩展的张量,
multiples - 是扩展方法。
假如input是一个3维的张量。那么mutiples就必须是一个1x3的1维张量。这个张量的三个值依次表示input的第1,第2,第3维数据扩展几倍。
a = tf.ones([3, 4])
a1 = tf.broadcast_to(a, [2, 3, 4])
Out[131]:
<tf.Tensor: shape=(2, 3, 4), dtype=float32, numpy=
array([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]],
[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]], dtype=float32)>
a2 = tf.expand_dims(a, axis = 0)
a2 = tf.tile(a2, [2, 1, 1])
a2
Out[134]:
<tf.Tensor: shape=(2, 3, 4), dtype=float32, numpy=
array([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]],
[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]], dtype=float32)>