本文介绍在
tensorflow
库中,用于
动态调整神经网络的学习率
的一种方法——
指数衰减
ExponentialDecay()
策略的参数含义及其具体用法。

在进行神经网络训练时,我们经常需要用到动态变化的学习率,其中
指数衰减
ExponentialDecay()
策略是我们常用的一种策略。在
tensorflow
库中,其完整的用法是
tf.keras.optimizers.schedules.ExponentialDecay()
,其中的具体参数如下所示。

tf.keras.optimizers.schedules.ExponentialDecay(
    initial_learning_rate, decay_steps, decay_rate, staircase=False, name=None
)

首先,我们需要知道,在用了
ExponentialDecay()
策略后,程序将动态调整神经网络训练过程中的学习率,且这一调整是与我们当前训练的
step
有关的。具体关于
step
的解释,大家可以参考文章
神经网络常见参数解释:epoch、batch、batch size、step、iteration
,本文就不再赘述。

如以下代码所示,使用
ExponentialDecay()
策略后,程序将依据如下的规律,基于当前训练的
step
,以及我们自行设定的几个参数,从而计算得到当前的学习率。其中,函数的返回值就是当前的学习率。

def decayed_learning_rate(step):
  return initial_learning_rate * decay_rate ^ (step / decay_steps)

其中,
initial_learning_rate * decay_rate ^ (step / decay_steps)
就是当前学习率的计算公式。这里的
initial_learning_rate

decay_rate
以及
decay_steps
,就是我们前面提到的
ExponentialDecay()
函数的前
3
个参数。其中,
initial_learning_rate
是我们的初始学习率,
decay_rate
是学习率下降的速率,而
decay_steps
则是学习率下降的位置(具体含义我们稍后介绍)。此外,
ExponentialDecay()
策略还有两个参数,
staircase
表示我们在计算
(step / decay_steps)
时,是对结果
向下取整
还是
取小数
,默认为
False
,即
取小数
结果(具体含义我们稍后介绍);最后一个
name
参数,只是对当前这一学习率下降的策略加以命名,一般用不上这个参数,我们就不再介绍了。

由此,我们可以初步知道,
ExponentialDecay()
函数的前
4
个参数都是用来计算当前的学习率的;且结合我们前面的公式
initial_learning_rate * decay_rate ^ (step / decay_steps)
,我们可以知道,随着当前的
step
不断增加,
decay_rate ^ (step / decay_steps)
是降低的。

接下来,我们直接带入具体的数据,来看一下这几个参数的具体作用。

如下图所示,我们这里有一个训练数据集,其中共有
193608
个样本。

image

同时,我设置了神经网络的
batch size

2048
,那么基于前述提及的文章
神经网络常见参数解释:epoch、batch、batch size、step、iteration
,可知在
1

epoch
中,我们对这
193608
个样本加以训练,共需要的
batch
数目为
193608 / 2048
,也就是
94.54
,向上取整为
95
,相当于需要
95

step
。此外,我设置
initial_learning_rate

decay_rate
以及
decay_steps
分别为
0.1

0.95
以及
95
,且设置
staircase

True
。如下图所示。

此时,我们就可以对每一个参数的具体含义与作用加以介绍了。首先,我们开始训练神经网络模型,即
step
开始从
0
逐步增加;但是由于我的
staircase

True
,因此只要指数
(step / decay_steps)
是小于
1
的,那么都视作
0
(因为当前参数设置是对结果
向下取整
);而由于除了
0
以外任何数的
0
次方都是
1
,因此此时的公式
initial_learning_rate * decay_rate ^ (step / decay_steps)
始终等于
initial_learning_rate
,也就是一直保持
0.1
;只有当
step
到达我们设置的
decay_steps
之后,指数
(step / decay_steps)
才可以成为
1
,使得
decay_rate
终于产生了效果。而在这里,由于我故意设置
decay_steps

95
,因此按道理只要经过
1

epoch
之后,学习率就会下降——因为前面我们计算过了,在
1

epoch
中需要
95

step
。那么此时,学习率就变为了
0.1 * 0.95

接下来,我们运行上述代码,训练
6

epoch
,来验证一下学习率的变化是否如同我们的设想。

下图为
TensorBoard
中,学习率随着
epoch
的变化。这里需要注意,我这里截图的时候开了曲线图的平滑选项,因此应该以浅色的线为准。

上面的图因为不太全,所以或许看不出什么;我们直接将学习率变化情况导出,如下图所示。

其中,图中的
step
实际上表示的是
epoch
,大家这里理解即可。可以看到,在
epoch

0
时(也就是进行第一个
epoch
时),学习率一直为
0.1
;而进行到第二个
epoch
时——此时我们训练过程的
step
就应该是从
95
开始,但还不到
190
,因此
(step / decay_steps)
始终为
1
,学习率就是
0.1 * 0.95 = 0.095
了(因为数据格式问题,精度稍有差距);随后,进行到第三个
epoch
时——此时我们训练过程的
step
就应该是从
190
开始,但还不到
285
,因此
(step / decay_steps)
始终为
2
,学习率就已经是
0.1 * 0.95 * 0.95 = 0.09025
了。

由此可知,假如我将
decay_steps
扩大
10
倍,使得其为
950
,那么在前
10

epoch
时,学习率都不会发生改变,而从第
11

epoch
开始,学习率才会开始衰减。

这里我的参数
staircase
设置为
True
,因此会出现上述结果;相反的,如果设置为
False
,那么计算
(step / decay_steps)
时,是对结果
取小数
,换句话说只要
step
发生变化,那么当前对应的学习率也会发生变化,只不过变化的幅度会稍小一些。

由此看到,上述学习率的变化,是符合我们的预期的。当然,上图中最后两个
epoch
对应的学习率没有发生变化,这个具体原因我暂时也没搞清楚;不过学习率下降作为一种策略,我们通过上述代码,还是达到了动态调整学习率的需求的。

至此,大功告成。

标签: none

添加新评论