【深度学习-Day 18】从SGD到Adam:深度学习优化器进阶指南与实战选择
Langchain系列文章目录
01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南
02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖
03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南
04-玩转 LangChain:从文档加载到高效问答系统构建的全程实战
05-玩转 LangChain:深度评估问答系统的三种高效方法(示例生成、手动评估与LLM辅助评估)
06-从 0 到 1 掌握 LangChain Agents:自定义工具 + LLM 打造智能工作流!
07-【深度解析】从GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
08-【万字长文】MCP深度解析:打通AI与世界的“USB-C”,模型上下文协议原理、实践与未来
Python系列文章目录
PyTorch系列文章目录
机器学习系列文章目录
深度学习系列文章目录
Java系列文章目录
JavaScript系列文章目录
深度学习系列文章目录
01-【深度学习-Day 1】为什么深度学习是未来?一探究竟AI、ML、DL关系与应用
02-【深度学习-Day 2】图解线性代数:从标量到张量,理解深度学习的数据表示与运算
03-【深度学习-Day 3】搞懂微积分关键:导数、偏导数、链式法则与梯度详解
04-【深度学习-Day 4】掌握深度学习的“概率”视角:基础概念与应用解析
05-【深度学习-Day 5】Python 快速入门:深度学习的“瑞士军刀”实战指南
06-【深度学习-Day 6】掌握 NumPy:ndarray 创建、索引、运算与性能优化指南
07-【深度学习-Day 7】精通Pandas:从Series、DataFrame入门到数据清洗实战
08-【深度学习-Day 8】让数据说话:Python 可视化双雄 Matplotlib 与 Seaborn 教程
09-【深度学习-Day 9】机器学习核心概念入门:监督、无监督与强化学习全解析
10-【深度学习-Day 10】机器学习基石:从零入门线性回归与逻辑回归
11-【深度学习-Day 11】Scikit-learn实战:手把手教你完成鸢尾花分类项目
12-【深度学习-Day 12】从零认识神经网络:感知器原理、实现与局限性深度剖析
13-【深度学习-Day 13】激活函数选型指南:一文搞懂Sigmoid、Tanh、ReLU、Softmax的核心原理与应用场景
14-【深度学习-Day 14】从零搭建你的第一个神经网络:多层感知器(MLP)详解
15-【深度学习-Day 15】告别“盲猜”:一文读懂深度学习损失函数
16-【深度学习-Day 16】梯度下降法 - 如何让模型自动变聪明?
17-【深度学习-Day 17】神经网络的心脏:反向传播算法全解析
18-【深度学习-Day 18】从SGD到Adam:深度学习优化器进阶指南与实战选择
文章目录
- Langchain系列文章目录
- Python系列文章目录
- PyTorch系列文章目录
- 机器学习系列文章目录
- 深度学习系列文章目录
- Java系列文章目录
- JavaScript系列文章目录
- 深度学习系列文章目录
- 前言
- 一、基础梯度下降法的挑战
- 1.1 批量梯度下降 (Batch Gradient Descent, BGD)
- 1.2 挑战总结
- 二、随机梯度下降 (Stochastic Gradient Descent, SGD)
- 2.1 SGD 的核心思想
- 2.1.1 参数更新公式
- 2.2 SGD 的优缺点
- 2.2.1 优点
- 2.2.2 缺点
- 三、小批量梯度下降 (Mini-batch Gradient Descent)
- 3.1 Mini-batch GD 的核心思想
- 3.1.1 参数更新公式
- 3.2 Mini-batch GD 的优势
- 四、动量 (Momentum)
- 4.1 动量的核心思想
- 4.1.1 参数更新公式
- 4.2 动量的效果
- 4.2.1 Nesterov 加速梯度 (NAG)
- 五、自适应学习率算法
- 5.1 AdaGrad (Adaptive Gradient)
- 5.1.1 参数更新公式
- 5.1.2 AdaGrad 的优缺点
- 5.2 RMSprop (Root Mean Square Propagation)
- 5.2.1 RMSprop 的核心思想
- 5.2.2 参数更新公式
- 5.2.3 RMSprop 的优势
- 六、Adam (Adaptive Moment Estimation)
- 6.1 Adam 的核心思想
- 6.2 Adam 的参数更新公式
- 6.3 Adam 的优势
- 七、如何选择优化器?
- 7.1 常见选择策略
- 7.2 优化器可视化对比
- 7.3 代码实现示例 (PyTorch)
- 八、总结
前言
在【深度学习-Day 16】和【深度学习-Day 17】中,我们探讨了神经网络学习的动力——梯度下降法,以及高效计算梯度的核心——反向传播算法。我们理解了模型如何通过计算损失函数关于参数的梯度,并沿着梯度相反的方向更新参数来最小化损失。然而,基础的梯度下降法(尤其是批量梯度下降 BGD)在实践中面临诸多挑战,如训练速度慢、可能陷入局部最优等。为了更快、更稳定地训练深度神经网络,研究者们提出了一系列更先进的优化算法。本文将带您深入了解这些高级优化器,从经典的随机梯度下降(SGD)出发,逐步探索动量(Momentum)、AdaGrad、RMSprop,直至当今广受欢迎的 Adam 算法,并探讨它们各自的优缺点及适用场景。
一、基础梯度下降法的挑战
在深入了解高级优化器之前,我们先回顾一下基础梯度下降法,并明确它们面临的挑战。
1.1 批量梯度下降 (Batch Gradient Descent, BGD)
BGD 在每次参数更新时,都会计算整个训练数据集上的梯度。
- 优点: 梯度计算准确,每次更新都朝着全局最优的方向(对于凸函数)或一个好的局部最优方向前进,收敛路径相对平滑。
- 缺点:
- 计算成本高: 当数据集非常大时,每次迭代计算整个数据集的梯度会非常耗时。
- 内存需求大: 需要加载整个数据集到内存中。
- 可能陷入局部最优: 对于非凸函数,平滑的下降路径可能使其难以跳出局部最优解。
1.2 挑战总结
深度学习模型通常具有高度非凸的损失曲面和庞大的数据集,这使得 BGD 在实践中难以应用。我们需要更高效、更鲁棒的优化方法。
二、随机梯度下降 (Stochastic Gradient Descent, SGD)
为了解决 BGD 的计算效率问题,随机梯度下降(SGD)应运而生。
2.1 SGD 的核心思想
SGD 不再计算整个数据集的梯度,而是在每次更新时,随机选择 一个 训练样本来计算梯度并更新参数。
2.1.1 参数更新公式
对于样本 ( x ( i ) , y ( i ) ) (x^{(i)}, y^{(i)}) (x(i),y(i)),参数 W W W 的更新如下:
W = W − η ⋅ ∇ W L ( x ( i ) , y ( i ) ; W ) W = W - \eta \cdot \nabla_W L(x^{(i)}, y^{(i)}; W) W=W−η⋅∇WL(x(i),y(i);W)
其中, η \eta η 是学习率, L L L 是损失函数。
2.2 SGD 的优缺点
2.2.1 优点
- 更新速度快: 每次迭代只计算一个样本,速度非常快。
- 引入随机性: 梯度的随机性有助于跳出局部最优解,甚至可能找到更好的最优点。
2.2.2 缺点
- 高方差/噪音: 由于每次更新都基于单个样本,梯度估计的方差很大,导致收敛过程非常颠簸,损失函数曲线波动剧烈。
- 收敛不稳定: 可能不会精确收敛到最优点,而是在最优点附近徘徊。
- 学习率选择困难: 高方差使得选择合适的学习率更加困难。
三、小批量梯度下降 (Mini-batch Gradient Descent)
小批量梯度下降(Mini-batch GD)是 BGD 和 SGD 之间的一个折衷方案,也是目前深度学习中最常用的方法。
3.1 Mini-batch GD 的核心思想
它既不像 BGD 那样使用全部数据,也不像 SGD 那样只用一个样本,而是在每次更新时,选择一小批(mini-batch,通常大小为 32, 64, 128, 256 等)样本来计算梯度。
3.1.1 参数更新公式
对于一个大小为 m m m 的小批量样本 { ( x ( 1 ) , y ( 1 ) ) , . . . , ( x ( m ) , y ( m ) ) } \{ (x^{(1)}, y^{(1)}), ..., (x^{(m)}, y^{(m)}) \} {(x(1),y(1)),...,(x(m),y(m))},参数 W W W 的更新如下:
W = W − η ⋅ 1 m ∑ i = 1 m ∇ W L ( x ( i ) , y ( i ) ; W ) W = W - \eta \cdot \frac{1}{m} \sum_{i=1}^{m} \nabla_W L(x^{(i)}, y^{(i)}; W) W=W−η⋅m1i=1∑m∇WL(x(i),y(i);W)
3.2 Mini-batch GD 的优势
- 兼顾效率与稳定性: 相比 BGD,计算效率大大提高;相比 SGD,梯度估计更准确,收敛过程更稳定,波动更小。
- 利用并行计算: 可以充分利用现代 GPU 的并行计算能力,进一步加速训练。
尽管 Mini-batch GD 改善了 BGD 和 SGD 的许多问题,但它仍然面临一些挑战:
- 学习率选择: 仍然需要仔细选择一个合适的学习率。
- 所有参数共享学习率: 对所有参数使用相同的学习率可能不是最优的,因为不同参数的重要性或更新频率可能不同。
- 鞍点问题: 在高维空间中,相比局部最小值,鞍点(某些方向上是极大值,另一些方向上是极小值)更常见,Mini-batch GD 可能会在鞍点附近徘徊。
四、动量 (Momentum)
为了解决 Mini-batch GD 在鞍点附近和梯度变化剧烈区域的收敛问题,动量法被引入。
4.1 动量的核心思想
动量法模拟了物理学中的动量概念。想象一个球从山上滚下来,它不仅受到当前斜坡(梯度)的影响,还带有之前滚动的速度(动量)。这使得球在平坦区域或梯度方向变化时能够继续前进,并且在梯度方向一致时加速滚动。
4.1.1 参数更新公式
动量法引入了一个“速度”变量 v v v,它是过去梯度的指数加权平均值。
v t = β v t − 1 + ( 1 − β ) ∇ W L ( W t − 1 ) v_t = \beta v_{t-1} + (1 - \beta) \nabla_W L(W_{t-1}) vt=βvt−1+(1−β)∇WL(Wt−1)
W t = W t − 1 − η v t W_t = W_{t-1} - \eta v_t Wt=Wt−1−ηvt
通常,我们会看到一个稍有不同的、但效果类似的实现(尤其在很多框架中):
v t = β v t − 1 + η ∇ W L ( W t − 1 ) v_t = \beta v_{t-1} + \eta \nabla_W L(W_{t-1}) vt=βvt−1+η∇WL(Wt−1)
W t = W t − 1 − v t W_t = W_{t-1} - v_t Wt=Wt−1−vt
其中, β \beta β 是动量超参数(通常取 0.9 左右),它控制了过去梯度对当前速度的影响程度。
4.2 动量的效果
- 加速收敛: 当梯度方向一致时,动量会累积,使得更新步长变大,加速收敛。
- 抑制震荡: 当梯度方向变化时,动量可以抵消部分震荡,使更新路径更平滑。
- 克服鞍点和局部最优: 动量有助于冲过平坦区域(梯度接近零)或小的局部最优坑。
4.2.1 Nesterov 加速梯度 (NAG)
NAG 是动量法的一个变种,它更“聪明”一些。它不是计算当前位置的梯度,而是计算在“预估”的下一步位置(基于当前速度)的梯度。这使得它能提前感知到斜坡的变化,从而进行调整。
v t = β v t − 1 + η ∇ W L ( W t − 1 − β v t − 1 ) v_t = \beta v_{t-1} + \eta \nabla_W L(W_{t-1} - \beta v_{t-1}) vt=βvt−1+η∇WL(Wt−1−βvt−1)
W t = W t − 1 − v t W_t = W_{t-1} - v_t Wt=Wt−1−vt
NAG 通常比标准动量法有更好的性能。
五、自适应学习率算法
动量法主要关注梯度的方向和速度,而自适应学习率算法则关注为每个参数自动调整学习率。
5.1 AdaGrad (Adaptive Gradient)
AdaGrad 的核心思想是:对于那些过去梯度较大的参数,给予较小的学习率;对于过去梯度较小的参数,给予较大的学习率。它非常适合处理稀疏数据,因为不经常更新的参数会获得更大的学习率。
5.1.1 参数更新公式
AdaGrad 累积了每个参数过去所有梯度的平方和 G t G_t Gt:
G t = G t − 1 + ( ∇ W L ( W t − 1 ) ) 2 G_t = G_{t-1} + (\nabla_W L(W_{t-1}))^2 Gt=Gt−1+(∇WL(Wt−1))2
(这里的平方是逐元素平方)
参数更新如下:
W t = W t − 1 − η G t + ϵ ∇ W L ( W t − 1 ) W_t = W_{t-1} - \frac{\eta}{\sqrt{G_t + \epsilon}} \nabla_W L(W_{t-1}) Wt=Wt−1−Gt+ϵη∇WL(Wt−1)
其中, ϵ \epsilon ϵ 是一个很小的常数(如 10 − 8 10^{-8} 10−8),用于防止分母为零。
5.1.2 AdaGrad 的优缺点
- 优点: 自动调整学习率,无需手动设置;对稀疏数据表现好。
- 缺点: 学习率会随着训练的进行而单调递减,最终可能变得过小,导致模型无法继续学习。这是因为 G t G_t Gt 不断累积,分母会越来越大。
5.2 RMSprop (Root Mean Square Propagation)
RMSprop 是为了解决 AdaGrad 学习率过早衰减的问题而提出的(由 Geoff Hinton 在他的 Coursera 课程中提出,但未正式发表论文)。
5.2.1 RMSprop 的核心思想
它不再累积所有历史梯度的平方和,而是使用指数加权移动平均来计算梯度的平方和,这样只关注最近一段时间的梯度信息。
5.2.2 参数更新公式
S t = γ S t − 1 + ( 1 − γ ) ( ∇ W L ( W t − 1 ) ) 2 S_t = \gamma S_{t-1} + (1 - \gamma) (\nabla_W L(W_{t-1}))^2 St=γSt−1+(1−γ)(∇WL(Wt−1))2
W t = W t − 1 − η S t + ϵ ∇ W L ( W t − 1 ) W_t = W_{t-1} - \frac{\eta}{\sqrt{S_t + \epsilon}} \nabla_W L(W_{t-1}) Wt=Wt−1−St+ϵη∇WL(Wt−1)
其中, γ \gamma γ 是衰减率(通常取 0.9 或 0.99),控制了历史信息的遗忘速度。
5.2.3 RMSprop 的优势
- 缓解学习率衰减: 通过使用移动平均,避免了 AdaGrad 学习率过快下降的问题。
- 表现良好: 在很多应用中表现稳定且良好。
六、Adam (Adaptive Moment Estimation)
Adam 可能是目前最流行的深度学习优化算法之一,它结合了动量法和 RMSprop 的优点。
6.1 Adam 的核心思想
Adam 既利用了动量法中梯度的指数加权移动平均(一阶矩估计 m t m_t mt),也利用了 RMSprop 中梯度平方的指数加权移动平均(二阶矩估计 v t v_t vt),并对它们进行了偏差修正。
6.2 Adam 的参数更新公式
- 计算一阶矩估计 (动量):
m t = β 1 m t − 1 + ( 1 − β 1 ) ∇ W L ( W t − 1 ) m_t = \beta_1 m_{t-1} + (1 - \beta_1) \nabla_W L(W_{t-1}) mt=β1mt−1+(1−β1)∇WL(Wt−1) - 计算二阶矩估计 (类似 RMSprop):
v t = β 2 v t − 1 + ( 1 − β 2 ) ( ∇ W L ( W t − 1 ) ) 2 v_t = \beta_2 v_{t-1} + (1 - \beta_2) (\nabla_W L(W_{t-1}))^2 vt=β2vt−1+(1−β2)(∇WL(Wt−1))2 - 偏差修正: 由于 m 0 m_0 m0 和 v 0 v_0 v0 通常初始化为 0,在训练初期, m t m_t mt 和 v t v_t vt 会偏向于 0。因此,进行修正:
m ^ t = m t 1 − β 1 t \hat{m}_t = \frac{m_t}{1 - \beta_1^t} m^t=1−β1tmt
v ^ t = v t 1 − β 2 t \hat{v}_t = \frac{v_t}{1 - \beta_2^t} v^t=1−β2tvt - 参数更新:
W t = W t − 1 − η v ^ t + ϵ m ^ t W_t = W_{t-1} - \frac{\eta}{\sqrt{\hat{v}_t} + \epsilon} \hat{m}_t Wt=Wt−1−v^t+ϵηm^t
其中, β 1 \beta_1 β1 通常取 0.9, β 2 \beta_2 β2 通常取 0.999, η \eta η 是学习率, ϵ \epsilon ϵ 是 10 − 8 10^{-8} 10−8。
6.3 Adam 的优势
- 结合动量和自适应学习率: 既能加速收敛,又能为每个参数调整学习率。
- 计算高效: 只需要存储一阶和二阶矩。
- 内存需求小: 适合大规模数据和参数。
- 对超参数选择相对鲁棒: 通常使用默认的 β 1 \beta_1 β1 和 β 2 \beta_2 β2 就能获得不错的效果,主要调整学习率 η \eta η。
- 表现优异: 在各种深度学习任务中通常表现出色,被广泛用作默认优化器。
七、如何选择优化器?
没有一个“万能”的优化器能在所有任务上都表现最好。选择哪个优化器取决于具体任务、数据集特性、模型结构以及计算资源。
7.1 常见选择策略
- Adam 作为起点: 如果你不确定选哪个,Adam 通常是一个很好的、安全的起点,它在大多数情况下都能提供不错的性能和较快的收敛速度。
- SGD + Momentum (NAG): 尽管 Adam 很流行,但精心调整的 SGD + Momentum (尤其是 NAG) 常常能在最终性能上超越 Adam,并且可能泛化得更好。但这需要更多的超参数调优经验(尤其是学习率和动量)。
- 考虑数据特性: 如果你的数据非常稀疏,AdaGrad 或 RMSprop 可能是值得考虑的。
- 实验与评估: 最好的方法是通过实验来比较不同优化器在你的特定任务上的表现。
7.2 优化器可视化对比
下面是一个(概念性的)Mermaid 流程图,展示了不同优化器在寻找最小值的路径上的可能差异。
- SGD: 路径通常非常抖动,因为它对每个样本都做出反应。
- Momentum: 路径更平滑,能“冲过”小的波动和鞍点。
- AdaGrad/RMSprop: 路径会根据梯度的历史进行调整,在梯度大的方向步长小,梯度小的方向步长大。
- Adam: 结合了 Momentum 和 RMSprop 的特点,通常能快速、平稳地收敛。
7.3 代码实现示例 (PyTorch)
在 PyTorch 中使用这些优化器非常简单,你只需要选择你想用的优化器并传入模型参数和学习率即可。
import torch
import torch.optim as optim
from torch.nn import Module# 假设你有一个模型实例 model = MyModel()
# model.parameters() 会返回模型中所有需要训练的参数# 使用 SGD
optimizer_sgd = optim.SGD(model.parameters(), lr=0.01)# 使用 SGD + Momentum
optimizer_momentum = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)# 使用 Nesterov Accelerated Gradient (NAG)
optimizer_nag = optim.SGD(model.parameters(), lr=0.01, momentum=0.9, nesterov=True)# 使用 AdaGrad
optimizer_adagrad = optim.Adagrad(model.parameters(), lr=0.01)# 使用 RMSprop
optimizer_rmsprop = optim.RMSprop(model.parameters(), lr=0.001, alpha=0.99)# 使用 Adam
optimizer_adam = optim.Adam(model.parameters(), lr=0.001, betas=(0.9, 0.999))# 在训练循环中:
# 1. 清零梯度
# optimizer_adam.zero_grad()
# 2. 计算损失
# loss = criterion(outputs, labels)
# 3. 反向传播
# loss.backward()
# 4. 更新参数
# optimizer_adam.step()
八、总结
本文深入探讨了深度学习中常用的高级优化算法,它们旨在克服基础梯度下降法的局限性,实现更快、更稳定的模型训练。
- 基础回顾: 我们认识到 BGD 计算昂贵,而 SGD 波动剧烈。
- Mini-batch GD: 作为 BGD 和 SGD 的折衷,它是现代深度学习训练的基石。
- 动量法 (Momentum & NAG): 通过引入速度概念,加速收敛并抑制震荡,有助于克服鞍点和局部最优。
- 自适应学习率 (AdaGrad & RMSprop): 通过为每个参数动态调整学习率,AdaGrad 适合稀疏数据但学习率会衰减,RMSprop 则通过移动平均缓解了这个问题。
- Adam: 结合了动量和 RMSprop 的优点,成为当前最常用、表现稳健的优化器之一,通常作为首选。
- 选择策略: 没有绝对最好的优化器,Adam 是优秀的起点,但 SGD+Momentum 经仔细调优可能获得更好泛化性,最终选择应基于实验。
理解这些优化器的原理和特性,对于诊断训练问题、提升模型性能至关重要。它们是驱动庞大神经网络不断学习、逼近最优解的强大“引擎”。在接下来的文章中,我们将开始接触强大的深度学习框架,看看如何利用它们轻松构建和训练模型。