共计 1659 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点:标准 BP 的数学缺陷
标准反向传播的权重更新公式为:
$$\Delta w_{ij} = -\eta \frac{\partial L}{\partial w_{ij}}$$
当使用 sigmoid 激活时,其导数最大值为 0.25,多层链式求导会出现梯度衰减:
$$\frac{\partial L}{\partial w_1} = \frac{\partial L}{\partial o_n} \cdot \prod_{k=2}^{n} (o_k(1-o_k)w_k) $$

- 当网络层数 n >5 时,梯度值可能衰减到 1e-10 量级
- 参数初始值过大时会导致梯度爆炸(如超过 1e5)
优化器对比实验
在 TensorBoard 中对比不同优化器的收敛速度:
# 可视化代码示例
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter()
for epoch in range(100):
# 训练代码...
writer.add_scalars('Optimizers', {
'SGD': sgd_loss,
'Adam': adam_loss,
'RMSprop': rms_loss
}, epoch)
典型现象:
– Momentum 能在鞍点处加速逃离(β=0.9 时效果最佳)
– Adam 在稀疏梯度场景下表现优异
– RMSprop 对循环结构更稳定
PyTorch 自定义优化器实现
梯度裁剪
def train():
optimizer.zero_grad()
loss.backward()
# 限制梯度 L2 范数不超过 1.0
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
optimizer.step()
学习率调度
# 余弦退火 +warmup
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=100, eta_min=1e-5)
for epoch in range(100):
# 前 5 个 epoch 线性 warmup
if epoch < 5:
lr_scale = 0.1 + 0.9 * epoch / 5
for param_group in optimizer.param_groups:
param_group['lr'] = lr_scale * base_lr
scheduler.step()
生产环境注意事项
多 GPU 训练
- 使用
DistributedDataParallel而非DataParallel - 梯度同步用
all_reduce而非reduce - 确保
find_unused_parameters=True时不会漏同步
AMP 混合精度
with torch.cuda.amp.autocast():
outputs = model(inputs)
loss = criterion(outputs, targets)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update() # 检查 inf/NaN 值
三大典型错误
-
梯度累积未清零
# 错误示范 for i, data in enumerate(dataloader): loss.backward() # 梯度累加 if i % 8 == 0: optimizer.step() # 正确做法 optimizer.zero_grad(set_to_none=True) # 显存优化 -
误用 detach 切断计算图
# 错误示例 hidden = lstm(x).detach() # 阻断梯度传播 # 解决方案 with torch.no_grad(): # 仅前向时不保存计算图 hidden = lstm(x) -
BatchNorm 状态不一致
- 验证时需设置
model.eval()模式 - 分布式训练时同步 BN 统计量
开放性问题
当 batch size 超过 1 万时:
– 梯度方差修正是否需要调整系数?
– 超大 batch 下 Adam 的动量补偿是否依然有效?
建议通过 CIFAR-100 的对比实验验证(调整 –batch-size=10240)
正文完
