直觉:下山

想象你在一片雾中的山上,想走到谷底。

看不见整座山,但能感觉到脚下的坡度。

策略:每一步都朝当前位置最陡的下坡方向走一小步。反复如此,最终会到达一个低点。

这就是梯度下降(Gradient Descent)。

数学

目标:最小化损失函数 L(θ),其中 θ 是模型的所有参数。

梯度 ∇L(θ):指向函数上升最快的方向。

因此,负梯度方向是下降最快的方向。

更新规则:

θ ← θ - α · ∇L(θ)

  • α(学习率,Learning Rate):每一步的步长;
  • ∇L(θ):损失对参数的梯度。

反复迭代,直到收敛。

学习率:最关键的超参数

太大:

  • 可能"跳过"最优点;
  • 损失震荡甚至发散(越训练越差)。

太小:

  • 收敛极慢;
  • 可能卡在局部最优点或鞍点附近。

实践做法:

  • 从常用的默认值开始(如 1e-3、3e-4,取决于模型和优化器);
  • 用学习率调度(Learning Rate Schedule)——训练中动态调整:

    • 衰减:随训练逐渐减小;
    • 预热(Warmup):初期从小学习率逐步增大(在大模型训练中几乎是必需的,因为初期梯度可能很大);
    • 余弦退火(Cosine Annealing):按余弦曲线衰减;
    • 自适应:根据验证集表现调整(ReduceLROnPlateau)。

三种变体

一、批量梯度下降(Batch GD)

用全部训练数据计算梯度。

  • 优点:梯度方向准确、稳定;
  • 缺点:每次更新都要遍历全部数据——极慢,且无法在线学习。

二、随机梯度下降(SGD)

每次只用一个样本计算梯度。

  • 优点:更新快,可以在线学习;
  • 缺点:梯度噪声极大(单个样本的方向不代表整体方向),损失曲线抖动剧烈。

三、小批量梯度下降(Mini-batch GD)✅

每次用一小批样本(如 32、64、256 个)计算梯度。

这是实际的默认选择——兼顾了:

  • 梯度的稳定性(比单样本准确得多);
  • 计算的效率(可以充分利用 GPU 的并行能力);
  • 一定的噪声(这种噪声反而是有益的——见下)。

batch size 的选择:

  • 太小:噪声大,训练不稳定,GPU 利用率低;
  • 太大:GPU 内存可能不够,且梯度过于"确定"——可能陷入尖锐的局部最优,泛化变差;
  • 常见的范围:32–1024,取决于模型、数据和硬件。

有意思的发现:适度的小 batch 噪声有助于泛化 ——它使模型不容易陷入"尖峰"型的解(尖锐的局部最优),而倾向于找到"平坦"的解(对参数扰动不敏感,泛化更好)。

进阶优化器

朴素 SGD 的问题:

  • 所有参数共享同一个学习率;
  • 在"峡谷"形的损失曲面上(一个方向陡峭、另一个方向平缓)会震荡;
  • 容易卡在鞍点(梯度为 0 但不是极值点——在高维空间中,鞍点远比局部最优多)。

一、动量(Momentum)

思路:引入"惯性"——累积过去梯度的方向。

v ← μ·v + ∇L(θ)
θ ← θ - α·v

效果:

  • 在持续同向的方向上加速;
  • 在震荡的方向上相互抵消;
  • 像球滚下山坡——会冲过小的坑洼。

二、自适应学习率方法

核心思想:为每个参数维护独立的学习率——根据梯度的历史大小调整。

AdaGrad:累积梯度的平方,梯度大的参数学习率变小。

问题:学习率单调递减,可能过早停止学习。

RMSProp:用指数移动平均代替累积——解决了 AdaGrad 的问题。

Adam(最流行):

结合了动量 + 自适应学习率。

m ← β₁·m + (1-β₁)·∇L     (一阶矩,梯度均值)
v ← β₂·v + (1-β₂)·(∇L)²  (二阶矩,梯度平方均值)
θ ← θ - α · m̂ / (√v̂ + ε)

优点:

  • 对学习率的选择相对鲁棒;
  • 收敛快;
  • 几乎是所有任务的合理默认选择。

AdamW:Adam + 解耦的权重衰减(正确的 L2 正则化实现)——这是训练 Transformer 等模型的标准选择。

有意思的现象:尽管 Adam 收敛快,但在某些任务(如图像分类的某些设置)上,SGD + 动量 + 精心调度的学习率可能获得更好的最终泛化性能。

实践建议:先用 AdamW 快速验证和迭代;如果追求极致性能,可以尝试 SGD + 动量。

梯度是怎么算出来的:反向传播

神经网络有数百万到数千亿个参数——如何高效计算所有参数的梯度?

反向传播(Backpropagation):

核心:链式法则 + 动态规划(复用中间结果)。

过程:

  1. 前向传播:计算每一层的输出,直到得到损失;
  2. 反向传播:从损失开始,逐层向后计算梯度——每一层的梯度可以基于后一层的梯度算出;
  3. 所有中间结果(激活值)被缓存并复用。

复杂度:反向传播的计算量约等于前向传播的 2 倍——这使得训练大规模网络成为可能。

现代的深度学习框架(PyTorch、TensorFlow、JAX)都实现了自动微分——你只需定义前向计算,框架自动构建计算图并计算梯度。

局部最优与鞍点

一个常见的担忧:"梯度下降会卡在局部最优。"

现代的理解:

在高维空间中,真正的"局部最优"很少——更常见的是鞍点(某些方向是极小,某些方向是极大)。

原因:要成为局部最优,需要在所有维度上都是极小值——维度越高,这个概率呈指数下降。

而鞍点是可以逃离的:

  • 梯度的随机噪声(SGD 的小批量噪声);
  • 动量;
  • 自适应方法。

因此,在高维深度学习中,"卡在局部最优"通常不是主要障碍——更常见的困难是:

  • 梯度消失/爆炸(通过残差连接、归一化等解决);
  • 损失曲面过于平坦/陡峭(通过归一化、学习率调度解决)。

一句话

梯度下降的优雅之处在于:你不需要知道整座山的样子——只需要知道脚下哪边更低。

这个简单的想法,支撑了几乎所有现代机器学习的训练过程。

说明:本文为机器学习的知识整理。