梯度与梯度下降

首先,梯度是一个向量,指向函数在某点上增长最快的方向,那么梯度的负方向,也就是负梯度,指向函数值下降最快的方向

在模型训练中,我们会定义一个损失函数$L(\theta)$,等于模型输出与真实标签之间的差异,我们希望找到一组参数$\theta$,使得损失最小,这就变成了一个最优化问题minimize $L(\theta)$,于是我们用梯度下降法$\theta \leftarrow \theta - \alpha \cdot \nabla L(\theta)$,意义就是每次沿着负梯度方向走一点,逐步让损失减少,逼近局部极小值或者鞍点

方法 BGD(Batch Gradient Descent) SGD(Stochastic Gradient Descent) Mini-batch Gradient Descent
每次更新用数据量 全部样本 一个样本 一部分样本(如 32、64)
梯度估计 精确,无噪声 噪声大,变化剧烈 有一定噪声,平衡两者
更新频率 每轮 1 次 每轮 $n$ 次($n$ 为样本数) 每轮 $n / b$ 次($b$ 为 batch 大小)
收敛路径 平滑、稳定 抖动、震荡明显 相对平滑,偶有波动
收敛速度 慢(每步贵) 快(每步便宜) 快速而稳定
最终精度 高,容易收敛到最优点 较低,常震荡于最优点附近 高,可精确收敛
是否能跳出局部最优 难(因无噪声) 容易(噪声大可扰动) 适中(适度噪声)
资源占用 高(需一次加载所有数据) 低(单样本) 中等(小批量)
实现复杂度 简单 简单 稍复杂(需划分 batch)
实用性(深度学习) 差(不常用) 中(用于在线学习或高频任务) 高(主流方法,适合 GPU 并行)

学习率及其影响

上述公式中的$\alpha$也就是学习率,控制步长,影响收敛的速度,稳定性和最终性能

过大:参数更新步长过大,可能导致模型在损失函数极小值附近震荡(来回跳跃,无法收敛);更严重时会导致训练过程发散(不断越过最优解,甚至Loss越来越大)

过小:虽然模型在理论上可以收敛,但是收敛速度极慢,训练迭代次数大大增加,耗时耗资源;再者因为步子小,难以跳出陷阱,所以更容易陷入局部极小值或鞍点,对于非凸函数而言,陷入局部极小值或鞍点就意味着提前停止优化,导致模型性能不佳(言外之意,如果是凸函数梯度降到0后,停止了也无所谓,因为不存在鞍点,已经达到了全局极小值)

AdaGrad

AdaGrad 是最早提出的自适应学习率算法,思想是:历史梯度大 → 降低学习率,避免震荡;历史梯度小 → 保持学习率,继续优化。

更新公式:

  • 累积梯度平方:
    $$ G_t = G_{t-1} + g_t^2 $$
  • 参数更新:
    $$ \theta_{t+1} = \theta_t - \frac{\alpha}{\sqrt{G_t + \epsilon}} \cdot g_t $$

其中:

  • $g_t$:当前梯度
  • $G_t$:历史梯度平方累积
  • $\epsilon$:防止除以 0 的小常数

优点:

  • 自适应调整每个参数的学习率
  • 稀疏特征效果好(如 NLP)

缺点:

  • 学习率会一直减小,后期可能“停止学习”

RMSProp

RMSProp 是对 AdaGrad 的改进,用滑动平均代替累积和,避免学习率过早衰减。

更新公式:

  • 指数加权平均梯度平方:
    $$ r_t = \rho \cdot r_{t-1} + (1 - \rho) \cdot g_t^2 $$
  • 参数更新:
    $$ \theta_{t+1} = \theta_t - \frac{\alpha}{\sqrt{r_t + \epsilon}} \cdot g_t $$

其中:

  • $\rho$:衰减系数(通常设为 0.9)
  • $r_t$:当前梯度平方的平滑值

优点:

  • 始终维持较稳定的局部学习率
  • 适用于非凸优化(如深度神经网络)

本质: RMSProp 解决了 AdaGrad 学习率“衰减太快”的问题,让参数能持续更新。

动量法

Momentum 是为了解决震荡与收敛慢问题,引入“惯性”概念:当前更新方向受过去梯度影响。

更新公式:

  • 累积梯度动量:
    $$ v_t = \beta \cdot v_{t-1} + (1 - \beta) \cdot g_t $$
  • 参数更新:
    $$ \theta_{t+1} = \theta_t - \alpha \cdot v_t $$

其中:

  • $v_t$:当前动量(方向)
  • $\beta$:动量因子(一般为 0.9)

优点:

  • 加速收敛(方向一致时)

如果当前和历史梯度方向一致,$v_t$ 趋于加大(增强“信号”);如果方向反复变化,$v_t$ 被抵消,趋于减小(抑制“噪声”);所以 Momentum 在方向稳定的平滑区域加速收敛,而在不稳定区域自适应减速。

  • 可减缓梯度震荡(如锯齿函数、鞍点处)

当梯度方向频繁来回变动(如锯齿函数的左右跳动),Momentum 会平滑更新方向,当前 $g_t$ 与历史 $v_{t-1}$ 方向相反时,它们在 $v_t$ 中部分抵消,这让更新方向更加稳定,不跟着瞬时梯度乱跳

例如:梯度一会儿是 +1,一会儿是 -1,GD 就会左右大幅震荡,Momentum 会自动平滑成趋近 0 的小更新,使路径更“直”

  • 突破鞍点(局部平缓区)

在鞍点或者局部极小值点区域(梯度为 0,但不是最小值),GD 因当前梯度接近 0,更新几乎停止,Momentum 因历史梯度仍有积累,$v_t$ 不为 0,能继续滑出困境

Adam

Adam 是目前最常用的优化器,结合了:

  • Momentum: 提供稳定方向
  • RMSProp: 提供自适应步长

一阶矩估计(First Moment Estimate)

一阶矩是指 梯度的期望,即动量的思想:记录梯度的“平均方向”。

Adam 中的表示方式为:

$$
m_t = \beta_1 \cdot m_{t-1} + (1 - \beta_1) \cdot g_t
$$

  • $m_t$ 是当前时刻的动量(类似 Momentum);
  • $\beta_1$ 是动量衰减系数,通常取 0.9;
  • 本质是梯度的 指数加权平均(Exponential Moving Average);
  • 目的:平滑震荡梯度,指引更新方向

加速收敛:通过动量机制保留历史梯度方向,减少震荡,使参数更新更稳定;

捕捉梯度趋势:在非凸优化问题中,帮助模型避开局部最小值,向全局最优方向移动

二阶矩估计(Second Moment Estimate)

二阶矩是指 梯度平方的期望,即对梯度的尺度做估计,用来调整学习率。

Adam 中的表示方式为:

$$
v_t = \beta_2 \cdot v_{t-1} + (1 - \beta_2) \cdot g_t^2
$$

  • $v_t$ 是当前时刻的平方梯度平均(来自 RMSProp);
  • $\beta_2$ 是衰减系数,通常取 0.999;
  • 目的:估计梯度的“波动程度”,调整每个参数的自适应学习率

自适应学习率:根据梯度方差调整步长,梯度变大时,学习率自动变小,防止震荡;梯度变小时,学习率增大,加快收敛

处理稀疏梯度:对稀疏数据(NLP任务)中的低频参数分配更大更新步长,提升训练效率

偏差修正(Bias Correction)

Adam 初始化时,$m_0 = 0$ 和 $v_0 = 0$,所以在前几步迭代中:

  • $m_t$ 和 $v_t$ 被低估,尤其是在 $t$ 很小时;
  • 为了纠正这个初始偏小的问题,引入了偏差修正项

修正后的动量和平方项为:

$$
\hat{m}_t = \frac{m_t}{1 - \beta_1^t}, \quad \hat{v}_t = \frac{v_t}{1 - \beta_2^t}
$$

  • 当 $t$ 较小时,$\beta_1^t$ 接近 0,修正效果显著;
  • 当 $t$ 较大时,$\beta_1^t$ 接近 1,修正趋于无效。

整合三者后,Adam 的参数更新为:

$$
\theta_{t+1} = \theta_t - \alpha \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon}
$$

  • 分子是平滑方向(动量);
  • 分母是自适应步长;
  • 加上 $\epsilon$ 是为了避免除 0(通常设为 $10^{-8}$)。
任务 符号 作用
一阶矩估计 $m_t$ 平滑梯度方向,控制方向变化
二阶矩估计 $v_t$ 平滑梯度幅度,自适应步长
偏差修正 $\hat{m}_t$, $\hat{v}_t$ 修正初期估计偏小,提高稳定性

学习率常用的调度策略

  • 固定学习率(Constant LR)

    • 学习率保持不变:
      $$
      \alpha_t = \alpha_0
      $$
    • 优点:实现简单;
    • 缺点:前期慢,后期震荡大,难以兼顾速度与稳定性;
    • 通常只用于 baseline 或短时间训练。
  • Step Decay(阶梯式衰减)

    • 每隔固定步数或 epoch,将学习率乘以一个常数因子:
      $$
      \alpha_t = \alpha_0 \cdot \gamma^{\lfloor t / k \rfloor}
      $$

    • $\gamma$:衰减因子,如 0.1;

    • $k$:衰减周期,如每 10 轮。

    • 优点:可控、实现简单;

    • 缺点:变化不连续,可能引发梯度突变。

  • Exponential Decay(指数衰减)

    • 每一步都按指数衰减:
      $$
      \alpha_t = \alpha_0 \cdot e^{-\lambda t}
      $$

    • 或简化为:
      $$
      \alpha_t = \alpha_0 \cdot \gamma^t
      $$

    • 优点:比 Step Decay 平滑;

    • 缺点:衰减可能过快,需设置好初始值与 $\gamma$。

  • Cosine Annealing(余弦退火)

    • 学习率呈余弦下降趋势:
      $$
      \alpha_t = \alpha_{\text{min}} + \frac{1}{2}(\alpha_0 - \alpha_{\text{min}})(1 + \cos(\frac{t}{T} \pi))
      $$

    • 可以配合 Restart(重启) 策略使用(SGDR);

    • 优点:训练后期学习率变化更加细腻,利于 fine-tune;

    • 应用于如 ResNet、Transformer 等模型训练中。

  • Warm-up(预热)

    • 一开始使用较小学习率,然后逐渐升高,再转入正常调度策略;

    • 典型线性 warm-up:
      $$
      \alpha_t = \alpha_0 \cdot \frac{t}{T_{\text{warmup}}}, \quad t \leq T_{\text{warmup}}
      $$

    • 常与 AdamW、Transformer 一起使用;

    • 目的:避免训练初期权重剧烈更新导致发散。

  • ReduceLROnPlateau(性能平稳时降低)

    • 当验证集 loss 在若干 epoch 内不下降时,自动降低学习率:例如:patience=5, factor=0.1
    • PyTorch / Keras 均内置该策略;
    • 优点:自适应触发,智能控制收敛过程;
    • 缺点:需监控指标,不适合无验证集训练。
  • Cyclical Learning Rate(周期性学习率)

    • 学习率在 [low, high] 区间周期性震荡:
      $$
      \alpha_t = \text{cyclical}(t)
      $$

    • 增强探索性,可能帮助跳出局部最优;

    • 在某些场景(如小模型、局部最小值密集区域)下表现好;

    • 常与 momentum 一起调制(CLR + momentum scheduling)。

Lipschitz条件

Lipschitz 条件是一种对函数“变化速度”的约束,表示函数不会“跳得太快”。

一个函数 $f(x)$ 满足 $L$-Lipschitz 连续,指对于任意 $x, y$,有:

$$
|f(x) - f(y)| \leq L |x - y|
$$

  • $L$ 是 Lipschitz 常数,衡量最大“斜率”;
  • 如果 $L$ 越小,函数越平滑;
  • 如果 $f$ 可导,该条件等价于:$|\nabla f(x)| \leq L$

梯度 Lipschitz 连续(Gradient Lipschitz)

如果 $f(x)$ 是光滑的,我们关注的是梯度的 Lipschitz 连续性:

$$
|\nabla f(x) - \nabla f(y)| \leq L |x - y|
$$

  • 表示梯度变化不太剧烈(即 Hessian 的谱范数有上界);
  • $L$ 是梯度 Lipschitz 常数,常在一阶优化中设为学习率上限;
  • 多数优化器默认函数满足这个条件(特别是凸优化理论)。

Lipschitz 条件与学习率的关系

在最经典的梯度下降中,如果损失函数的梯度是 $L$-Lipschitz 连续的:

  • 为了保证每步不“走过头”,学习率必须满足:

    $$
    0 < \alpha \leq \frac{1}{L}
    $$

  • 否则更新可能导致震荡或发散;

  • 所以 $L$ 实际上决定了学习率的最大安全边界

优化算法的理论收敛边界

这是从理论角度回答:“一个优化算法最坏情况下能收敛到多快?”

下面列出常见一阶优化器的最坏收敛边界(假设目标函数满足一定条件):

问题类型 算法 收敛速度 最坏误差界限
一般凸函数 梯度下降 子线性 $\mathcal{O}(1/t)$ $f(x_t) - f(x^) \leq \frac{L|x_0 - x^|^2}{2t}$
强凸 + 梯度 Lipschitz 梯度下降 线性收敛 $\mathcal{O}(\rho^t)$ $f(x_t) - f(x^) \leq (1 - \mu / L)^t (f(x_0) - f(x^))$
非凸函数 SGD 无保证 只保证 $\mathbb{E}|\nabla f(x)|^2 \leq \epsilon$
函数光滑 + Convex Nesterov 加速 $\mathcal{O}(1/t^2)$ 更快但不稳定

说明:

  • $L$ 是梯度 Lipschitz 常数;
  • $\mu$ 是强凸常数;
  • $t$ 是迭代次数;
  • $\rho = 1 - \frac{\mu}{L}$ 是收敛率。
概念 含义 与优化的关系
Lipschitz 连续 函数变化速度有限 保证更新稳定,避免跳跃
梯度 Lipschitz 梯度变化速度有限 决定学习率上限与收敛性
强凸 函数最小值唯一且曲率有限 保证线性收敛
理论边界 算法最坏误差随步数下降速度 指导优化器设计、调参与收敛预估

反向传播与链式法则

为什么需要反向传播:因为我们需要通过反向传播计算神经网络中所有参数(权重,偏置)的梯度,才能用梯度下降算法更新参数,让模型学会降低损失

从最后一层向前面层传播,每一层都根据上层传下来的梯度,乘上自己的局部导数,作为链式乘积继续往下传

梯度消失

在反向传播中,梯度会连乘多个激活函数的导数,如果每一层的导数都是小于1的值,多层乘起来后就会导致最终梯度趋近于0,sigmoid激活函数的输出范围在0-1,当x很大或很小,函数值趋近于1或者0,只有中心附近有梯度,两端导数几乎为0;ReLU的导数在x大于0是就是1,所以没有梯度缩小的问题,不像sigmoid那样输出收缩在0-1之间;但是当x<=0时,导数为0,所以如果输入长期为负,会导致dead neuron问题,解决办法是Leaky ReLU等平滑版本的激活函数;在神经网络中,网络层数过深(连乘次数过多),还有如果参数初始化特别小(小权重代表前向输出趋近于0,激活函数进入饱和区,导数接近0),会造成梯度消失