Python 变量赋值方法破坏了tf.GradientTape
当我使用tf.Variable的赋值方法来更改变量的值时,它会阻止tf.Gradient,e。g、 ,请参见下面玩具示例的代码: (注:我只对TensorFlow 2感兴趣。) 然后它给我Python 变量赋值方法破坏了tf.GradientTape,python,tensorflow,deep-learning,tensorflow2.0,Python,Tensorflow,Deep Learning,Tensorflow2.0,当我使用tf.Variable的赋值方法来更改变量的值时,它会阻止tf.Gradient,e。g、 ,请参见下面玩具示例的代码: (注:我只对TensorFlow 2感兴趣。) 然后它给我do\u dpatch的None 请注意,如果我执行以下操作,它将非常正常: x = tf.Variable([[2.0,3.0,4.0], [1.,10.,100.]]) patch = tf.Variable([[0., 1.], [2., 3.]]) with tf.GradientTape() as g
do\u dpatch
的None
请注意,如果我执行以下操作,它将非常正常:
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)>
>>do\u dx
这种行为确实有道理。让我们举你的第一个例子
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(补丁)。但是您的y
依赖于x
而不是补丁
。是的,您可以从patch
为x
赋值。但此操作不带对补丁
变量的引用。它只是复制值
简而言之,你试图得到一个梯度,它不依赖于。因此,您将得到无
让我们看看第二个例子,以及它的工作原理
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。所以在这个例子中你会得到实际的梯度。这个行为是有意义的。让我们举你的第一个例子
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(补丁)。但是您的y
依赖于x
而不是补丁
。是的,您可以从patch
为x
赋值。但此操作不带对补丁
变量的引用。它只是复制值
简而言之,你试图得到一个梯度,它不依赖于。因此,您将得到无
让我们看看第二个例子,以及它的工作原理
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。因此,在本例中可以得到实际的渐变。如前所述(请参阅下面来自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)>
do\u dpatch
如前所述(参见下面来自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)>
do\u dpatch