【深度学习】(三)学习率优化

一、梯度下降

1 概述

梯度下降是一种优化算法,核心是通过反复调整参数,让模型的预测误差(损失函数)降到最低

可以理解为下山

  1. 找方向:计算当前位置最陡的下坡方向(梯度反方向)。
  2. 迈一步:按照学习率设定的步长,向下走一步,更新参数。
  3. 重复:直到走到最低点(误差最小)。

关键点

  • 学习率:决定步长大小。太大容易错过最低点,太小则收敛太慢。
  • 常用形式小批量梯度下降,每次用一小批数据计算方向,兼顾速度与稳定。

2 核心数学逻辑

在数学上,我们的目标是**最小化损失函数 $ J(\theta) ∗∗(**( \theta $ 代表模型参数)。

  • 梯度:就是损失函数对参数 $ \theta $ 的偏导数 $ \nabla J(\theta) $。它指向的是函数上升最快的方向。
  • 下降:既然要最小值,我们就朝梯度的反方向更新参数。
  • 更新公式:$ \theta_{new} = \theta_{old} - \eta \cdot \nabla J(\theta) $

这里的 $ \eta $(学习率) 就是你下山的步长。步长太大容易跨过山谷(错过最优点),步长太小则下山太慢(训练耗时)。

在实际写代码时(如PyTorch/TensorFlow),你不会只看到一种梯度下降,根据数据量的处理方式,主要分为三类:

  • 批量梯度下降(BGD):每次更新参数时,使用全部训练数据计算梯度。优点:梯度方向最准确,下降稳定;缺点:在海量数据下计算极慢,无法用于大型数据集。
  • 随机梯度下降(SGD):每次更新时,随机选取1个样本计算梯度。优点:计算极快,且能跳出局部极小值;缺点:梯度波动剧烈,下降路径很“震荡”。
  • 小批量梯度下降(Mini-batch GD)最常用。每次选取一个固定数量(如 32、256 个)的样本计算梯度。它结合了前两者的优点,既有计算效率,又有稳定性。(你现在听到的大模型训练,基本都是用这种)。

3 注意事项

实际使用时,需要注意这些:

  1. 特征缩放(归一化):如果输入数据量级差异巨大(如身高1.7m和收入10000元),损失函数会变成“扁平”的峡谷,梯度下降会走“之”字形,极其缓慢。必须使用标准化(Standardization)将数据压缩到相近范围。
  2. 学习率的选择:这是最重要的超参数。通常从 $ 10^{-3} $ 或 $ 10^{-4} $ 开始尝试,或者使用学习率衰减(随着训练轮次增加逐渐减小步长)。
  3. 梯度裁剪(Gradient Clipping):当梯度值过大时(梯度爆炸),参数会一步跳出很远导致Loss变成NaN。需要设置一个阈值,截断过大的梯度。

二、反向传播

反向传播是训练神经网络的核心算法,负责计算梯度,告诉每一层参数应该如何调整。

形象理解

  • 把神经网络想象成一个流水线,多名工人依次加工产品。
  • 前向:原料进去,成品出来,质检员发现质量差(误差大)。
  • 反向:质检员把问题逆向反馈——先调整最后一名工人的操作,再调整前一名……直到第一名。每个人根据反馈改进自己的手法。

三、梯度下降优化算法

基础梯度下降太“笨”了,在实际训练中会遇到三个致命问题。

  • 训练太慢:标准梯度下降每一步都走固定步长,在平坦区域(梯度很小)时,移动极其缓慢。
  • 容易卡在坏位置:鞍点、局部极小值
符号含义
θ\thetaθ模型参数(待优化的变量)
ggg梯度 $ \nabla L(\theta) $
η\etaη学习率(基础步长)
ϵ\epsilonϵ极小常数(防止分母为零,通常 10−810^{-8}10810−710^{-7}107

1 指数加权平均

一种平滑时序数据的算法,核心思想是:当前时刻的估计值 = 当前实际值 × 权重 + 历史估计值 × 衰减
vt=β⋅vt−1+(1−β)⋅θt v_t = \beta \cdot v_{t-1} + (1-\beta) \cdot \theta_t vt=βvt1+(1β)θt

  • vtv_tvt:第 ttt 时刻的加权平均值
  • θtθ_tθt:第 ttt 时刻的实际观测值
  • βββ:衰减系数(0 < βββ < 1),控制历史值的保留程度

2 AdaGrad

核心思想:不同参数用不同学习率——频繁更新的参数用较小步长,稀疏参数用较大步长。

实现方式

  • 维护梯度平方的累积和 r=r+g2r = r + g^2r=r+g2
  • 参数更新:θ=θ−ηr+ϵ⋅g\theta = \theta - \frac{\eta}{\sqrt{r + \epsilon}} \cdot gθ=θr+ϵηg

优点

  • 无需手动调整学习率
  • 适合稀疏数据(如自然语言处理、推荐系统)

缺点

  • 致命问题:r 单调递增,学习率会持续衰减 → 训练后期学习率过小,模型停止学习

3 RMSProp

核心思想:解决 AdaGrad 学习率过早消失的问题——用指数加权平均替代累积和,只关注近期梯度。

实现方式

  • 维护梯度平方的指数加权平均:r=βr+(1−β)g2r = \beta r + (1-\beta)g^2r=βr+(1β)g2
  • 参数更新:θ=θ−ηr+ϵ⋅g\theta = \theta - \frac{\eta}{\sqrt{r + \epsilon}} \cdot gθ=θr+ϵηg

优点

  • 学习率不会单调衰减,保持持续学习能力
  • 在非凸问题(如深度学习)中表现稳定

适用场景:RNN、强化学习等梯度波动较大的场景

4 Adam

核心思想:结合动量(Momentum)和自适应学习率(RMSProp)——既保持方向惯性,又自适应调整步长。

实现方式

  • 一阶矩(动量)m=β1m+(1−β1)gm = \beta_1 m + (1-\beta_1)gm=β1m+(1β1)g
  • 二阶矩(自适应)v=β2v+(1−β2)g2v = \beta_2 v + (1-\beta_2)g^2v=β2v+(1β2)g2
  • 偏差校正m^=m/(1−β1t), v^=v/(1−β2t)\hat{m} = m/(1-\beta_1^t), \ \hat{v} = v/(1-\beta_2^t)m^=m/(1β1t), v^=v/(1β2t)
  • 参数更新θ=θ−η⋅m^/(v^+ϵ)\theta = \theta - \eta \cdot \hat{m} / (\sqrt{\hat{v}} + \epsilon)θ=θηm^/(v^+ϵ)
符号含义更新方式
mmm一阶矩(动量)$ m = \beta_1 m + (1-\beta_1)g $
vvv二阶矩(自适应学习率)$ v = \beta_2 v + (1-\beta_2)g^2 $
β1\beta_1β1一阶矩衰减系数通常 0.9
β2\beta_2β2二阶矩衰减系数通常 0.999
m^\hat{m}m^偏差校正后的一阶矩$ \hat{m} = m / (1-\beta_1^t) $
v^\hat{v}v^偏差校正后的二阶矩$ \hat{v} = v / (1-\beta_2^t) $
ttt时间步(迭代次数)从 1 开始计数
η\etaη学习率通常 0.001
ϵ\epsilonϵ数值稳定项通常 10−810^{-8}108

优点

  • 收敛速度快,对超参数敏感度低
  • 适合大规模数据和深度网络

缺点

  • 在某些任务中泛化能力可能不如 SGD+Momentum
  • 需要额外内存存储动量项(参数量 × 2)

在这里插入图片描述

场景推荐方法PyTorch配置示例
快速上手、通用AdamAdam(lr=0.001)
图像分类、CVSGD + MomentumSGD(lr=0.01, momentum=0.9)
NLP、TransformerAdamWAdamW(lr=0.001, weight_decay=0.01)
稀疏特征AdagradAdamAdagrad(lr=0.01)
RNN/LSTMRMSpropAdamRMSprop(lr=0.001, alpha=0.99)
需要强正则化AdamWAdamW(lr=0.001, weight_decay=0.01)
import torch
import torch.nn as nn
import torch.optim as optim

# 定义模型
model = nn.Linear(10, 2)

# 1. SGD (含 Momentum 和 Nesterov)
optimizer_sgd = optim.SGD(model.parameters(), lr=0.01, momentum=0.9, nesterov=False)

# 2. Adagrad
optimizer_adagrad = optim.Adagrad(model.parameters(), lr=0.01)

# 3. RMSprop
optimizer_rmsprop = optim.RMSprop(model.parameters(), lr=0.001, alpha=0.99)

# 4. Adam
optimizer_adam = optim.Adam(model.parameters(), lr=0.001, betas=(0.9, 0.999))

# 5. AdamW
optimizer_adamw = optim.AdamW(model.parameters(), lr=0.001, weight_decay=0.01)

# 6. AdaDelta
optimizer_adadelta = optim.Adadelta(model.parameters(), lr=1.0)

# 训练使用
for epoch in range(100):
    optimizer.zero_grad()
    output = model(input_data)
    loss = criterion(output, target)
    loss.backward()
    optimizer.step()

四、学习率优化

如果使用固定的学习率,往往会面临以下困境:

  1. 收敛速度慢(学习率过小):模型参数更新步长太小,损失函数下降极其缓慢,训练周期过长,且容易陷入局部极小值或鞍点难以逃脱。
  2. 无法收敛或震荡(学习率过大):参数更新步长太大,导致损失函数在最小值附近剧烈震荡,甚至越过最优点导致梯度爆炸,使得模型无法收敛。
  3. 难以适应数据特征
    • 数据通常是高维且稀疏的(如文本、图像局部特征)。对于频繁出现的特征,我们希望用较小的步长精细调整;对于罕见的特征,我们希望用较大的步长捕捉其信息。固定学习率无法满足这种差异化需求。
  4. 训练阶段的需求不同
    • 初期:通常希望学习率大一些,快速靠近最优解区域。
    • 中后期:需要较小的学习率,帮助模型在最小值附近微调,避免震荡,甚至需要微调(Fine-tuning)时的极低学习率来防止破坏预训练知识。

1. 学习率衰减 (Learning Rate Decay)

这是最经典的策略,核心思想是随着迭代次数的增加,逐步减小学习率。

  • 分段常数衰减 (Step Decay):每经过一定轮次(Epoch),学习率降低为原来的 $\frac{1}{\sqrt{10}} $ 或 $ \frac{1}{10}。例如:。例如:。例如:\text{lr} = \text{lr}_0 \times \text{decay_rate}^{\lfloor \text{epoch}/\text{step_size} \rfloor}$。
  • 指数衰减 (Exponential Decay):学习率按指数函数平滑下降:lr=lr0⋅e−kt\text{lr} = \text{lr}_0 \cdot e^{-kt}lr=lr0ekt
  • 余弦退火 (Cosine Annealing):学习率按照余弦函数周期性地从最大值下降到最小值。这不仅是衰减,还引入了重启机制(见后文)。

2. 自适应学习率算法 (Adaptive Learning Rates)

这类算法不再需要手动指定全局学习率或衰减策略,它们会根据参数的梯度历史自动调整每个参数的学习率。

3. 预热 (Warmup)

在训练初期,模型参数是随机初始化的,梯度可能非常大或异常。如果一开始就使用较大的学习率,容易导致模型数值不稳定(甚至NaN)。

  • 策略:在前几个Epoch或几千步中,让学习率从一个非常小的值线性指数地增长到预设的最大学习率,然后再进行正常的衰减(如余弦退火)。
  • 常用组合Warmup + Cosine Annealing(如“三阶段学习率”)。这在Transformer架构(如BERT、GPT)的训练中几乎是标配。

4. 周期性重启 (Cyclical Learning Rates)

打破“学习率必须单调递减”的常规,允许学习率周期性变化,帮助模型跳出局部极小值或鞍点。

  • 循环学习率 (CLR):让学习率在预设的边界值之间周期性震荡。
  • 带重启的余弦退火 (Cosine Annealing with Restarts):训练过程中,学习率多次从最大值开始余弦衰减到最小值,每次衰减的周期可以逐渐变长。这种方法在训练深度网络时往往能比单一衰减策略获得更好的泛化能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值