趁着最近空闲一点,继续纠结TensorFlow学习率调整的问题。学习率对网路训练的影响还是挺大的,初始化时可以采用大的学习率,帮助网络快速收敛。但网络的梯度是非线性的,随着迭代次数的增加,梯度的导数趋于变小,如果继续保持大学习率,会出现优化目标在最优解附近波动的情况,如下图所示。此时,为了接近收敛点,需要调整学习率。
参考TensorFlow: 实战Google深度学习框架这本书,利用指数衰减的方法设置梯度下降算法的学习率,TensofFLow中集成了这一算法,即tf.train.exponential_decay
。其实现了
其中$L_R$表示学习率,$R_d$表示衰减率,$S_g$和$S_d$分别表示总Epochs和每个Epochs中的Batches。从而没迭代一轮,学习率便更新一次。
在TensorFlow中可以用如下代码实现指数衰减的学习率更新。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import numpy as np import tensorflow as tf init_lr = tf.Variable(0., name="LR") global_step = tf.Variable(0., name="global_step") decay_step = tf.Variable(0., name="decay_step") decay_rate = tf.Variable(0., name="decay_rate") learning_rate = tf.train.exponential_decay( learning_rate = init_lr , global_step = global_step, decay_steps = decay_step, decay_rate = decay_rate, staircase=False, name=None ) lr_init = 0.1 epochs = 200 batches = 100. d_rate = 0.9 epoch = np.arange(0,epochs,1) lr = np.zeros(epoch.shape) init_op = tf.global_variables_initializer() sess = tf.InteractiveSession() sess.run(init_op) for i in epoch.astype(int): lr[i] = sess.run(learning_rate, feed_dict={init_lr: lr_init, global_step: i, decay_step: batches, decay_rate: d_rate })
|
这里提供了一个样例,其输出结果如下图,通过设置tf.exponential_decay
的参数staircase
可以控制learning rate是否为阶梯型或者平滑的。
而在训练网络,优化目标函数的过程中,可以参考官方手册,用如下语句进行梯度更新。
1 2 3 4 5 6 7 8 9 10
| ... global_step = tf.Variable(0, trainable=False) starter_learning_rate = 0.1 learning_rate = tf.train.exponential_decay(starter_learning_rate, global_step, 100000, 0.96, staircase=True) learning_step = ( tf.train.GradientDescentOptimizer(learning_rate) .minimize(...my loss..., global_step=global_step) )
|
Reference
[1] exponential decay