首页 > 解决方案 > 为什么`tf.tile`通过所有副本传播梯度?

问题描述

我试图具体了解 Tensorflow 如何通过函数传播梯度tf.tile。我想做的很简单:

""" Considering batch_size = 3: """

# CASE 1:

a = tf.constant([[[1., 1.5], [2., 2.5], [3., 3.5]], [[4, 4.5], [5, 5.5], [6, 6.5]], [[7, 7.5], [8., 8.5], [9., 9.5]]])  # shape [3, 3, 2]

b = tf.constant([[[0.1], [0.2], [0.3]], [[0.4], [0.5], [0.6]], [[0.7], [0.8], [0.9]]])  # shape [3, 3, 1]

""" What I want is c = a + b, so I tile b to match last dimension of a: """

b_tile = tf.tile(b, [1, 1, tf.shape(a)[-1]])  # shape [3, 3, 2]
c = a + b_tile  # shape [3, 3, 2]

现在让我们计算c关于a和的梯度b_tile

dc_da, dc_dbtile = tf.gradients(c, [a, b_tile])
# dc_da: tensor with same shape as a and all elements 1.
# dc_dbtile: tensor with same shape as b and all elements 1.

这是完全有道理的,因为我有一个线性关系:c = a + b_tile. 但是,当我计算b_tilewrt的梯度时b,我希望梯度也是1.如此,因为我没有更改 的内部值b,只需扩展维度。但是当我这样做时,它会给出2.结果:

dbtile_db  = tf.gradients(b_tile, [b])
# dbtile_db: tensor with same shape as b and all elements equal 2.

我也尝试过b两次连接张量而不是使用tf.tile,它给出了相同的结果,所以很明显我遗漏了一些东西。

我试过用另一个例子来检查它的来源。现在让我们考虑另一个t具有完全相同值的张量b,让我们将它们连接起来以获得我需要的张量。在这种情况下:

# CASE 2:

m = tf.concat([b, t], -1) # shape [3, 3, 2]. Tensor identical to b_tile
dm_db, dm_dt = tf.gradients(m, [b, t])
# dm_db: tensor with same shape as b and all elements equal 1.
# dm_dt: tensor with same shape as t and all elements equal 1.

所以我有几个问题:

1)我不明白为什么使用tf.tile梯度会传播到所有副本,而它们只是能够计算总和的工具。从数值上讲,这对我来说没有意义,我希望渐变像最后一种情况一样传播。

2)案例1和案例2之间有什么区别(就梯度而言)?当我尝试做的事情相同时,为什么它会产生不同的结果?

3)考虑到我想计算总和c = a + b,正确的方法是什么?

问题是,在示例中,我的最后一个维度是2,所以我可以手动(连接)购买我真正的问题,我的最后一个维度是256000,所以我不能用最后一种方式来做。先感谢您

标签: pythontensorflow

解决方案


推荐阅读