我想看看学习率在培训期间如何变化(打印出来或创建摘要并在张量板中可视化)。
以下是我目前所拥有的代码段:
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与我的相似。但是,我不能在评论部分发布我的发现,因为我没有足够的代表。
答案 0 :(得分:2)
我问自己完全相同的问题,并想知道为什么它不会改变。通过查看original paper(第2页),我们可以看到算法需要self._lr
步长(在论文中设计为alpha
),但从未更新过。我们还发现,每个alpha_t
步骤都会更新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
张量不会在整个训练过程中发生变化,这可能会导致优化器无法适应的错误结论(这可以通过切换到 vanilla GradientDescentOptimizer
具有相同的alpha
)。事实上,其他值确实会发生变化:快速查看优化程序__dict__
会显示以下键:['_epsilon_t', '_lr', '_beta1_t', '_lr_t', '_beta1', '_beta1_power', '_beta2', '_updated_lr', '_name', '_use_locking', '_beta2_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
和{{1} }}通过整个培训,与_beta2
和_lr
类似的方式与论文的符号相矛盾。 我想这是有原因的,但我个人不知道为什么,无论如何这是实施的受保护/私有属性(因为它们以下划线开头)并且不属于公共界面(它们甚至可能在TF版本之间发生变化)。
因此,在这个小背景之后,我们可以看到lr_t
和_beta_1_power
是指向当前训练步骤的原始beta值,也就是相当于_beta_2_power
引用的变量在论文中。回到本文第2部分中beta_t
的定义,我们看到,通过这些信息,实现起来应该非常简单:
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
的有用性提出质疑,因为它不依赖于数据。
此外,为了完成这些信息,本文第2部分还给出了权重更新的公式,这更加有说服力,但也更多的是情节密集型。对于非常好看且外观漂亮的实现,您可能需要查看您链接的帖子中的this nice answer。
希望它有所帮助!干杯,
安德烈