前向传播从输入计算输出,反向传播用链式法则求梯度,二者构成神经网络训练的核心循环。训练计算量约为推理的 3 倍。
核心概念
神经网络训练的本质是:通过不断调整参数(权重 、偏置 ),使预测输出逼近真实值。
| 概念 | 说明 |
|---|---|
| 模型 | 参数(权重 、偏置 )+ 计算流程(层与层之间的变换) |
| 前向传播 | 从输入出发,沿计算流程正向计算到输出,得到预测值 |
| 损失函数 | 衡量预测值与真实值的差距,如 MSE、CrossEntropy |
| 反向传播 | 从损失出发,逆向求导,计算每个参数的梯度 |
| 梯度下降 | 用梯度调整参数,最小化损失 |
训练循环:
初始化参数 → 前向传播 → 计算损失 → 反向传播 → 参数更新 → 循环前向传播:从输入到输出
前向传播是纯粹的计算过程:给定输入 和当前参数,按网络结构逐层计算,最终得到输出 。
单神经元示例(数值计算)
最简单的神经网络单元——单个神经元:
其中:
- :输入值
- :权重,决定输入对输出的影响程度
- :偏置,调整输出的基准值
- :预测输出
具体计算(假设 , , ):
计算损失(假设真实值 ,使用 MSE 损失):
**为什么用 **:为了求导方便, ,系数正好是 1。
多层神经网络示例
输入 ,经过隐藏层和输出层:
隐藏层(权重 ,偏置 ):
激活函数(Sigmoid):
输出层(权重 ,偏置 ):
矩阵形式的前向传播(实际实现)
实际神经网络的每一层是矩阵运算,可并行处理多个样本。
单层线性层前向传播:
其中:
- : 个样本,每个样本 维特征
- :权重矩阵,将 维映射到 维
- :偏置向量
- :输出矩阵
理解矩阵乘法: 的每个元素 是 的第 行与 的第 列的内积,表示第 个样本在第 个输出维度上的值。
前向传播的特点
- 纯计算过程,依赖输入和当前参数
- 中间值被框架记录,构建计算图(用于后续反向传播)
- 计算量主要由矩阵乘法决定,受内存带宽限制
反向传播:从损失到梯度
反向传播的核心任务:计算损失函数 对每个参数的梯度 、 ,用于参数更新。
链式法则(数学基础)
反向传播依赖链式法则处理复合函数的求导。
单变量链式法则:
若 ,即 通过中间变量 依赖于 ,则:
直观理解:把复杂函数拆成简单环节,逐环节求导,再相乘得到整体导数。
多变量链式法则:
若 同时依赖于 和 ,而 、 都依赖于 :
单神经元反向传播(数值推导)
回到前面的单神经元示例,求 和 。
计算链路:
逐环节求导:
-
损失对预测的导数:
-
预测对权重的导数:
-
预测对偏置的导数:
链式法则组合:
梯度含义:
- :权重增加 1,损失减少 2(应增加权重)
- :偏置增加 1,损失减少 1(应增加偏置)
参数更新(梯度下降)
用梯度调整参数(学习率 ):
更新后重新前向传播:
损失变小( 比 更接近 ),说明更新方向正确。
矩阵形式的反向传播
对于线性层 ,反向传播需要计算三类梯度:
| 梯度 | 用途 | 公式 |
|---|---|---|
| 更新本层参数 | ||
| 更新本层偏置 | (沿样本轴求和) | |
| 传递误差给前一层 |
**推导 **:
,即
对 求偏导:
由链式法则:
这正是矩阵乘法 的第 个元素。
**推导 **:
类似地,
**为什么必须算 **:它是误差传递给前一层的唯一桥梁。多层网络中,每层都需要接收来自后层的误差信号( ),才能计算本层参数梯度。
计算量分析
矩阵乘法的 FLOPs(浮点运算数): ,其中 ,
每个输出元素需要 次乘法和 次加法(约 次运算),共 个输出元素。
设线性层维度: , ( 样本数, 输入维度, 输出维度)
| 阶段 | 计算 | FLOPs |
|---|---|---|
| 前向传播 | ||
| 反向传播(算 ) | ||
| 反向传播(算 ) | ||
| 训练总计 | 前向 + 反向 | ** ** |
| 推理 | 仅前向 | ** ** |
结论:训练计算量 ≈ 3 倍推理。
为什么反向比前向慢:反向传播需要保存前向传播的中间结果(用于求导),显存读写开销大。
梯度问题与解决方案
梯度消失
深层网络中,梯度逐层相乘。如果每层梯度小于 1,经过多层后梯度趋近于 0,前层参数几乎无法更新。
典型场景:Sigmoid 激活函数,
梯度爆炸
如果每层梯度大于 1,经过多层后梯度指数级增大,参数更新剧烈,训练不稳定。
解决方案
| 方案 | 机制 |
|---|---|
| LayerNorm | 标准化每层的输出分布,稳定梯度范围 |
| 残差连接 | 梯度可跨层直接传递,不经过激活函数衰减 |
| 梯度裁剪 | 强制限制梯度上限,防止爆炸 |
| ReLU 激活 | 正区间导数恒为 1,避免梯度衰减 |
PyTorch 实现
import torch
import torch.nn as nn
import torch.optim as optim
# 定义模型
model = nn.Linear(10, 5)
optimizer = optim.SGD(model.parameters(), lr=0.01)
loss_fn = nn.MSELoss()
# 训练循环
for x, y_true in data_loader:
# 1. 前向传播
y_pred = model(x)
loss = loss_fn(y_pred, y_true)
# 2. 反向传播
optimizer.zero_grad() # 清零旧梯度
loss.backward() # 自动计算所有参数梯度
# 3. 参数更新
optimizer.step() # 梯度下降更新参数框架自动实现:
- PyTorch 在前向传播时自动构建计算图
loss.backward()自动应用链式法则求导- 梯度存储在
param.grad中
实践要点
| 场景 | 要点 |
|---|---|
| 分布式训练 | 反向传播后 AllReduce 同步梯度 |
| 性能优化 | 前向优化内存带宽,反向利用通信-计算重叠 |
| 混合精度 | 前向用 FP16,梯度累加用 FP32,减少显存 |
| 梯度累积 | 小 batch 多次前向+反向,累积梯度后一次更新 |
总结
| 阶段 | 输入 | 输出 | 核心操作 |
|---|---|---|---|
| 前向传播 | 数据 、参数 | 预测 、损失 | 矩阵乘法、激活函数 |
| 反向传播 | 损失 | 梯度 、 | 链式法则求导 |
| 参数更新 | 梯度、学习率 | 新参数 | 梯度下降 |
核心公式:
训练的本质:通过前向-反向循环,不断用梯度修正参数,使损失函数最小化。