最近看北京大学曹建老师的TensorFlow搭建神经网络,在指数衰减学习率中,了解到指数衰减学习率的强大。由此写一些自己在学习中的感悟和启发。
大家都知道在设定学习率时,如果偏大会发生动荡不收敛,如果偏小则收敛速度慢。那么有没有一个好的方法可以让可以让学习率变化,并随着训练轮数由大到小进行变化。
答案是有的:指数衰减学习率可以做到。
先给出它的公式(枯燥的):learning_rate = learning_rate_base * learning_rate_decyglobal_step/learning_rate_step
TensorFlow源码中同样给出个计算公式
(注 1):learning_rate_base 表示学习率的初始值,learning_rate_decy 表示学习率衰减率,
global_step表示运行了几轮的BATCH_SIZE计数器,learning_rate_step表示多少轮BATCH_SIZE后更新一次学习率,一般设为:总样本数/BATCH_SIZE
通俗来讲:假设learning_rate_step为 1,那么就是1轮更新一次。由于global_step是每轮都自加一的,所以第一轮后学习率为:learning_rate_base * learning_rate_decy1
第二轮后学习率为:learning_rate_base * learning_rate_decy 2,第n轮后学习率为:learning_rate_base * learning_rate_decy n
方便起见我们设 LEARNING_RATE_BASE = 0.1 ,LEARNING_RATE_DECY = 0.99, LEARNING_RATE_STEP = 1
第一轮后 学习率更新为 learning_rate = 0.1 * 0.991 = 0.099 ,第二轮后 学习率更新为 earning_rate = 0.1 * 0.992 = 0.098 ,第n轮后 学习率更新为 learning_rate = 0.1 * 0.99n
(注 2):如果想看指数衰减原理性的,推荐吴恩达老师的机器学习。
代码奉上如下:
1 import tensorflow as tf 2 3 LEARNING_RATE_BASE = 0.1 # 最初学习率 4 LEARNING_RATE_DECY = 0.99 # 学习率衰减率 5 LEARNING_RATE_STEP = 1 # 喂入多少轮BATCH_SIZE后更新一次学习率,一般设为:总样本数/BATCH_SIZE 6 7 # 运行了几轮的BATCH_SIZE计数器,初值给零,设置为不被训练 8 global_step = tf.Variable(0, trainable=False) 9 10 # 定义指数下降学习率 11 learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE, global_step, 12 LEARNING_RATE_STEP, LEARNING_RATE_DECY, staircase=True) 13 14 # 定义待优化参数,初值给10 15 w = tf.Variable(tf.constant(10, dtype=tf.float32)) 16 # 定义损失函数 loss 17 loss = tf.square(w+1) 18 # 定义反向传播方法 19 train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step) 20 21 # 生成会话,训练40轮 22 with tf.Session() as sess: 23 init_op = tf.global_variables_initializer() 24 sess.run(init_op) 25 for i in range(40): 26 sess.run(train_step) 27 learning_rate_val = sess.run(learning_rate) 28 global_step_var = sess.run(global_step) 29 w_var = sess.run(w) 30 loss_var = sess.run(loss) 31 print('after %d steps: global_step is %f, w is %f, learn_rate is %f, loss is %f' % (i+1, global_step_var, w_var, 32 learning_rate_val, loss_var))
# 定义指数下降学习率
learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE, global_step,LEARNING_RATE_STEP, LEARNING_RATE_DECY, staircase=True)
LEARNING_RATE_DECY取值为(0, 1)这个区间
当staircase为True时,global_step/LEARNING_RATE_STEP取整数,学习率阶梯性衰减。staircase为False时,学习率会是一条平滑下降的曲线。
下面附上代码运行结果更直观显示:运行的轮数以及对应的学习率
结果显示loss值下降的过程非常好。且w很快的收敛到1.
下面给出固定学习率的运行结果。
learning_rate = 0.001
结果表明w随着轮数缓慢的下降(此时w应该是趋于1的)
当learning_rate = 1时
结果表明w随着轮数增加在10和-12之间跳变(此时w应该是趋于1的)