使用+和*的张量流中的隐式广播是如何工作的?
如果我有两个张量,那么
a.get_shape() = [64, 10, 1, 100]
b.get_shape() = [64, 100]
(a+b).get_shape = [64, 10, 64, 100]
(a*b).get_shape = [64, 10, 64, 100]
怎么会变成[64,10,64,100] ??
答案 0 :(得分:2)
根据documentation,像add
这样的操作是广播操作。
引用glossary:
详细记录了numpy式广播广播业务
使用numpy风格广播使其张量参数的形状兼容的操作。
简而言之:
[...]较小的数组在较大的数组中“广播”,以便它们具有兼容的形状。
广播提供了一种矢量化数组操作的方法,以便在C而不是Python中进行循环。
答案 1 :(得分:1)
我认为广播并没有按照你的意图行事。它实际上是广播两个方向。让我通过修改你的例子来告诉你我的意思
a = tf.ones([64, 10, 1, 100])
b = tf.ones([128, 100])
print((a+b).shape) # prints "(64, 10, 128, 100)"
从此我们看到它首先匹配最后的维度进行广播。它隐含地在{* 1}}之间平铺{3}以匹配a
第一维的大小,然后隐式添加单例和平铺b
b
的前两个维度。
我认为您希望在a
的第二维上隐式平铺b
。要做到这一点,您需要a
为不同的形状:
b
您可以在b上使用tf.expand_dims()
两次添加两个单身尺寸以匹配此形状。
答案 2 :(得分:0)
numpy
样式broadcasting
有据可查,但为了简短说明:将比较两个张量的形状,从最后一个形状开始向后,然后复制两个张量中缺少的任何形状要匹配。
例如,使用
a.get_shape() = [64, 10, 1, 100]
b.get_shape() = [64, 100]
(a*b).get_shape = [64, 10, 64, 100]
a
和b
具有相同的最后一个形状== 100,然后复制a
的倒数第二个形状以匹配b
shape == 64,{ {1}}缺少b
的前两个形状,它们将被创建。
请注意,任何缺少的形状都必须为1或不存在,因为所有较低级别的形状都会被复制。