首页 > 解决方案 > tf.Variable assign 方法打破了 tf.GradientTape

问题描述

当我使用 tf.Variable 的 assign 方法来更改变量的值时,它会阻止 tf.Gradient,例如,请参见下面的玩具示例代码:

(注意:我只对 TensorFlow 2 感兴趣。)

x = tf.Variable([[2.0,3.0,4.0], [1.,10.,100.]])
patch = tf.Variable([[0., 1.], [2., 3.]])
with tf.GradientTape() as g:
    g.watch(patch)
    x[:2,:2].assign(patch)
    y = tf.tensordot(x, tf.transpose(x), axes=1)
    o = tf.reduce_mean(y)
do_dpatch = g.gradient(o, patch)

然后它给了Nonedo_dpatch

请注意,如果我执行以下操作,则效果很好:

x = tf.Variable([[2.0,3.0,4.0], [1.,10.,100.]])
patch = tf.Variable([[0., 1.], [2., 3.]])
with tf.GradientTape() as g:
    g.watch(patch)
    x[:2,:2].assign(patch)
    y = tf.tensordot(x, tf.transpose(x), axes=1)
    o = tf.reduce_mean(y)
do_dx = g.gradient(o, x)

并给我:

>>>do_dx 
<tf.Tensor: id=106, shape=(2, 3), dtype=float32, numpy=
array([[ 1.,  2., 52.],
       [ 1.,  2., 52.]], dtype=float32)>

标签: pythontensorflowdeep-learningtensorflow2.0

解决方案


这种行为确实有道理。让我们以您的第一个示例为例

x = tf.Variable([[2.0,3.0,4.0], [1.,10.,100.]])
patch = tf.Variable([[1., 1.], [1., 1.]])
with tf.GradientTape() as g:
    g.watch(patch)
    x[:2,:2].assign(patch)
    y = tf.tensordot(x, tf.transpose(x), axes=1)
dy_dx = g.gradient(y, patch)

您正在计算 dy/d(patch)。但你只y依赖于x不依赖于patch。是的,您确实将值分配给xfrom patch。但是这个操作不携带对patch变量的引用。它只是复制值。

简而言之,您正在尝试获得不依赖的渐变。所以你会得到None.

让我们看看第二个例子以及它为什么起作用。

x = tf.Variable([[2.0,3.0,4.0], [1.,10.,100.]])
with tf.GradientTape() as g:
    g.watch(x)
    x[:2,:2].assign([[1., 1.], [1., 1.]])
  y = tf.tensordot(x, tf.transpose(x), axes=1)
dy_dx = g.gradient(y, x)

这个例子非常好。Y 取决于 x 并且您正在计算dy/dx。所以你会在这个例子中得到实际的渐变。


推荐阅读