为了实现这一点,我们可以定义一系列独特的正向反向传播,并在操作之间指定依赖关系,然后tf.group 将它们一起[1] 以在单个会话运行中执行。
我的示例定义了一个感知器层,用于拟合 50 个二维高斯斑点。该代码在 tensorboard 中生成以下图表:
为了测试正确性,我用相同的初始化值训练了两次。第一次使用单个前向反向传播步骤,第二次使用 3 个步骤组合为一个操作:
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for i in range(12):
loss_val = loss_op.eval(feed_dict={x:x_train, y:y_train})
print(i, '-->', "{0:.3f}".format(loss_val))
_ = sess.run(train_op, feed_dict={x:x_train, y:y_train})
# loss_val = loss_op.eval(feed_dict={x:x_train, y:y_train})
# print(i, '-->', "{0:.3f}".format(loss_val))
# _ = sess.run(applied_grads, feed_dict={x:x_train, y:y_train})
# 3-steps # 1-step
# 0 --> 0.693 # 0 --> 0.693 ---
# 1 --> 0.665 # 1 --> 0.683
# 2 --> 0.638 # 2 --> 0.674
# 3 --> 0.613 # 3 --> 0.665 ---
# 4 --> 0.589 # 4 --> 0.656
# 5 --> 0.567 # 5 --> 0.647
# 6 --> 0.547 # 6 --> 0.638 ---
# 7 --> 0.527 # 7 --> 0.630
# 8 --> 0.509 # 8 --> 0.622
# 9 --> 0.492 # 9 --> 0.613 ---
# ...
显然对应于 3 步。
完整示例:
from sklearn.datasets import make_blobs
import tensorflow as tf
import numpy as np
tf.reset_default_graph()
times_to_apply = 3 # number of steps to perform
with tf.name_scope('x'):
x = tf.placeholder(tf.float32, shape=(None, 2))
with tf.name_scope('y'):
y = tf.placeholder(tf.int32, shape=(50))
logits = tf.layers.dense(inputs=x,
units=2,
name='NN',
kernel_initializer=tf.initializers.ones,
bias_initializer=tf.initializers.zeros)
optimizer = tf.train.GradientDescentOptimizer(0.01)
with tf.name_scope('loss-step-1'):
xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
loss_op = tf.reduce_mean(xentropy)
with tf.name_scope('optimizer-step-1'):
grads_and_vars = optimizer.compute_gradients(loss_op)
applied_grads = optimizer.apply_gradients(grads_and_vars)
all_grads_and_vars = [grads_and_vars]
all_applied_grads = [applied_grads]
all_loss_ops = [loss_op]
for i in range(times_to_apply - 1):
with tf.control_dependencies([all_applied_grads[-1]]):
with tf.name_scope('loss-step-' + str(i + 2)):
xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
all_loss_ops.append(tf.reduce_mean(xentropy))
with tf.control_dependencies([all_loss_ops[-1]]):
with tf.name_scope('optimizer-step-' + str(i + 2)):
all_grads_and_vars.append(optimizer.compute_gradients(all_loss_ops[-1]))
all_applied_grads.append(optimizer.apply_gradients(all_grads_and_vars[-1]))
train_op = tf.group(all_applied_grads)
[1] @eqzx 是绝对正确的。没有必要将操作分组在一起。为了达到同样的效果,我们可以只执行具有明确定义的依赖关系的最终优化器步骤。