前言
优化算法是深度学习的 "引擎"------模型能力上限由网络结构决定,而实际性能下限由优化算法主导。《动手学深度学习(PyTorch 版)》优化算法系统讲解了从经典梯度下降到主流自适应学习率算法的完整脉络,既是理论基石,也是工业界 "炼丹" 的核心工具包。
本章将以教材内容为核心,从理论拆解、代码实现、场景适配、避坑指南、学习规划五大维度深度解析优化算法的底层逻辑与实战技巧,帮你彻底吃透模型训练的核心密码。
一 优化和深度学习:核心关系与目标
1.1 优化的本质:从数学到深度学习
优化 的核心是在约束条件下寻找目标函数的极值 (最小或最大)。在深度学习中,目标函数即损失函数 (如分类任务的交叉熵、回归任务的 MSE),待优化变量是模型参数(权重W、偏置b)。
数学定义:给定损失函数L(θ)(θ为模型参数),优化目标为:θ∗=argminθL(θ)
1.2 深度学习优化的核心挑战
深度学习优化与传统机器学习(如线性回归、SVM)有本质区别,面临三大核心难题:
- 非凸损失曲面 :深层网络的损失函数存在大量局部最优解 和鞍点,无法保证找到全局最优;
- 高维参数空间:现代模型(如 BERT、ResNet)参数规模达百万至亿级,搜索空间维度极高;
- 梯度噪声与不稳定性 :小批量数据计算的梯度存在随机噪声 ,深层网络易出现梯度消失 / 爆炸;
- 计算效率瓶颈 :海量数据与大模型训练需平衡收敛速度 与计算成本。
1.3 优化 vs. 泛化:核心目标差异
- 优化目标 :最小化训练集损失(让模型 "记住" 训练数据);
- 泛化目标 :最小化测试集损失(让模型 "理解" 数据规律,适配新数据)。
核心结论:优化算法的核心任务不是 "找全局最优",而是找到 "泛化能力最优" 的局部最优解------ 过度优化训练集易导致过拟合,需通过正则化、早停等手段平衡。
1.4 优化算法的分类(教材核心框架)
教材将优化算法分为三大类,本章按此脉络展开:
- 经典梯度类算法:梯度下降(GD)、随机梯度下降(SGD)、小批量随机梯度下降(Mini-batch SGD);
- 动量加速类算法:动量法(Momentum)、Nesterov 加速梯度(NAG);
- 自适应学习率算法:AdaGrad、RMSProp、Adadelta、Adam(工业界主流);
- 学习率调度器:固定衰减、余弦退火、Warmup 等(辅助优化收敛)。
二 凸性:优化算法的理论基石
2.1 凸集与凸函数:定义与直观理解
凸集(Convex Set)
若集合内任意两点的连线仍在集合内,则该集合为凸集。例如:实数域R、圆盘、正方形;非凸集如圆环、五角星。
凸函数(Convex Function)
定义:对函数f:Rn→R,若对任意x,y∈Rn,λ∈[0,1],满足:f(λx+(1−λ)y)≤λf(x)+(1−λ)f(y)
直观理解:凸函数的图像上任意两点的连线,都在图像上方。常见凸函数:f(x)=x2、f(x)=ex、负对数概率(交叉熵)。
2.2 凸函数的核心性质:全局最优保证
凸函数的局部最优解一定是全局最优解------ 这是传统机器学习(如逻辑回归、SVM)能通过梯度下降找到全局最优的核心原因。
非凸函数(如深层网络的损失函数)无此保证,存在大量局部最优,但深层网络的局部最优解通常具有相近的泛化能力,这是深度学习能有效工作的关键前提。
2.3 凸性在深度学习中的实际意义
- 理论基准:凸优化是理解非凸优化的基础 ------GD/SGD 在凸函数上的收敛性分析,可迁移至非凸场景的稳定性优化;
- 损失函数设计:交叉熵、MSE 等凸损失函数是深度学习主流选择,避免引入额外非凸性;
- 梯度稳定性:凸函数的梯度方向始终指向全局最优,而非凸函数的梯度易在局部最优附近震荡。
三 梯度下降(Gradient Descent, GD):经典基准算法
3.1 核心思想:沿梯度反方向迭代更新
梯度下降是最基础的优化算法,核心逻辑:损失函数在某点的梯度指向上升最快的方向,因此沿梯度反方向更新参数,可最小化损失。
算法公式(教材核心)
- 梯度计算:对损失函数L(θ),计算参数梯度∇L(θ);
- 参数更新:θ←θ−η∇L(θ)其中η>0为学习率(控制每次更新的步长)。
3.2 一维与二维示例:直观理解收敛过程
一维示例(f(x)=x2,全局最优x∗=0)
- 初始值x0=4,学习率η=0.1;
- 迭代过程:x1=4−0.1×8=3.2 → x2=3.2−0.1×6.4=2.56 → ... → 逐步收敛至 0。
二维示例(f(x,y)=x2+2y2,全局最优(0,0))
- 梯度:∇f=(2x,4y);
- 迭代轨迹:沿椭圆等高线垂直方向收敛,学习率过大易震荡,过小收敛过慢。
3.3 代码实现(PyTorch,从零开始)
import numpy as np
import torch
import matplotlib.pyplot as plt
# 定义损失函数:f(x) = x²
def f(x):
return x ** 2
# 定义梯度:f'(x) = 2x
def grad_f(x):
return 2 * x
# 梯度下降实现
def gd(eta, x0, num_epochs):
x = x0
history = [x.item()] # 记录迭代过程
for _ in range(num_epochs):
x -= eta * grad_f(x)
history.append(x.item())
return x, history
# 超参数设置
eta = 0.1 # 学习率
x0 = torch.tensor(4.0, requires_grad=False) # 初始值
num_epochs = 20
# 执行梯度下降
x_final, history = gd(eta, x0, num_epochs)
print(f"最终收敛值:{x_final.item()}")
# 可视化迭代过程
plt.plot(history, marker='o')
plt.xlabel('迭代次数')
plt.ylabel('x值')
plt.title('梯度下降收敛过程(η=0.1)')
plt.show()
3.4 核心优缺点与适用场景
优点
- 理论简单易实现:公式简洁,无额外超参数,稳定性强;
- 凸函数全局收敛:在凸损失函数上可稳定收敛至全局最优。
缺点
- 全量梯度计算,效率极低 :每次迭代需遍历全部训练数据计算梯度,大数据集(如 ImageNet、BERT 预训练)无法使用;
- 学习率敏感:η过大易震荡不收敛,过小收敛极慢;
- 非凸场景易陷入局部最优:无逃离局部最优的机制。
适用场景
- 小数据集、简单模型(如线性回归、逻辑回归);
- 作为优化算法的理论基准,用于对比其他算法性能。
四 随机梯度下降(Stochastic Gradient Descent, SGD):效率革命
4.1 核心思想:单样本梯度近似全量梯度
随机梯度下降(SGD)是 GD 的改进,核心突破:每次迭代仅用 1 个样本 计算梯度,近似全量梯度,大幅提升计算效率。
算法公式(教材核心)
对训练集{(xi,yi)}i=1N,单样本损失为Li(θ)=L(θ;xi,yi):
- 随机采样 1 个样本i;
- 计算单样本梯度∇Li(θ);
- 参数更新:θ←θ−η∇Li(θ)
4.2 梯度噪声与收敛特性:震荡中快速收敛
核心特点:梯度存在随机噪声
SGD 的梯度是全量梯度的无偏估计 :E[∇Li(θ)]=∇L(θ),但单次梯度存在噪声,导致参数更新轨迹震荡。
收敛优势:噪声助力逃离局部最优
- GD:平稳收敛,易陷入局部最优;
- SGD:震荡收敛,梯度噪声可帮助模型逃离局部最优,更易找到泛化能力强的最优解。
4.3 代码实现(PyTorch,对比 GD 与 SGD)
import numpy as np
import torch
import matplotlib.pyplot as plt
# 生成模拟数据:y = 2x + 3 + 噪声
np.random.seed(42)
X = np.random.rand(100, 1) # 100个样本
y = 2 * X + 3 + 0.1 * np.random.randn(100, 1)
# 转换为Tensor
X_tensor = torch.tensor(X, dtype=torch.float32)
y_tensor = torch.tensor(y, dtype=torch.float32)
# 定义线性模型:y = wx + b
def model(X, w, b):
return w * X + b
# 定义MSE损失
def loss(y_pred, y):
return torch.mean((y_pred - y) ** 2)
# GD实现(全量数据)
def gd(X, y, lr, epochs):
w = torch.tensor(0.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)
history = []
for _ in range(epochs):
y_pred = model(X, w, b)
l = loss(y_pred, y)
l.backward()
with torch.no_grad():
w -= lr * w.grad
b -= lr * b.grad
w.grad.zero_()
b.grad.zero_()
history.append(l.item())
return w, b, history
# SGD实现(单样本随机采样)
def sgd(X, y, lr, epochs):
w = torch.tensor(0.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)
history = []
n = X.shape[0]
for _ in range(epochs):
# 随机采样1个样本
i = np.random.randint(0, n)
X_i = X[i:i+1]
y_i = y[i:i+1]
y_pred = model(X_i, w, b)
l = loss(y_pred, y_i)
l.backward()
with torch.no_grad():
w -= lr * w.grad
b -= lr * b.grad
w.grad.zero_()
b.grad.zero_()
# 记录全量损失(用于对比)
with torch.no_grad():
full_loss = loss(model(X, w, b), y).item()
history.append(full_loss)
return w, b, history
# 超参数
lr = 0.1
epochs = 50
# 训练
w_gd, b_gd, hist_gd = gd(X_tensor, y_tensor, lr, epochs)
w_sgd, b_sgd, hist_sgd = sgd(X_tensor, y_tensor, lr, epochs)
# 可视化对比
plt.plot(hist_gd, label='GD')
plt.plot(hist_sgd, label='SGD')
plt.xlabel('迭代次数')
plt.ylabel('损失值')
plt.title('GD vs SGD 收敛对比')
plt.legend()
plt.show()
4.4 核心优缺点与避坑要点
优点
- 计算效率极高:每次迭代仅需 1 个样本,大数据集训练速度提升百倍;
- 泛化能力更强:梯度噪声助力逃离局部最优,避免过拟合;
- 在线学习适配:可实时处理流式数据(如推荐系统、广告点击率预测)。
缺点
- 梯度噪声大,收敛震荡:参数更新轨迹波动明显,后期难以精细收敛;
- 学习率敏感:对学习率调度要求更高,需随训练逐步降低学习率;
- 单样本梯度方差大:高维稀疏数据(如 NLP 词向量)中梯度噪声更严重。
避坑要点(实战高频)
- 必须使用学习率衰减:固定学习率易导致后期震荡不收敛,常用指数衰减、余弦退火;
- 小批量替代单样本:单样本梯度噪声过大,实际工程中几乎不使用纯 SGD,而是用 Mini-batch SGD;
- 梯度裁剪:防止梯度爆炸,尤其在 RNN/LSTM 等序列模型中。
五 小批量随机梯度下降(Mini-batch SGD):工业界主流基准
5.1 核心思想:平衡效率与稳定性
小批量随机梯度下降(Mini-batch SGD,简称 MB-SGD)是GD 与 SGD 的折中方案 ,核心逻辑:每次迭代采样 batch_size 个样本 计算梯度,兼顾计算效率与梯度稳定性。
关键概念:Batch Size(批量大小)
- Batch Size=1:纯 SGD,噪声最大,效率最高;
- Batch Size=N(N 为总样本数):GD,无噪声,效率最低;
- Batch Size=32/64/128(主流选择):平衡噪声与效率,工业界默认配置。
算法公式(教材核心)
- 将训练集随机划分为M个小批量,每个批量含B个样本(B≪N);
- 对每个小批量B,计算批量梯度:∇LB(θ)=B1∑i∈B∇Li(θ)
- 参数更新:θ←θ−η∇LB(θ)
5.2 批量大小的影响:收敛速度、稳定性与泛化能力
1. 收敛速度
- 小 Batch Size(如 32):迭代次数多,每次迭代快,整体收敛速度快;
- 大 Batch Size(如 1024):迭代次数少,每次迭代慢,整体收敛速度慢。
2. 梯度稳定性
- 小 Batch Size:梯度噪声大,更新震荡;
- 大 Batch Size:梯度接近全量梯度,稳定性强,更新平稳。
3. 泛化能力(核心结论)
小 Batch Size 模型泛化能力更强------ 梯度噪声引入的随机性可抑制过拟合,大 Batch Size 易陷入训练集局部最优,泛化能力弱。
工业界经验:Batch Size=32/64 是性价比最高的选择,大模型训练(如 BERT)常用 128/256,需配合学习率线性缩放。
5.3 PyTorch 简洁实现(使用内置优化器)
import torch
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset
# 生成模拟数据
np.random.seed(42)
X = np.random.rand(1000, 1)
y = 2 * X + 3 + 0.1 * np.random.randn(1000, 1)
X_tensor = torch.tensor(X, dtype=torch.float32)
y_tensor = torch.tensor(y, dtype=torch.float32)
# 创建数据集与DataLoader(Batch Size=64)
dataset = TensorDataset(X_tensor, y_tensor)
dataloader = DataLoader(dataset, batch_size=64, shuffle=True)
# 定义线性模型
class LinearModel(nn.Module):
def __init__(self):
super().__init__()
self.linear = nn.Linear(1, 1)
def forward(self, x):
return self.linear(x)
model = LinearModel()
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.1) # MB-SGD优化器
# 训练循环
epochs = 50
history = []
for epoch in range(epochs):
running_loss = 0.0
for batch_X, batch_y in dataloader:
optimizer.zero_grad() # 梯度清零
y_pred = model(batch_X) # 前向传播
loss = criterion(y_pred, batch_y) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 参数更新
running_loss += loss.item()
epoch_loss = running_loss / len(dataloader)
history.append(epoch_loss)
if (epoch + 1) % 10 == 0:
print(f'Epoch {epoch+1}, Loss: {epoch_loss:.4f}')
# 可视化收敛曲线
plt.plot(history)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Mini-batch SGD 收敛过程(Batch Size=64)')
plt.show()
5.4 核心优缺点与实战避坑指南
优点
- 平衡效率与稳定性:梯度噪声适中,收敛速度快,稳定性强;
- 泛化能力最优:小批量噪声抑制过拟合,工业界首选基准算法;
- 适配分布式训练:可通过数据并行扩展至多 GPU,大模型训练必备。
缺点
- 需调优 Batch Size 与学习率:两者强相关,需配合调整;
- 批量梯度仍有噪声:后期收敛精度略低于 GD。
实战避坑指南(高频踩坑点)
- Batch Size 与学习率线性缩放:Batch Size 翻倍,学习率也应翻倍(如 64→128,lr=0.1→0.2),保证梯度更新幅度稳定;
- Batch Size 不宜过大:超过 256 易导致泛化能力下降,且 GPU 显存占用激增;
- Shuffle 必须开启:DataLoader 中 shuffle=True,避免批量数据相关性导致梯度偏差;
- 梯度累积替代超大 Batch:GPU 显存不足时,用梯度累积(多次小批量梯度累加后更新)模拟大 Batch 效果。
六 动量法(Momentum):加速收敛 + 抑制震荡
6.1 核心思想:引入 "惯性",加速梯度方向收敛
动量法(Momentum)是 MB-SGD 的加速改进,核心灵感来自物理力学 :参数更新如同小球下山,累积历史梯度的 "动量",加速梯度一致方向的收敛,抑制梯度反向方向的震荡。
算法公式(教材核心,带权重衰减)
- 维护动量变量v(初始化为 0);
- 每次迭代更新动量:v←βv+η∇LB(θ)
- 参数更新:θ←θ−v其中β∈[0,1)为动量系数(控制历史梯度的权重,默认 0.9),η为学习率。
6.2 动量的物理意义:加速 + 平滑
- 加速收敛:若当前梯度与历史动量方向一致,动量累积,更新步长增大,加速下山;
- 抑制震荡:若当前梯度与历史动量方向相反,动量抵消,更新步长减小,减少震荡;
- 平滑梯度 :动量是历史梯度的指数加权平均,有效降低梯度噪声。
6.3 代码实现(从零开始 + PyTorch 内置)
从零实现动量法
import torch
import matplotlib.pyplot as plt
# 定义损失函数:f(x) = 0.1x² + 2sin(x)(非凸,有震荡)
def f(x):
return 0.1 * x ** 2 + 2 * torch.sin(x)
# 定义梯度
def grad_f(x):
return 0.2 * x + 2 * torch.cos(x)
# 动量法实现
def momentum(eta, beta, x0, num_epochs):
x = x0
v = 0.0 # 动量初始化为0
history = [x.item()]
for _ in range(num_epochs):
v = beta * v + eta * grad_f(x)
x -= v
history.append(x.item())
return x, history
# 对比MB-SGD与动量法
eta = 0.1
beta = 0.9
x0 = torch.tensor(5.0)
num_epochs = 50
_, hist_sgd = momentum(eta, 0.0, x0, num_epochs) # β=0即SGD
_, hist_momentum = momentum(eta, beta, x0, num_epochs)
# 可视化对比
plt.plot(hist_sgd, label='SGD (β=0)')
plt.plot(hist_momentum, label='Momentum (β=0.9)')
plt.xlabel('迭代次数')
plt.ylabel('x值')
plt.title('SGD vs 动量法 收敛对比')
plt.legend()
plt.show()
PyTorch 内置动量优化器
# 延续11.5.3的模型与dataloader
optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9) # 动量法
6.4 Nesterov 加速梯度(NAG):动量法改进
NAG 是动量法的增强版,核心改进:提前计算动量方向的梯度,避免动量过大导致错过最优解。
算法公式
- 计算 "预测位置":θ′=θ−βv;
- 计算预测位置的梯度:∇L(θ′);
- 更新动量:v←βv+η∇L(θ′);
- 参数更新:θ←θ−v。
PyTorch 实现:
optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9, nesterov=True)
6.5 核心优缺点与避坑要点
优点
- 收敛速度大幅提升:相比 SGD,收敛速度提升 30%-50%,尤其在平坦区域;
- 有效抑制梯度震荡:动量平滑梯度噪声,非凸场景收敛更稳定;
- 超参数少:仅需调β(默认 0.9),鲁棒性强。
缺点
- 动量过大易错过最优解:β>0.95时,参数更新易 "冲过" 最优解;
- 对稀疏数据适配差:稀疏特征(如 NLP)中,历史动量易主导更新,抑制有效梯度。
避坑要点
- 动量系数默认 0.9:CV 任务(CNN/ResNet)首选 0.9,NLP 任务可降至 0.8-0.85;
- 学习率略低于 SGD:动量加速收敛,学习率可设为 SGD 的 0.8 倍,避免震荡;
- NAG 适用于高精度场景:如检测、分割任务,需精细收敛时优先用 NAG。
七 AdaGrad 算法:自适应学习率(稀疏数据神器)
7.1 核心思想:参数级自适应学习率,稀疏特征放大步长
AdaGrad(Adaptive Gradient)是首个自适应学习率算法 ,核心突破:为每个参数维护独立学习率,频繁更新参数(稠密特征)降低步长,稀疏更新参数(稀疏特征)放大步长,完美适配稀疏数据(如 NLP 词向量、推荐系统高维特征)。
算法公式(教材核心)
- 维护每个参数的梯度平方累积和s(初始化为 0);
- 批量梯度计算:g=∇LB(θ);
- 累积梯度平方:s←s+g⊙g(⊙为逐元素相乘);
- 参数更新:θ←θ−s+ϵη⊙g其中ϵ=10−6为防止除零的极小值,η为全局学习率。
7.2 核心特性:稀疏友好 + 学习率单调衰减
- 稀疏特征优先更新:稀疏参数梯度累积慢,s小,学习率大,快速更新;稠密参数梯度累积快,s大,学习率小,精细收敛;
- 学习率单调衰减:s随迭代持续增大,学习率持续降低,后期自动收敛;
- 无需手动调学习率:全局学习率η鲁棒性强,默认 0.01 即可。
7.3 代码实现(PyTorch 内置)
# 延续11.5.3的模型与dataloader
optimizer = torch.optim.Adagrad(model.parameters(), lr=0.01, eps=1e-6)
7.4 致命缺陷与适用场景
致命缺陷:梯度平方累积无限增长,学习率过早衰减
训练后期,s累积过大,学习率趋近于 0,参数停止更新,模型收敛停滞------ 这是 AdaGrad 在深层网络中几乎不使用的核心原因。
适用场景
- 高维稀疏数据:文本分类、推荐系统、广告点击率预测;
- 浅层模型:逻辑回归、浅层 MLP,训练轮次少,未出现严重学习率衰减。
八 RMSProp 算法:解决 AdaGrad 的过早衰减问题
8.1 核心思想:指数加权平均替代累积和,动态控制学习率
RMSProp(Root Mean Square Propagation)是 AdaGrad 的改进,核心解决学习率过早衰减 问题:用梯度平方的指数加权平均替代累积和,赋予近期梯度更高权重,远期梯度权重衰减,避免s无限增长。
算法公式(教材核心)
- 维护梯度平方的指数加权平均s(初始化为 0);
- 批量梯度计算:g=∇LB(θ);
- 更新指数加权平均:s←γs+(1−γ)g⊙g其中γ∈[0,1)为衰减系数(默认 0.9);
- 参数更新:θ←θ−s+ϵη⊙g
8.2 核心改进:动态平衡近期与远期梯度
- 近期梯度主导:γ=0.9时,近期 10 步梯度权重占比约 65%,远期梯度影响小;
- 学习率动态稳定:s不再无限增长,后期稳定在合理范围,学习率保持有效更新;
- 适配深层网络:解决 AdaGrad 的收敛停滞问题,可用于 CNN、RNN 等深层模型。
8.3 代码实现(PyTorch 内置)
# 延续11.5.3的模型与dataloader
optimizer = torch.optim.RMSprop(model.parameters(), lr=0.01, alpha=0.9, eps=1e-6)
8.4 优缺点与适用场景
优点
- 解决 AdaGrad 的过早衰减问题:深层网络收敛稳定,无停滞;
- 稀疏数据友好:保留自适应学习率特性,适配高维稀疏数据;
- 超参数鲁棒:γ默认 0.9,全局学习率 0.01,无需精细调优。
缺点
- 对学习率敏感:全局学习率过大易震荡,过小收敛慢;
- 无动量加速:相比动量法,收敛速度略慢。
适用场景
- CV 任务:CNN、ResNet、GAN 生成对抗网络;
- NLP 浅层任务:文本分类、情感分析;
- 稀疏数据 + 深层模型:推荐系统深度模型、多模态稀疏特征融合。
九 Adadelta 算法:无需全局学习率的自适应算法
9.1 核心思想:用参数更新量的历史缩放替代全局学习率
Adadelta 是 RMSProp 的扩展,核心突破:完全移除全局学习率,用参数更新量的指数加权平均动态缩放梯度,实现 "无学习率" 的自适应优化。
算法公式(教材核心,简化版)
- 维护两个指数加权平均:
- s:梯度平方的指数加权平均(同 RMSProp);
- Δθ:参数更新量的指数加权平均(初始化为 0);
- 批量梯度计算:g=∇LB(θ);
- 更新梯度平方平均:s←γs+(1−γ)g⊙g;
- 计算自适应学习率:ηt=s+ϵΔθ+ϵ;
- 参数更新:Δθt=−ηt⊙g,θ←θ+Δθt;
- 更新参数更新量平均:Δθ←γΔθ+(1−γ)Δθt⊙Δθt。
9.2 核心特性:无全局学习率、自动缩放更新量
- 无需手动设置学习率:完全自适应,鲁棒性极强;
- 更新量与梯度量级匹配:避免梯度量级过大 / 过小导致的震荡或收敛慢;
- 适配深层网络:无学习率衰减问题,收敛稳定。
9.3 代码实现(PyTorch 内置)
# 延续11.5.3的模型与dataloader
optimizer = torch.optim.Adadelta(model.parameters(), rho=0.9, eps=1e-6)
9.4 优缺点与适用场景
优点
- 零学习率调优:开箱即用,适合快速实验;
- 收敛稳定:自适应缩放更新量,无震荡;
- 适配深层 / 复杂模型:如 GAN、Transformer 浅层。
缺点
- 收敛速度慢于 Adam:工业界主流场景被 Adam 替代;
- 超参数 rho 需微调:默认 0.9,部分场景需降至 0.85。
适用场景
- 快速原型验证:无需调学习率,快速验证模型有效性;
- GAN 生成器训练:生成器梯度易震荡,Adadelta 稳定性强;
- 小数据集深层模型:数据少、模型复杂,需稳定收敛。
十 Adam 算法:工业界全能王者(动量 + 自适应学习率融合)
10.1 核心思想:融合动量法与 RMSProp,兼顾收敛速度与稳定性
Adam(Adaptive Moment Estimation)是动量法 + RMSProp 的融合算法,集大成者:
- 引入一阶动量(梯度均值):同动量法,加速收敛、抑制震荡;
- 引入二阶动量(梯度平方均值):同 RMSProp,自适应学习率、稀疏友好;
- 工业界默认首选优化算法,适配 90% 以上深度学习任务。
算法公式(教材核心,完整版)
- 维护四个变量:
- 一阶动量m(梯度均值,初始 0);
- 二阶动量v(梯度平方均值,初始 0);
- 一阶动量系数β1(默认 0.9);
- 二阶动量系数β2(默认 0.999);
- 批量梯度计算:g=∇LB(θ);
- 更新一阶动量:m←β1m+(1−β1)g
- 更新二阶动量:v←β2v+(1−β2)g⊙g
- 偏差修正(解决初期动量偏置):m^=1−β1tm,v^=1−β2tv(t为迭代次数)
- 参数更新:θ←θ−v^+ϵη⊙m^
10.2 核心特性:全能型优化算法
- 动量加速:一阶动量加速收敛,抑制震荡,收敛速度接近动量法;
- 自适应学习率:二阶动量为每个参数分配独立学习率,稀疏 / 稠密数据均友好;
- 偏差修正:解决初期动量偏小问题,初期收敛更稳定;
- 超参数鲁棒:默认β1=0.9、β2=0.999、η=0.001,适配绝大多数场景。
10.3 代码实现(PyTorch 内置,工业界标准配置)
# 延续11.5.3的模型与dataloader
optimizer = torch.optim.Adam(
model.parameters(),
lr=0.001,
betas=(0.9, 0.999),
eps=1e-8,
weight_decay=1e-4 # 权重衰减,抑制过拟合
)
10.4 Adam 变种(工业界进阶选择)
1. AdamW:权重衰减修正(解决 Adam 过拟合)
AdamW 是 Adam 的改进,核心修正:权重衰减与梯度更新解耦 ,避免权重衰减被自适应学习率抵消,抑制过拟合效果显著,是 BERT、ViT 等大模型的首选优化器。
PyTorch 实现:
optimizer = torch.optim.AdamW(model.parameters(), lr=0.001, weight_decay=1e-4)
2. Adamax:无穷范数稳定(高维梯度场景)
Adamax 用无穷范数 替代二阶动量的 L2 范数,梯度更新更稳定,适配高维稀疏梯度场景(如超大词表 NLP 模型)。
10.5 优缺点与避坑指南(高频踩坑点)
优点
- 全能型选手:收敛速度快、稳定性强、稀疏 / 稠密数据友好、深层 / 浅层模型适配;
- 超参数少且鲁棒:默认配置开箱即用,无需精细调优;
- 工业界标准:CV、NLP、多模态、强化学习等 90% 以上任务首选。
缺点
- 易过拟合:自适应学习率易过度优化训练集,需配合权重衰减、早停;
- 对学习率敏感:大模型训练需用 Warmup,避免初期学习率过大震荡;
- 显存占用略高:维护两个动量变量,显存占用比 SGD 高约 20%。
避坑指南(工业界实战总结)
- 大模型必须用 Warmup:训练前 1000 步学习率从 0 线性升至 0.001,避免初期震荡;
- 权重衰减必加:Adam 默认无权重衰减,过拟合严重,建议设为 1e-4~1e-5;
- 学习率默认 0.001:CV 任务可降至 0.0001,NLP 任务(如 BERT)常用 5e-5;
- 避免梯度爆炸:梯度裁剪(max_norm=1.0~5.0),尤其在 RNN/LSTM、GAN 中;
- 小数据集慎用:小数据集(<10k 样本)易过拟合,优先用 SGD + 动量。
十一 学习率调度器:优化收敛的 "辅助引擎"
11.1 核心思想:动态调整学习率,平衡收敛速度与精度
学习率是优化算法的核心超参数 ------大学习率快速收敛,小学习率精细收敛 。学习率调度器的作用:随训练进程动态降低学习率 ,实现 "先快后慢" 的收敛策略,避免后期震荡,提升最终精度。
11.2 主流学习率调度器(教材核心 + 工业界常用)
1. 固定衰减(StepLR):每隔固定轮次衰减
-
核心逻辑:每过
step_size个 epoch,学习率乘以gamma(如 0.5); -
适用场景:简单模型、快速实验;
-
PyTorch 实现:
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.5)
2. 余弦退火(CosineAnnealingLR):余弦曲线平滑衰减
-
核心逻辑:学习率按余弦函数从初始值平滑降至 0,无突变,收敛更稳定;
-
适用场景:大模型、高精度任务(如 ImageNet 分类、BERT 微调);
-
PyTorch 实现:
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=50)
3. Warmup + 余弦退火(工业界主流):初期升温 + 后期平滑衰减
-
核心逻辑:前 N 步 Warmup(学习率从 0 线性升至初始值),之后余弦退火衰减;
-
解决痛点:大模型训练初期梯度不稳定,高学习率易震荡;
-
PyTorch 实现(需自定义或用
transformers库):from transformers import get_cosine_schedule_with_warmup
scheduler = get_cosine_schedule_with_warmup(
optimizer, num_warmup_steps=1000, num_training_steps=10000
)
4. 自适应衰减(ReduceLROnPlateau):验证集损失停滞时衰减
-
核心逻辑:监控验证集损失,若连续
patience个 epoch 无下降,学习率乘以gamma; -
适用场景:数据分布复杂、收敛不稳定的任务;
-
PyTorch 实现:
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.5, patience=5)
11.3 学习率调度器使用核心要点
- 调度器需在每个 epoch 结束后调用 :
scheduler.step(); - Warmup 是大模型必备:BERT、ViT、GPT 等模型训练前 1000-5000 步必须 Warmup;
- 学习率与批量大小联动:Batch Size 翻倍,初始学习率翻倍,调度器同步调整;
- 优先余弦退火:相比固定衰减,余弦退火收敛更稳定,最终精度更高。
十二 优化算法实际学习场景适配指南
12.1 场景 1:计算机视觉(CV)任务(CNN/ResNet/ViT)
- 首选优化器:AdamW(ViT / 大模型)、SGD + 动量(ResNet / 传统 CNN);
- 学习率:AdamW=1e-4~5e-5,SGD=0.1~0.01;
- 批量大小:32/64(单 GPU),大模型用梯度累积;
- 调度器:Warmup + 余弦退火;
- 避坑要点:CNN 用 SGD + 动量(0.9)泛化能力更强,ViT 必须用 AdamW+Warmup。
12.2 场景 2:自然语言处理(NLP)任务(BERT/RNN/Transformer)
- 首选优化器:AdamW(BERT/Transformer)、Adam(RNN/LSTM);
- 学习率:BERT=5e-5~2e-5,RNN=1e-3~1e-4;
- 批量大小:16/32(受序列长度限制);
- 调度器:Warmup(1000 步)+ 余弦退火;
- 避坑要点:BERT 微调禁用权重衰减(或设为 0),RNN 需梯度裁剪(max_norm=1.0)。
12.3 场景 3:推荐系统 / 广告(高维稀疏数据)
- 首选优化器:AdaGrad(浅层模型)、RMSProp(深层模型);
- 学习率:AdaGrad=0.01,RMSProp=0.001;
- 批量大小:64/128;
- 调度器:固定衰减;
- 避坑要点:稀疏特征模型禁用 Adam,易过拟合,优先 AdaGrad/RMSProp。
12.4 场景 4:小数据集 / 快速原型验证
- 首选优化器:SGD + 动量(0.9)、Adadelta;
- 学习率:SGD=0.01~0.1;
- 批量大小:8/16;
- 调度器:固定衰减或无;
- 避坑要点:小数据集禁用 Adam,过拟合严重,优先 SGD + 动量。
12.5 场景 5:生成对抗网络(GAN)
- 首选优化器:RMSProp(生成器)、Adam(判别器);
- 学习率:生成器 = 0.0001,判别器 = 0.001;
- 批量大小:64;
- 调度器:无或自适应衰减;
- 避坑要点:GAN 训练不稳定,生成器用 RMSProp 抑制梯度震荡,判别器用 Adam 加速收敛。
十三 优化算法高频避坑指南(汇总版)
13.1 通用避坑点(所有算法适用)
- 学习率过大 / 过小:过大震荡不收敛,过小收敛极慢;默认搜索范围:1e-5~0.1;
- 批量大小不合理:过小噪声大,过大泛化差;优先 32/64,大模型用梯度累积;
- 梯度爆炸 / 消失:梯度裁剪(max_norm=1.0~5.0)、权重初始化、BatchNorm;
- 过拟合:权重衰减、Dropout、早停、数据增强;
- 未使用学习率调度:后期震荡,精度下降;优先 Warmup + 余弦退火。
13.2 算法专属避坑点
SGD + 动量
- 动量系数默认 0.9,NLP 可降至 0.8;
- 学习率比 Adam 大 10 倍(如 0.1 vs 0.001)。
Adam/AdamW
- 必须加权重衰减(1e-4~1e-5),否则过拟合;
- 大模型必须 Warmup,避免初期震荡;
- 小数据集禁用,泛化能力差。
AdaGrad
- 仅用于高维稀疏数据 + 浅层模型;
- 深层模型易收敛停滞,优先 RMSProp/Adam。
RMSProp
- 学习率默认 0.001,CV 任务可降至 0.0001;
- 无动量加速,收敛慢于 Adam。
十四 本章学习计划(4 周系统掌握)
第 1 周:理论筑基(理解核心逻辑)
- 任务 1:精读教材 11.1-11.5 节,掌握 GD/SGD/MB-SGD 的核心思想、公式、优缺点;
- 任务 2:推导凸函数性质、梯度下降收敛条件;
- 任务 3:从零实现 GD/SGD/MB-SGD 代码,对比收敛曲线;
- 目标:能区分三种基础算法的差异,独立实现代码。
第 2 周:进阶算法(动量 + 自适应学习率)
- 任务 1:精读教材 11.6-11.10 节,掌握动量法、AdaGrad、RMSProp、Adam 的核心改进;
- 任务 2:推导 Adam 公式,理解一阶 / 二阶动量、偏差修正的作用;
- 任务 3:用 PyTorch 内置优化器实现动量法、Adam,对比 SGD 收敛速度;
- 目标:能解释各进阶算法的改进动机,熟练使用 PyTorch 优化器。
第 3 周:学习率调度 + 场景适配
- 任务 1:精读教材 11.11 节,掌握主流学习率调度器的逻辑与使用;
- 任务 2:在 CV/NLP 小数据集上,对比不同调度器(StepLR / 余弦退火 / Warmup)的效果;
- 任务 3:按 11.12 节场景,为不同任务选择优化器、学习率、批量大小;
- 目标:能根据任务场景制定优化方案,熟练使用学习率调度器。
第 4 周:实战项目 + 避坑总结
- 任务 1:实战项目(二选一):
- CV:用 ResNet 训练 CIFAR-10,对比 SGD + 动量 vs AdamW;
- NLP:用 BERT 微调文本分类任务,使用 AdamW+Warmup;
- 任务 2:记录训练过程中的问题(震荡、过拟合、收敛慢),用避坑指南解决;
- 任务 3:总结本章知识点,绘制优化算法对比表;
- 目标:能独立完成实战项目,解决训练中的常见问题。
十五 下章预告
下一章 计算性能 将聚焦深度学习训练的效率优化,核心内容包括:
- 硬件加速:GPU/TPU 原理、多 GPU 并行训练(数据并行 / 模型并行);
- 内存优化:梯度累积、混合精度训练(AMP)、模型量化;
- 计算图优化:PyTorch JIT、算子优化;
- 分布式训练:DDP、ZeRO、大模型训练策略。
掌握本章优化算法后,下一章将帮你解决大模型训练慢、显存不足的痛点,实现高效模型训练。
互动 & 收藏关注
🎉 本章万字长文深度解析了深度学习优化算法的理论、代码、场景与避坑指南,从基础 GD 到工业界全能 Adam,从理论推导到实战适配,全覆盖无死角!
💡 互动话题:
- 你在模型训练中遇到过哪些优化问题?(如震荡、过拟合、收敛慢)
- 你最常用的优化算法是什么?在哪个场景下效果最好?
- 对下一章 "计算性能" 有哪些期待?
👇 收藏 + 关注不迷路,后续将持续更新《动手学深度学习(PyTorch 版)》全章节万字解析,配套代码、实战项目、避坑指南,帮你系统吃透深度学习核心技术!