python - 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)
然后它给了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)>
解决方案
这种行为确实有道理。让我们以您的第一个示例为例
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
。是的,您确实将值分配给x
from 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
。所以你会在这个例子中得到实际的渐变。
推荐阅读
- reactjs - 如何在反应虚拟化中限制 onScroll 功能?
- javascript - 在客户端更改上传文件的名称
- mapbox - mapbox gl fill-extrusion-height 限制十进制值,以米为单位
- grep - 使用 grep -v 过滤行
- c++ - 类模板成员函数的特化
- javascript - Jquery Confirm 在打字稿中不起作用
- javascript - 了解来自 api 的 addEventListener 回调?
- android - 如何实现半透明EditText?
- css - 为什么使用Flexbox时overflow-x会使块的宽度发生变化?
- arrays - 如何组合 2 个数组并将元素设置为变量?