深度学习:反向传播算法(Backpropagation)
本节目标:
- 理解神经网络是如何“学会”调整参数的
- 掌握反向传播算法(BP)的核心原理与数学推导
- 理解链式法则(Chain Rule)在多层网络中的作用
- 分析反向传播过程中的常见问题(如梯度消失/爆炸)
- 理解PyTorch中自动求导的工作机制
一、什么是反向传播算法?
反向传播(Backpropagation)是神经网络中用于计算损失函数对每个参数梯度的算法。
该算法是深度学习训练的核心步骤,用于回答“当前网络输出错了多少,哪一层的参数该如何调整”
二、反向传播的工作流程概览
神经网络训练过程可分为三个阶段:
阶段 | 描述 |
前向传播 | 从输入出发,逐层计算输出 |
损失计算 | 计算预测值与真实标签的差距 |
反向计算 | 反向计算每个参数的梯度(偏导数) |
参数更新 | 使用优化器(如SGD/Adam)更新参数值 |
三、数学原理:链式法则是关键
设神经网络由层级函数组合而成:
若损失函数为 ,则对于每一层参数
的梯度:
上述为链式法则,即“输出对参数的导数 = 输出对中间变量的导数 × 中间变量对参数的导数”
四、一个三层神经网络反向传播示例
以最简单的三层网络(输入层-隐藏层-输出层)为例:
网络结构:
假设损失函数为交叉熵:
目标:计算,
我们从后往前,逐层链式求导(即反向传播)
1.输出层导数:
2.二层权重导数
3.一层激活反传:
4.一层权重导数:
五、梯度下降与反向传播结合
完整训练流程如下:
输入数据 → 前向传播 → 计算损失 → 反向传播 → 优化器更新参数 → 下一轮训练
六、常见问题:梯度消失与梯度爆炸
梯度消失(Gradient Vanishing)
出现位置:深层网络,激活函数饱和(如Sigmoid)
表现:前面几层梯度变得非常小,网络无法学习
解决:
- 使用ReLU/GELU替代Sigmoid/Tanh
- 使用残差连接(如ResNet)
- 使用BatchNorm/LayerNorm
梯度爆炸(Gradient Explosion)
出现位置:深层或递归网络(RNN)
表现:权重变得非常大,loss为nan
解决:
- 梯度裁剪(gradient clipping)
- 参数初始化优化(如Xavier,He)
- 更稳健的优化器(如Adam)
七、PyTorch中的反向传播机制
自动求导机制(Autograd)
import torchx = torch.tensor(2.0, requires_grad=True)
y = x**2 + 3*x + 5
y.backward()
print(x.grad) # 输出 dy/dx
神经网络训练流程中:
loss.backward() # 自动计算所有参数的梯度
optimizer.step() # 根据梯度更新参数
optimizer.zero_grad() # 清零梯度(防止累加)
八、图解记忆法:反向传播流程
输入 x↓
前向传播(W·x + b → 激活)↓
输出层(Softmax)↓
损失函数(CrossEntropy)↓
反向传播(从输出层依次往前算梯度)↓
更新参数(W, b)
九、实战建议
场景 | 建议 |
---|---|
Loss 一直不下降 | 检查反向传播是否执行了 backward() 和 step() |
loss = nan | 可能梯度爆炸,尝试梯度裁剪 |
学习率过大 | 会导致 loss 上下跳动甚至发散 |
梯度全为0 | 可能 ReLU 死神经元或前向没有连接好参数 |
不确定梯度是否正确 | 可用 torch.autograd.gradcheck() 进行检查 |
十、小结
概念 | 功能 |
---|---|
链式法则 | 逐层计算梯度的核心 |
backward() | 自动触发梯度传播 |
optimizer.step() | 根据梯度调整参数 |
optimizer.zero_grad() | 清零上一轮残留梯度 |
梯度裁剪 | 防止梯度爆炸 |
激活函数选择 | 防止梯度消失 |