深度学习 - 网络的优化 Optimisation for Training Deep Networks
深度学习问题需要一个损失函数,我们的目标就是通过优化算法来最小化损失,即最小化目标(损失)函数。需要注意的是,优化和深度学习的本质目标有差异,优化关注的是最小(最大)化目标,深度学习更关注模型。比如说,优化,也就是训练阶段,目标是最小化训练误差,但深度学习的目标是减小泛化误差,也就是推理阶段的误差。
最小化目标函数
最小化目标函数时,经常遇到的问题就是梯度消失,下述几种情况可能导致梯度消失。
局部最小值:某点的函数值小于其附近所有点的函数值,为局部最小值;整个函数域内的最小值为全局最小值。当目标函数接近局部最优时,梯度会接近0。使用一定程度的噪声(SDG)可以让参数跳出局部最优。
鞍点(saddle point):一个不是局部极值点的驻点称为鞍点。此时函数的梯度为 0,但该点既非局部最小值、也非局部最大值的位置。这种情况下优化也会停止。下面两种情况为函数 和的鞍点。
驻点(stationary point):函数的一阶导数为零的点。
拐点(inflection point):在一条连续曲线上,曲线的凹凸性发生改变的点。
凸 Convex
英文的逆天性在凹(concave)凸(convex)这两个单词上得到了极大体现。凹进去的函数是凸函数,凸出来的函数是凹函数。。。
凸函数最重要的一个特性就是:局部极小值就是全局极小值。也就是说,在最小化损失函数时,如果损失函数是凸函数,就不必担心陷入局部最小值的问题。
此外,凸优化的另一个特性是能有效处理约束。先明确啥是约束优化问题:
比如在训练中,我们的目标是最小化损失函数,不过给定了 一个 的可行域。
理论核心:拉格朗日函数。
直接求解带约束的优化问题较难,拉格朗日函数通过引入拉格朗日乘数,将约束条件融入目标函数,将约束优化问题转化为无约束的鞍点优化问题。
公式中,是拉格朗日乘数,非负实数。
若约束未激活,,参数在可行域内,则 ,约束项在函数中消失。
若约束激活, ,参数在可行域边界,则 ,约束项仍在函数中消失。
这被称作互补松弛条件,即乘积必须为零。互补松弛条件帮助我们在优化过程中判断哪些约束是活跃的,哪些是松弛的。
拉格朗日函数最优解是鞍点。
对 最小化 :等价于在约束条件下最小化目标函数
对 最大化 :等价于找到最合适的约束。
实践方法:
深度学习的损失函数并不总是凸函数,精确求解鞍点也不一定可行。
惩罚方法:直接保留拉格朗日函数的$a_ic_i$项,加入到原损失函数中,获得新的优化目标。
经典的惩罚方法例子包括权重衰减(Weight Decay, L2正则化)。
权重衰减的约束函数为:
权重衰减的惩罚项及最终优化目标为:
投影方法
惩罚方法属于软约束,投影方法属于硬约束。无论参数优化到哪里,都被强制投影回可行域内,确保约束被严格满足。
典型方法包括梯度截断(Gradient Clipping)。
梯度下降 Gradient Decent
GD每次迭代使用全部训练样本计算梯度,然后统一更新参数,计算量巨大,因此有人提出了随机梯度下降(SGD),SGD是对GD的无偏估计,可以看出二者数学期望一致:
SGD每次迭代随机选取一个样本计算梯度,然后更新参数。
不过SGD收敛不稳定,更新路径震荡比较大,对学习率也比较敏感,因此引入了动态学习率的概念:
为了平衡GD的稳定性和SGD高效性,有人提出了MiniBatch GD,即小批量梯度下降。这是目前DL的主流选择。GD和SGD在工程中使用极少,如果提到了,除非特别说明,否则使用的一般是MiniBatch GD。算法库中API的SGD实际上使用的也是MiniBatch GD。下文中SGD如不加说明均指MiniBatch GD。
动量法 Momentum
核心是利用过去梯度的加权平均替代瞬时梯度。
动态学习率解决的是训练过程中如何调整学习率的问题,动量法主要解决梯度噪声导致下降方向不稳定的问题。
SGD本身通过平均Batch内的梯度以减小方差,动量法的泄露平均值(Leaky Ave)是在时间维度上,对过去梯度做加权平均,以进一步降低方差。
其中:
:动量,梯度的累计
:动量系数,对过去梯度的记忆程度
:$t-1$时刻的瞬时梯度(SGD梯度)
公式递归展开可以得到:
大的 说明对过去梯度记忆久,相当于长期平均;小的 说明仅关注近期梯度。
AdaGrad
全称 Adaptive Gradient,即自适应梯度算法,是梯度下降算法的一种改进。在一般的SGD中,学习率是统一的,AdaGrad认为不同的参数需要不同的学习率。
最终目的是在凸函数优化上能够快速收敛。
梯度平方的累积量更新:
参数更新:
其中:
:参数 的梯度
:初值为0, 的累计平方和
:学习率
:极小常数避免分母为0
自动调整的方式就是将学习率 除以 来实现的。
RMSProp
均方根传播,全称 Root Mean Square Propagation。是AdaGrad的改进:
梯度平方的累积量更新:
参数更新:
加入了一个衰减系数 ,取值范围 [0,1]。衰减系数可以避免 的无限增大和AdaGrad学习率消失的问题。
AdaDelta
改进的RMSProp,去掉了学习率,完全不需要设置学习率。
梯度平方的累计量更新:
修正后的梯度计算:
参数值更新:
参数变化量平方的累计量更新:
这里的 为衰减系数。
太复杂的公式不用记,只需要知道AdaDelta使用 来替代了原本的学习率,让算法学习率的变化更加Adaptive。
Adam
全称Adaptive Moment Estimation,整合了RMSProp和Momentum方法。
Adam可以说是目前DL中使用频率最高的优化方法了。
融合Momentum的惯性特性,即梯度的指数移动平均:
参考RMSProp自适应学习率,梯度平方的指数移动平均:
一般将 和 分别设为0.9和0.999。
为了避免初始偏差过大,对上述 和 进行修正:
参数最终更新:
Pytorch中已经对上述优化方法提供了直接的参数实现:
# 1 带动量的SGD (Momentum)
model_momentum = LinearModel()
optimizer_momentum = optim.SGD(model_momentum.parameters(), lr=lr, momentum=0.9) # momentum=0.9是常用值
loss_momentum = train_model(model_momentum, optimizer_momentum, epochs)
# 2 Adagrad
model_adagrad = LinearModel()
optimizer_adagrad = optim.Adagrad(model_adagrad.parameters(), lr=lr) # 自适应学习率,无需手动调momentum
loss_adagrad = train_model(model_adagrad, optimizer_adagrad, epochs)
# 3 RMSprop
model_rmsprop = LinearModel()
optimizer_rmsprop = optim.RMSprop(model_rmsprop.parameters(), lr=lr, alpha=0.99) # alpha是移动平均系数
loss_rmsprop = train_model(model_rmsprop, optimizer_rmsprop, epochs)
# 4 Adam
model_adam = LinearModel()
optimizer_adam = optim.Adam(model_adam.parameters(), lr=lr, betas=(0.9, 0.999)) # betas是两个动量系数
loss_adam = train_model(model_adam, optimizer_adam, epochs)参考文章
[2] 11. 优化算法 — 动手学深度学习 2.0.0 documentation
[3] Anderson, S. (n.d.). Lecture 5 Optimisation for Training Deep Networks [Lecture]. In ACS61011 Deep Learning. University of Sheffield.
评论