我是Tensorflow
的新朋友。在教科书示例中,我看到了以下旨在使用Tensorflow 2.x
API训练简单线性模型的代码:
m = tf.Variable(0.)
b = tf.Variable(0.)
def predict_y_value(x):
y = m * x + b
return y
def squared_error(y_pred, y_true):
return tf.reduce_mean(tf.square(y_pred - y_true))
learning_rate = 0.05
steps = 500
for i in range(steps):
with tf.GradientTape() as tape:
predictions = predict_y_value(x_train)
loss = squared_error(predictions, y_train)
gradients = tape.gradient(loss, [m, b])
m.assign_sub(gradients[0] * learning_rate)
b.assign_sub(gradients[1] * learning_rate)
print ("m: %f, b: %f" % (m.numpy(), b.numpy()))
为什么有必要在块with tf.GradientTape() as tape
中包含损失函数的定义,但是gradients = tape.gradient(loss, [m, b])
代码行在with
块之外?
我知道这可能是特定于Python
语言的,但是这种构造对我来说似乎还不清楚。 Python
上下文管理器在这里的作用是什么?
答案 0 :(得分:1)
从tensorflow文档中
默认情况下,GradientTape将自动监视在上下文中访问的所有可训练变量。
从直觉上讲,这种方法增强了很多灵活性。例如,它允许您编写如下的(伪)代码:
inputs, labels = get_training_batch()
inputs_preprocessed = some_tf_ops(inputs)
with tf.GradientTape() as tape:
pred = model(inputs_preprocessed)
loss = compute_loss(labels, pred)
grads = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(grads, model.trainable_variables))
# For example, let's attach a model that takes the above model's output as input
next_step_inputs, next_step_labels = process(pred)
with tf.GradientTape() as tape:
pred = another_model(next_step_inputs)
another_loss = compute_loss(next_step_labels, pred)
grads = tape.gradient(another_loss, another_model.trainable_variables)
optimizer.apply_gradients(zip(grads, another_model.trainable_variables))
上面的示例可能看起来很复杂,但是它说明了需要极端灵活性的极端情况。
我们不希望some_tf_ops
和process
在梯度计算中发挥作用,因为它们是预处理步骤。
我们想为多个具有一定关系的模型计算梯度
一个实际的例子是训练GAN,尽管可能更简单的实现。