优化器方法总结
日期:2024-05-13 09:10 | 人气:
梯度优化算法,简而言之就是利用目标函数的梯度进行优化。利用一阶梯度的优化算法,也就是常说的梯度下降优化算法以及基于此的一些优化,二阶梯度优化算法称为牛顿算法。本文主要介绍第一种即一阶梯度优化算法。
一阶梯度的优化公式为:
其中 为学习率, 为梯度计算。
从上式可以看出,针对梯度优化的算法,主要包括两方面:一个是梯度的计算,一个是学习率的设置。本文综合一些参考文献 Juliuszh:一个框架看懂优化算法之异同 SGD/AdaGrad/Adam 提到的统一框架,对各种优化算法(梯度的计算)进行统一描述,对学习率的设置做简要介绍。
加速训练、收敛
找到最优解
- 优化训练样本的大小:mini-batch,计算mini-batch大小的样本的loss和梯度,更新参数,不需要计算所有样本的loss和梯度,速度加快
- 优化梯度计算:动量梯度下降优化算法,RMSprop, Adam。
- 优化学习率:学习率衰减
待优化参数:
目标函数(损失函数):
初始学习率:
通过一个统一的优化器框架,方便比较掌握各种优化器的不同与优缺点。
训练过程中进行迭代优化。在每个batch:
1. 计算目标函数对于当前参数的梯度:
2. 根据历史梯度计算一阶动量和二阶动量:
3. 计算当前时刻的下降梯度:
4.根据下降梯度进行更新:
各种优化器的主要差别在前两个步骤,步骤3和4是一致的。
优化器方法,主要对应优化梯度计算的方法
SGD为随机梯度下降
SGD没有动量概念,即没有考虑历史梯度:
即梯度下降为:
梯度更新为:
随机梯度下降经常代指mini-batch梯度下降,即对mini-batch size (n)的样本计算目标函数
mini-batch梯度下降,介于BGD(batch gradient desent)和完全的随机梯度下降方法之间。前者需要对所有样本进行计算然后更新梯度,后者只需要对一个样本进行计算就更新梯度。
- BGD:更新速度慢,不能在线更新,对于凸损失函数,收敛于全局最小值。对于非凸损失函数,收敛于局部最小值。
* 完全随机梯度下降:更新速度快,可用于在线更新,但是会发生震荡,噪声大。当缓慢降低学习率 时,收敛行为类似于BGD。
- MBSGD:相比完全随机梯度下降,参数更新会更加稳定。
存在问题:
- 学习率选择困难
- 对所有参数采用相同的学习率
- 可能困在局部最小值
Nesterov momentum is a different version of the momentum method which has stronger theoretical converge guarantees for convex functions.
考虑历史梯度计算一阶动量(类似惯性),减少了随机梯度的震荡,并加速了训练。
梯度更新为:
通常设置 的值为0.9,即时刻t的主要下降方向由此前累积的下降方向决定,并略微偏向当前时刻的梯度方向。
SGD可能困在局部沟壑里,相比SGDM,NAG中的梯度会计算下一步位置的梯度。即 。通过计算下一步位置的梯度,实现向前多看一步,减少困在局部沟壑里的可能性。
在RNN的模型任务中,NAG的效果较好。
对不同的参数采用不同的学习率,对于更新频繁的参数,采用较小的学习率;对于更新不频繁的参数,采用较大的学习率。
通过计算历史二阶动量来衡量历史更新频率:
其中i为参数的索引.
目标函数当前参数i的梯度为:
下降梯度为:
其中 为平滑参数。
这一方法在稀疏数据场景下表现很好,如在Glove训练word embedding的训练中。学习率由 变为了 ,学习率会自动更新,但是随着二阶动量的积累,学习率会逐渐变小。
AdaGrad单调递减的学习率源于历史梯度的积累,AdaDelta中不累积全部历史梯度,而只关注过去一段时间窗口的下降梯度。这就是Delta的由来。
指数移动平均值大约就是过去一段时间的平均值,因此通过这一方法计算二阶累积动量:
这样避免了二阶动量持续累积,导致学习率逐渐变小为零导致训练过程提前结束的问题。
SGD-M是在SGD基础上增加了一阶动量,AdaGrad和AdaDelta是在SGD的基础上增加了二阶动量。Adam是将一阶动量与二阶动量都结合了起来,Adam=Adaptive+Momentum
一阶动量:
二阶动量:
超参 控制一阶动量, 控制二阶动量
实际使用过程中,参数的经验值是
初始化时 会接近于0,尤其是在迭代初期和 接近于1的情况下。这种估计会有问题,需要修正,修正如下:
最终的梯度更新为:
SGD利用了目标函数的一阶导数,为一阶优化方法。牛顿算法利用了目标函数的二阶导数信息,为二阶优化算法。但由于二阶导数导致参数量过大,计算复杂,导致牛顿算法并不流行。
Momentum、AdaGrad、Adam等方法,利用了一阶导数的变化信息(如历史一阶导数、下一时刻的导数),与牛顿算法二阶导数本质上是利用了一阶导数的梯度信息一致,所以Momentum、AdaGrad、Adam等算法,也可以看做是近似二阶优化方法。
ref:
Intro to optimization in deep learning: Momentum, RMSProp and Adam
https://medium.com/@vinodhb95/momentum-optimizer-6023aa445e18
学习率的变化有多种方法,包括学习率衰减、warmup等,如一般在模型训练的初始阶段通过warmup的方式,逐渐增大学习率,在后期阶段通过学习率衰减的方式组件逼近最优值(bert的训练中也采用了这种方式)。这里以学习率衰减为例,介绍在keras中的实现。
keras中设置学习率衰减的方法
- 创建衰减函数
- LearningRateScheduler(decay_method) , LearningRateScheduler为callback的子类
- model.fit(callbacks=[LearningRateScheduler])
def step_decay(epoch):
initial_lrate = 0.1
drop = 0.5
epochs_drop = 10.0
lrate = initial_lrate * math.pow(drop,
math.floor((1+epoch)/epochs_drop))
return lrate
lrate = LearningRateScheduler(step_decay)
class LossHistory(keras.callbacks.Callback):
def on_train_begin(self, logs={}):
self.losses = []
self.lr = []
def on_epoch_end(self, batch, logs={}):
self.losses.append(logs.get(‘loss’))
self.lr.append(step_decay(len(self.losses)))
loss_history = LossHistory()
lrate = LearningRateScheduler(step_decay)
callbacks_list = [loss_history, lrate]
history = model.fit(X_train, y_train,
validation_data=(X_test, y_test),
epochs=epochs,
batch_size=batch_size,
callbacks=callbacks_list,
verbose=2)
As a digression, a callback is a set of functions to be applied at given stages of the training procedure
ref:
Ref:
Juliuszh:一个框架看懂优化算法之异同 SGD/AdaGrad/Adam
Juliuszh:Adam那么棒,为什么还对SGD念念不忘 (2)—— Adam的两宗罪
骆梁宸:从 SGD 到 Adam —— 深度学习优化算法概览(一)
深度学习--优化器算法Optimizer详解(BGD、SGD、MBGD、Momentum、NAG、Adagrad、Adadelta、RMSprop、Adam) - 云+社区 - 腾讯云
大力再出奇迹,1024 张TPU,65536 batch size,仅76分钟训练完BERT!
An overview of gradient descent optimization algorithms
“让Keras更酷一些!”:小众的自定义优化器 - 科学空间|Scientific Spaces
https://towardsdatascience.com/custom-optimizer-in-tensorflow-d5b41f75644a
Reducing BERT Pre-Training Time from 3 Days to 76 Minutes
Scaling SGD Batch Size to 32K for ImageNet Training
LARGE BATCH TRAINING OF CONVOLUTIONAL NETWORKS