我有一个问题,当我实现以下代码时,在对可训练变量应用掩码后,x 的梯度变为无。移除掩模后,就可以计算梯度了。我想知道这是什么原因。
layer = tf.keras.layers.Dense(2, activation='relu')
x = tf.Variable([[1., 2., 3.]], name = "tfv", trainable=True)
mask = tf.constant([0., 1., 0.], shape = (3,1))
x_ = x@mask
with tf.GradientTape() as tape:
# Forward pass
y = layer(x_)
loss = tf.reduce_mean(y**2)
# Calculate gradients with respect to every trainable variable
grad = tape.gradient(loss, [layer.trainable_variables, x])
grad的输出是
[[<tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[0. , 5.2745185]], dtype=float32)>,
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([0. , 2.6372592], dtype=float32)>],
None]
摘下面膜后
layer = tf.keras.layers.Dense(2, activation='relu')
x = tf.Variable([[1., 2., 3.]], name = "tfv", trainable=True)
with tf.GradientTape() as tape:
# Forward pass
y = layer(x)
loss = tf.reduce_mean(y**2)
# Calculate gradients with respect to every trainable variable
grad = tape.gradient(loss, [layer.trainable_variables,x])
梯度的输出为
[[<tf.Tensor: shape=(3, 2), dtype=float32, numpy=
array([[1.2404386, 3.1709769],
[2.4808772, 6.3419538],
[3.7213159, 9.512931 ]], dtype=float32)>,
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([1.2404386, 3.1709769], dtype=float32)>],
<tf.Tensor: shape=(1, 3), dtype=float32, numpy=array([[2.8783302 , 0.38053298, 2.651462 ]], dtype=float32)>]
非常感谢您的帮助!
原因很可能是您想要梯度 w.r.t。
x
,但是您将 x 与 GradientTape 之外的蒙版 相乘。因此,磁带永远不会将梯度记录回 x
,而只会记录到 x_
。这也是你的第二个例子有效的原因。在那里,您定义 x
,然后 x
上的每个操作都在 GradientTape
内部。x@mask
移动到 with
块内:
with tf.GradientTape() as tape:
x_ = x@mask
# Forward pass
y = layer(x_)
loss = tf.reduce_mean(y**2)
这样,磁带就知道了
x
和 x_
之间的关系。