SGD and Adam
参考:Understanding Deep Learning Chapter 6. Fitting Models
From GD to SGD
Gradient Descent 在优化 ML 模型的高维非凸损失函数时,通常会遇到 1. 局部极小值 2. 鞍点 问题。
这些问题与初始参数选择有关,不具有随机性,可能会导致梯度下降停在局部极小值或鞍点上。为了解决这些问题,随机梯度下降(SGD)被提出。
SGD 仅通过 batch 来小批量计算梯度,实现了参数更新方向的随机化。在一个 epoch 内遍历所有 batch 时,参数总会找到不同的梯度方向,从而避免停在局部极小值或鞍点上。SGD 的更新公式为: \[\phi_{t+1} \gets \phi_t - \alpha \cdot \sum_{i \in \mathcal{B}_t} \frac{\partial \ell_i[\phi_t]}{\partial \phi}\]
\(\mathcal{B}_t\) 是在一个 epoch 内的第 \(t\) 个 batch。
Adam Optimizer
Adam 是一种自适应学习率优化算法,结合了 Momentum 和 RMSProp 的优点。它通过计算梯度的一阶矩(均值)和二阶矩(方差)来调整每个参数的学习率。
Momentum
Momentum 动量:
\[\mathbf{g}_{t} = \sum_{i \in \mathcal{B}_t} \frac{\partial \ell_i[\phi_t]}{\partial \phi}\]
\[\mathbf{m}_{t+1} \gets \beta \cdot \mathbf{m}_t + (1 - \beta) \cdot \mathbf{g}_{t}\]
\[\phi_{t+1} \gets \phi_t - \alpha \cdot \mathbf{m}_{t+1}\]
其中 \(\beta \in [0.9, 0.99]\), \(\mathbf{m}_0 = 0\)。
动量的本质是梯度随时间的累积,包含过去所有梯度的指数加权平均。这种类似于凸优化中的共轭梯度方法,目的是提供惯性,减少梯度的震荡,使参数更新更平滑,从而加速收敛。
RMSProp
RMSProp 是一种自适应学习率方法,通过计算梯度的二阶矩来调整每个参数的学习率,防止学习率过大或过小。它的更新公式为:
\[\mathbf{v}_{t+1} \gets \gamma \cdot \mathbf{v}_t + (1 - \gamma) \cdot \mathbf{g}_{t}^2\]
\[\phi_{t+1} \gets \phi_t - \alpha \cdot \frac{\mathbf{g}_{t+1}}{\sqrt{\mathbf{v}_{t+1}} + \epsilon}\]
其中 \(\gamma \in [0.9, 0.99]\), \(\epsilon = 1e-8\),防止除零错误;\(\mathbf{v}_0 = 0\)。
这里的 \(\mathbf{g}_{t}^2\) 是对 \(\mathbf{g}_{t}\) 的逐元素平方,因而是二阶矩,用来衡量每个参数的梯度的绝对值大小,然后用这个值做缩放,使梯度大时学习率小,梯度小时学习率大。相当于原来的学习率 \(\alpha \rightarrow \alpha / \sqrt{\mathbf{v}_{t+1}}\),使得每个参数的学习率根据梯度的二阶矩进行自适应调整。
Adam Optimizer
Adam = Adaptive moment estimation 结合了 Momentum 和
RMSProp,同时使用一阶矩和二阶矩,兼具抑制震荡和自适应更新学习率的优点。Adam
的更新公式为:
\[\mathbf{g}_{t} = \sum_{i \in \mathcal{B}_t} \frac{\partial \ell_i[\phi_t]}{\partial \phi}\]
\[\mathbf{m}_{t+1} \gets \beta \cdot \mathbf{m}_t + (1 - \beta) \cdot \mathbf{g}_{t}\]
\[\mathbf{v}_{t+1} \gets \gamma \cdot \mathbf{v}_t + (1 - \gamma) \cdot \mathbf{g}_{t}^2\]
\[\phi_{t+1} \gets \phi_t - \alpha \cdot \frac{\mathbf{m}_{t+1}}{\sqrt{\mathbf{v}_{t+1}} + \epsilon}\]
偏差校正
训练开始时 \(\mathbf{m}_0 = 0, \mathbf{v}_0 = 0\),导致初始时刻的一阶矩和二阶矩估计偏小。为了防止起步时的失真(我认为这里由于 \(\mathbf{m}_t, \sqrt{\mathbf{v}_t}\) 是同级别的,很难说如果不修正,最终的更新量会偏大还是偏小,但总归是失真),Adam 引入了偏差校正:
\[\hat{\mathbf{m}}_{t+1} = \frac{\mathbf{m}_{t+1}}{1 - \beta^{t+1}}\] \[\hat{\mathbf{v}}_{t+1} = \frac{\mathbf{v}_{t+1}}{1 - \gamma^{t+1}}\]
\[\phi_{t+1} \gets \phi_t - \alpha \cdot \frac{\hat{\mathbf{m}}_{t+1}}{\sqrt{\hat{\mathbf{v}}_{t+1}} + \epsilon}\]
从而在训练初期,\(\hat{\mathbf{m}}_t, \hat{\mathbf{v}}_t\) 能更接近单步梯度的结果,而随着时间的推移,偏差校正的影响指数衰减,过渡到稳定状态。
AdamW
AdamW 是 Adam 的一个变种,主要区别在于权重衰减的处理方式。AdamW 将权重衰减作为独立的正则化项,而不是将其包含在梯度计算中。这种方法可以更有效地控制模型的复杂度,防止过拟合。
具体来说,在 Adam 中,可以指定权重衰减系数 \(\lambda\) =
weight_decay,它在计算梯度时会被加到梯度上: \[\mathbf{g}_{t} = \sum_{i \in \mathcal{B}_t}
\frac{\partial \ell_i[\phi_t]}{\partial \phi} + \lambda \cdot
\phi_t\]
这相当于在损失函数中添加了一个正则化项, \[Loss = \ell + \frac{\lambda}{2} ||\phi||^2\]
这样做导致当前参数 \(\phi_t\) 被加入至 \(\mathbf{g}_t\) 后,继续参与一二阶矩的计算,与梯度更新的历史耦合在一起,影响了动量和自适应学习率的效果。
而 AdamW 则将权重衰减独立出来,在参数更新时单独应用,而不是加入到梯度中: \[\phi_{t+1} \gets \phi_t - \alpha \cdot \frac{\hat{\mathbf{m}}_{t+1}}{\sqrt{\hat{\mathbf{v}}_{t+1}} + \epsilon} - \alpha \cdot \lambda \cdot \phi_t\]
这种方式确保了权重衰减不会影响动量和自适应学习率的计算,从而提高了优化过程的稳定性和效果。
