我想写一个自定义的训练循环。这里是我想做的一个示例代码。我有两个训练参数其中一个参数更新另一个参数。请看下面的代码:
x1 = tf.Variable(1.0, dtype=float)
x2 = tf.Variable(1.0, dtype=float)
with tf.GradientTape() as tape:
n = x2 + 4
x1.assign(n)
x = x1 + 1
y = x**2
val = tape.gradient(y, [x1, x2])
for v in val:
print(v)
,输出为
tf.Tensor(12.0, shape=(), dtype=float32)
None
看起来好像GradientTape没有监视第一个(x2)参数。这两个参数都是tf.Variable
类型,因此GradientTape应该监视这两个参数。我也试过tape.watch(x2)
,这也不工作。我错过什么了吗?
查看None
渐变的文档。要获得x1
的梯度,您必须使用tape.watch(x)
:
x
。x1 = tf.Variable(1.0, dtype=float)
x2 = tf.Variable(1.0, dtype=float)
with tf.GradientTape() as tape:
n = x2 + 4
x1.assign(n)
x = x1 + 1
tape.watch(x)
y = x**2
dv0, dv1 = tape.gradient(y, [x1, x2])
print(dv0)
print(dv1)
然而,对于x2
,输出y
根本没有连接到x2
,因为x1.assign(n)
似乎没有被跟踪,这就是梯度为None的原因。这与docs:
状态停止梯度。当从有状态对象中读取数据时,磁带只能观察当前状态,而不能观察导致当前状态的历史。
特遣部队。张量是不可变的。张量一旦被创建,你就不能改变它。它有值,但没有状态。到目前为止讨论的所有操作都是也是无状态的:tf的输出。Matmul只依赖于它的输入。
特遣部队。变量具有内部状态——它的值。当你使用这个变量时,状态被读取。计算关于的梯度是很正常的一个变量,但是变量的状态阻止梯度计算再往前看
例如,如果您这样做:
x1 = tf.Variable(1.0, dtype=float)
x2 = tf.Variable(1.0, dtype=float)
with tf.GradientTape() as tape:
n = x2 + 4
x1 = n
x = x1 + 1
tape.watch(x)
y = x**2
dv0, dv1 = tape.gradient(y, [x1, x2])
应该可以。