【问题标题】:tf.Variable assign method breaks the tf.GradientTapetf.Variable assign 方法打破了 tf.GradientTape
【发布时间】:2019-12-19 15:15:06
【问题描述】:

当我使用 tf.Variable 的 assign 方法更改变量的值时,它会制动 tf.Gradient,例如。 g.,请参阅下面的玩具示例代码:

(注意:我只对 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)

然后它给我None do_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)>

【问题讨论】:

    标签: python tensorflow deep-learning tensorflow2.0


    【解决方案1】:

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

    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。是的,您确实从patchx 赋值。但此操作不携带对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。所以你会在这个例子中得到实际的渐变。

    【讨论】:

      【解决方案2】:

      正如HERE 所解释的(请参阅下面来自alextp 的引用)tf.assign 不支持渐变。

      “没有计划向 tf.assign 添加渐变,因为通常无法将分配变量的用途与分配它的图形联系起来。”

      所以,上面的问题可以通过下面的代码来解决:

      x= tf.Variable([[0.0,0.0,4.0], [0.,0.,100.]])
      patch = tf.Variable([[0., 1.], [2., 3.]])
      with tf.GradientTape() as g:
          g.watch(patch)
          padding = tf.constant([[0, 0], [0, 1]])
          padde_patch = tf.pad(patch, padding, mode='CONSTANT', constant_values=0)
          revised_x = x+ padde_patch
          y = tf.tensordot(revised_x, tf.transpose(revised_x), axes=1)
          o = tf.reduce_mean(y)
      do_dpatch = g.gradient(o, patch)
      

      导致

      do_dpatch
      
      <tf.Tensor: id=65, shape=(2, 2), dtype=float32, numpy=
      array([[1., 2.],
             [1., 2.]], dtype=float32)>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-15
        • 2016-10-10
        相关资源
        最近更新 更多