在TensorFlow中,AdamOptimizer的学习率不会改变

我想看看学习率在培训期间如何变化(打印出来或创建摘要并在张量板中可视化).

这是我到目前为止的代码片段:

optimizer = tf.train.AdamOptimizer(1e-3)
grads_and_vars = optimizer.compute_gradients(loss)
train_op = optimizer.apply_gradients(grads_and_vars, global_step=global_step)

sess.run(tf.initialize_all_variables())

for i in range(0, 10000):
   sess.run(train_op)
   print sess.run(optimizer._lr_t)

如果我运行代码,我会不断获得初始学习率(1e-3),即我看不到任何变化.

在每一步获得学习率的正确方法是什么?

我想补充一点,this question与我的相似.但是,我不能在评论部分发布我的发现,因为我没有足够的代表.

最佳答案 我问自己完全相同的问题,并想知道为什么它不会改变.通过查看
original paper(第2页),可以看到算法需要self._lr stepsize(在论文中设计为alpha),但从未更新过.我们还看到每个t步都有一个alpha_t更新,并且应该与self._lr_t属性相对应.但实际上,正如您所观察到的那样,在训练期间的任何时刻评估self._lr_t张量的值总是返回初始值,即_lr.

因此,正如我所理解的那样,您的问题是如何获取TensorFlow的AdamOptimizer的alpha_t,如本文第2部分和相应的TF v1.2 API page中所述:

alpha_t = alpha * sqrt(1-beta_2_t) / (1-beta_1_t)

背景

正如您所观察到的那样,_lr_t张量不会随着训练而改变,这可能导致优化器不适应的错误结论(这可以通过切换到具有相同alpha的vanilla GradientDescentOptimizer来轻松测试).而且,实际上,其他值确实会发生变化:快速查看优化器的__dict__会显示以下键:[‘_ epsilon_t’,’_ lr’,’_ beta1_t’,’_ lr_t’,’_ betaa1′,’_ beta1_power’,’_ betaa2′ ,’_ update_lr’,’_ name’,’_ use_locking’,’_ betaa2_t’,’_ beta2_power’,’_ epsilon’,’_slots’].

通过训练检查它们,我注意到只有_beta1_power,_beta2_power和_slots得到更新.

进一步检查the optimizer’s code,在第211行,我们看到以下更新:

update_beta1 = self._beta1_power.assign(
        self._beta1_power * self._beta1_t,
        use_locking=self._use_locking)

这基本上意味着_beta1_power,即initialized with _beta1,将在每次迭代后乘以_beta_1_t,即is also initialized with beta_1_t.

但是这里出现了令人困惑的部分:_beta1_t和_beta2_t永远不会得到更新,因此他们通过整个训练有效地保持初始值(_beta1和_beta2),与_lr和lr_t类似的方式与论文的符号相矛盾.我想这是有原因的,但我个人不知道为什么,无论如何这是实现的受保护/私有属性(因为它们以下划线开头)并且不属于公共接口(它们甚至可能会改变在TF版本中).

因此,在这个小背景之后,我们可以看到_beta_1_power和_beta_2_power是指向当前训练步骤的原始beta值,也就是说,相当于beta_tin引用的变量.回到本文第2部分中关于alpha_t的定义,我们看到,使用这些信息,实现它应该非常简单:

optimizer = tf.train.AdamOptimizer()
# rest of the graph...

# ... somewhere in your session
# note that a0 comes from a scalar, whereas bb1 and bb2 come from tensors and thus have to be evaluated
a0, bb1, bb2 = optimizer._lr, optimizer._beta1_power.eval(), optimizer._beta2_power.eval()
at = a0* (1-bb2)**0.5 /(1-bb1)
print(at)

变量at保存当前训练步骤的alpha_t.

免责声明

我只是使用优化器的界面找不到更清晰的方法来获取这个值,但请告诉我它是否存在!我猜没有,这实际上是对绘制alpha_t的有用性提出质疑,因为它不依赖于数据.

此外,为了完成这些信息,本文的第2部分还给出了权重更新的公式,这更加有说服力,但也更多的是情节密集型.对于一个非常好看和好看的实现,你可能想看看你链接的帖子this nice answer.

希望能帮助到你!干杯,
安德烈斯

点赞