一、反向传播基础概念
-
定义:反向传播是神经网络中用于计算参数梯度、进而通过优化器更新参数的核心算法,核心逻辑是“从输出层到输入层,沿前向传播的反方向传递误差,并计算各层参数对损失的梯度”。
-
核心作用:解决神经网络参数优化问题,通过梯度指引参数调整方向,使模型的损失函数值不断减小,最终提升模型预测精度。
-
前置知识:
-
链式法则:多变量函数求导的核心规则,反向传播中梯度的传递依赖链式法则逐层计算。
-
损失函数:用于衡量模型预测值与真实值的差异,如均方误差(MSE)、交叉熵损失等,是反向传播的“误差源头”。
-
神经网络基本结构:需明确输入层、隐藏层、输出层的神经元数量,以及各层使用的激活函数(如Sigmoid、ReLU)。
-
二、反向传播核心原理(三步法)

1. 第一步:前向传播(计算预测值与损失)
-
按“输入层→隐藏层→输出层”的顺序,计算每一层的输出值。
-
以单隐藏层网络为例,假设输入为 xxx ,隐藏层权重为 W1W_1W1 、偏置为 b1b_1b1 ,激活函数为 σ\sigmaσ ,输出层权重为 W2W_2W2 、偏置为 b2b_2b2 ,则:
-
隐藏层输入: z1=W1x+b1z_1 = W_1x + b_1z1=W1x+b1
-
隐藏层输出: a1=σ(z1)a_1 = \sigma(z_1)a1=σ(z1)
-
输出层输入: z2=W2a1+b2z_2 = W_2a_1 + b_2z2=W2a1+b2
-
模型预测值: ypred=σ(z2)y_{pred} = \sigma(z_2)ypred=σ(z2) (若为回归任务,输出层可无激活函数)
-
-
计算损失:根据损失函数,对比 ypredy_{pred}ypred 与真实标签 ytruey_{true}ytrue ,得到损失值 LLL (如MSE损失 L=12(ypred−ytrue)2L = \frac{1}{2}(y_{pred} - y_{true})^2L=21(ypred−ytrue)2 )。
2. 第二步:反向传播(计算各参数梯度)
-
从输出层开始,沿“输出层→隐藏层→输入层”的反方向,利用链式法则计算各参数( W2W_2W2 、 b2b_2b2 、 W1W_1W1 、 b1b_1b1 )对损失 LLL 的梯度。
-
关键梯度计算逻辑:
-
输出层参数梯度:先求损失对输出层输入 z2z_2z2 的梯度(记为 δ2=∂L∂z2\delta_2 = \frac{\partial L}{\partial z_2}δ2=∂z2∂L ),再结合隐藏层输出 a1a_1a1 ,得到 ∂L∂W2=δ2⋅a1T\frac{\partial L}{\partial W_2} = \delta_2 \cdot a_1^T∂W2∂L=δ2⋅a1T 、 ∂L∂b2=δ2\frac{\partial L}{\partial b_2} = \delta_2∂b2∂L=δ2 。
-
隐藏层参数梯度:先将输出层的梯度 δ2\delta_2δ2 传递到隐藏层,得到损失对隐藏层输入 z1z_1z1 的梯度( δ1=W2T⋅δ2⋅σ′(z1)\delta_1 = W_2^T \cdot \delta_2 \cdot \sigma'(z_1)δ1=W2T⋅δ2⋅σ′(z1) ,其中 σ′(z1)\sigma'(z_1)σ′(z1) 是激活函数的导数),再结合输入 xxx ,得到 ∂L∂W1=δ1⋅xT\frac{\partial L}{\partial W_1} = \delta_1 \cdot x^T∂W1∂L=δ1⋅xT 、 ∂L∂b1=δ1\frac{\partial L}{\partial b_1} = \delta_1∂b1∂L=δ1 。
-
3. 第三步:参数更新(基于梯度优化)
- 利用计算出的参数梯度,结合优化器(如随机梯度下降SGD)更新参数,更新公式为: Wnew=Wold−η⋅∂L∂WW_{new} = W_{old} - \eta \cdot \frac{\partial L}{\partial W}Wnew=Wold−η⋅∂W∂L , bnew=bold−η⋅∂L∂bb_{new} = b_{old} - \eta \cdot \frac{\partial L}{\partial b}bnew=bold−η⋅∂b∂L ,其中 η\etaη 是学习率(控制每步参数更新的幅度)。
三、具体计算案例(单隐藏层神经网络)
1. 案例设定
-
网络结构:输入层(1个神经元, x=1x=1x=1 )→ 隐藏层(2个神经元)→ 输出层(1个神经元)。
-
激活函数:全层使用Sigmoid函数( σ(z)=11+e−z\sigma(z) = \frac{1}{1+e^{-z}}σ(z)=1+e−z1 ,导数 σ′(z)=σ(z)(1−σ(z))\sigma'(z) = \sigma(z)(1-\sigma(z))σ′(z)=σ(z)(1−σ(z)) )。
-
初始参数: W1=[0.10.20.30.4]W_1 = \begin{bmatrix} 0.1 & 0.2 \\ 0.3 & 0.4 \end{bmatrix}W1=[0.10.30.20.4] , b1=[0.50.6]b_1 = \begin{bmatrix} 0.5 \\ 0.6 \end{bmatrix}b1=[0.50.6] ; W2=[0.70.8]W_2 = \begin{bmatrix} 0.7 & 0.8 \end{bmatrix}W2=[0.70.8] , b2=0.9b_2 = 0.9b2=0.9 。
-
真实标签: ytrue=0.5y_{true} = 0.5ytrue=0.5 。
2. 第一步:前向传播计算
-
隐藏层输入: z1=W1x+b1=[0.1×1+0.50.3×1+0.6]=[0.60.9]z_1 = W_1x + b_1 = \begin{bmatrix} 0.1×1 + 0.5 \\ 0.3×1 + 0.6 \end{bmatrix} = \begin{bmatrix} 0.6 \\ 0.9 \end{bmatrix}z1=W1x+b1=[0.1×1+0.50.3×1+0.6]=[0.60.9]
-
隐藏层输出: a1=σ(z1)=[11+e−0.6≈0.645711+e−0.9≈0.7109]a_1 = \sigma(z_1) = \begin{bmatrix} \frac{1}{1+e^{-0.6}} ≈ 0.6457 \\ \frac{1}{1+e^{-0.9}} ≈ 0.7109 \end{bmatrix}a1=σ(z1)=[1+e−0.61≈0.64571+e−0.91≈0.7109]
-
输出层输入: z2=W2a1+b2=0.7×0.6457+0.8×0.7109+0.9≈0.452+0.5687+0.9≈1.9207z_2 = W_2a_1 + b_2 = 0.7×0.6457 + 0.8×0.7109 + 0.9 ≈ 0.452 + 0.5687 + 0.9 ≈ 1.9207z2=W2a1+b2=0.7×0.6457+0.8×0.7109+0.9≈0.452+0.5687+0.9≈1.9207
-
预测值: ypred=σ(z2)≈11+e−1.9207≈0.8707y_{pred} = \sigma(z_2) ≈ \frac{1}{1+e^{-1.9207}} ≈ 0.8707ypred=σ(z2)≈1+e−1.92071≈0.8707
-
损失值(MSE): L=12(0.8707−0.5)2≈12×0.1374≈0.0687L = \frac{1}{2}(0.8707 - 0.5)^2 ≈ \frac{1}{2}×0.1374 ≈ 0.0687L=21(0.8707−0.5)2≈21×0.1374≈0.0687
3. 第二步:反向传播计算梯度
-
计算输出层梯度( δ2\delta_2δ2 ):
-
δ2=∂L∂z2=(ypred−ytrue)⋅σ′(z2)\delta_2 = \frac{\partial L}{\partial z_2} = (y_{pred} - y_{true}) \cdot \sigma'(z_2)δ2=∂z2∂L=(ypred−ytrue)⋅σ′(z2) 。
-
σ′(z2)=0.8707×(1−0.8707)≈0.1126\sigma'(z_2) = 0.8707×(1-0.8707) ≈ 0.1126σ′(z2)=0.8707×(1−0.8707)≈0.1126 。
-
δ2=(0.8707−0.5)×0.1126≈0.3707×0.1126≈0.0417\delta_2 = (0.8707 - 0.5)×0.1126 ≈ 0.3707×0.1126 ≈ 0.0417δ2=(0.8707−0.5)×0.1126≈0.3707×0.1126≈0.0417 。
-
-
计算输出层参数梯度:
-
∂L∂W2=δ2⋅a1T≈0.0417×[0.64570.7109]≈[0.02690.0296]\frac{\partial L}{\partial W_2} = \delta_2 \cdot a_1^T ≈ 0.0417×\begin{bmatrix} 0.6457 & 0.7109 \end{bmatrix} ≈ \begin{bmatrix} 0.0269 & 0.0296 \end{bmatrix}∂W2∂L=δ2⋅a1T≈0.0417×[0.64570.7109]≈[0.02690.0296] 。
-
∂L∂b2=δ2≈0.0417\frac{\partial L}{\partial b_2} = \delta_2 ≈ 0.0417∂b2∂L=δ2≈0.0417 。
-
-
计算隐藏层梯度( δ1\delta_1δ1 ):
-
δ1=W2T⋅δ2⋅σ′(z1)\delta_1 = W_2^T \cdot \delta_2 \cdot \sigma'(z_1)δ1=W2T⋅δ2⋅σ′(z1)
-
σ′(z1)=[0.6457×(1−0.6457)≈0.22810.7109×(1−0.7109)≈0.2055]\sigma'(z_1) = \begin{bmatrix} 0.6457×(1-0.6457) ≈ 0.2281 \\ 0.7109×(1-0.7109) ≈ 0.2055 \end{bmatrix}σ′(z1)=[0.6457×(1−0.6457)≈0.22810.7109×(1−0.7109)≈0.2055]
-
W2T⋅δ2=[0.7×0.04170.8×0.0417]≈[0.02920.0334]W_2^T \cdot \delta_2 = \begin{bmatrix} 0.7×0.0417 \\ 0.8×0.0417 \end{bmatrix} ≈ \begin{bmatrix} 0.0292 \\ 0.0334 \end{bmatrix}W2T⋅δ2=[0.7×0.04170.8×0.0417]≈[0.02920.0334]
-
δ1=[0.0292×0.2281≈0.00670.0334×0.2055≈0.0069]\delta_1 = \begin{bmatrix} 0.0292×0.2281 ≈ 0.0067 \\ 0.0334×0.2055 ≈ 0.0069 \end{bmatrix}δ1=[0.0292×0.2281≈0.00670.0334×0.2055≈0.0069]
-
-
计算隐藏层参数梯度:
-
∂L∂W1=δ1⋅xT≈[0.0067×10.0069×1]=[0.00670.0069]\frac{\partial L}{\partial W_1} = \delta_1 \cdot x^T ≈ \begin{bmatrix} 0.0067×1 \\ 0.0069×1 \end{bmatrix} = \begin{bmatrix} 0.0067 \\ 0.0069 \end{bmatrix}∂W1∂L=δ1⋅xT≈[0.0067×10.0069×1]=[0.00670.0069] (因 xxx 为1维,结果维度与 W1W_1W1 一致)
-
∂L∂b1=δ1≈[0.00670.0069]\frac{\partial L}{\partial b_1} = \delta_1 ≈ \begin{bmatrix} 0.0067 \\ 0.0069 \end{bmatrix}∂b1∂L=δ1≈[0.00670.0069]
-
4. 第三步:参数更新(学习率 η=0.1\eta=0.1η=0.1 )
-
W2new=W2−η⋅∂L∂W2≈[0.7−0.1×0.02690.8−0.1×0.0296]≈[0.69730.7970]W_2^{new} = W_2 - \eta \cdot \frac{\partial L}{\partial W_2} ≈ \begin{bmatrix} 0.7 - 0.1×0.0269 & 0.8 - 0.1×0.0296 \end{bmatrix} ≈ \begin{bmatrix} 0.6973 & 0.7970 \end{bmatrix}W2new=W2−η⋅∂W2∂L≈[0.7−0.1×0.02690.8−0.1×0.0296]≈[0.69730.7970]
-
b2new=0.9−0.1×0.0417≈0.8958b_2^{new} = 0.9 - 0.1×0.0417 ≈ 0.8958b2new=0.9−0.1×0.0417≈0.8958
-
W1new=W1−η⋅∂L∂W1≈[0.1−0.1×0.00670.2−0.1×0.00670.3−0.1×0.00690.4−0.1×0.0069]≈[0.09930.19930.29930.3993]W_1^{new} = W_1 - \eta \cdot \frac{\partial L}{\partial W_1} ≈ \begin{bmatrix} 0.1 - 0.1×0.0067 & 0.2 - 0.1×0.0067 \\ 0.3 - 0.1×0.0069 & 0.4 - 0.1×0.0069 \end{bmatrix} ≈ \begin{bmatrix} 0.0993 & 0.1993 \\ 0.2993 & 0.3993 \end{bmatrix}W1new=W1−η⋅∂W1∂L≈[0.1−0.1×0.00670.3−0.1×0.00690.2−0.1×0.00670.4−0.1×0.0069]≈[0.09930.29930.19930.3993]
-
b1new=[0.5−0.1×0.00670.6−0.1×0.0069]≈[0.49930.5993]b_1^{new} = \begin{bmatrix} 0.5 - 0.1×0.0067 \\ 0.6 - 0.1×0.0069 \end{bmatrix} ≈ \begin{bmatrix} 0.4993 \\ 0.5993 \end{bmatrix}b1new=[0.5−0.1×0.00670.6−0.1×0.0069]≈[0.49930.5993]
四、PyTorch框架下的反向传播实现(对应视频实战)
1. 核心逻辑
PyTorch通过“动态计算图”自动实现反向传播,无需手动计算梯度,只需定义网络结构、损失函数,调用loss.backward()即可自动求导。
2. 代码示例(对应案例网络)
import torch
import torch.nn as nn
import torch.optim as optim
# 1. 定义网络结构(单隐藏层)
class SimpleNN(nn.Module):
def __init__(self):
super(SimpleNN, self).__init__()
self.hidden = nn.Linear(1, 2) # 输入1维→隐藏层2维(W1, b1)
self.output = nn.Linear(2, 1) # 隐藏层2维→输出1维(W2, b2)
self.sigmoid = nn.Sigmoid() # Sigmoid激活函数
def forward(self, x):
# 前向传播:x → 隐藏层 → Sigmoid → 输出层 → Sigmoid
x = self.hidden(x)
x = self.sigmoid(x)
x = self.output(x)
x = self.sigmoid(x)
return x
# 2. 初始化模型、损失函数、优化器
model = SimpleNN()
# 手动设置初始参数(与案例一致)
model.hidden.weight.data = torch.tensor([[0.1, 0.3], [0.2, 0.4]]).T # PyTorch中Linear权重维度为(输出维,输入维)
model.hidden.bias.data = torch.tensor([0.5, 0.6])
model.output.weight.data = torch.tensor([[0.7, 0.8]])
model.output.bias.data = torch.tensor([0.9])
criterion = nn.MSELoss() # 均方误差损失
optimizer = optim.SGD(model.parameters(), lr=0.1) # SGD优化器,学习率0.1
# 3. 前向传播
x = torch.tensor([[1.0]]) # 输入(批量维度,1个样本)
y_true = torch.tensor([[0.5]]) # 真实标签
y_pred = model(x) # 预测值
loss = criterion(y_pred, y_true) # 计算损失
# 4. 反向传播与参数更新
optimizer.zero_grad() # 清空之前的梯度(避免累积)
loss.backward() # 自动计算所有参数的梯度(对应手动计算的梯度)
optimizer.step() # 根据梯度更新参数(对应手动参数更新)
# 5. 打印结果
print("预测值:", y_pred.item())
print("损失值:", loss.item())
print("更新后输出层权重:", model.output.weight.data)
3. 框架优势对比
-
手动计算:需逐层推导梯度公式,易出错,仅适用于简单网络。
-
PyTorch自动求导:无需关注梯度计算细节,支持复杂网络(如卷积神经网络),且梯度计算高效、准确。
五、常见问题与注意事项
-
梯度消失/爆炸:
-
原因:激活函数(如Sigmoid)在输入值过大/过小时导数接近0,导致梯度传递到浅层时趋近于0(梯度消失);或网络参数初始值过大,导致梯度逐层放大(梯度爆炸)。
-
解决方法:使用ReLU等梯度不易消失的激活函数、采用 Xavier/He 等参数初始化方法、使用批量归一化(Batch Normalization)。
-
-
梯度累积:PyTorch中若未调用
optimizer.zero_grad(),梯度会累积到上一次的梯度值上,导致参数更新错误,需每次反向传播前清空梯度。 -
学习率选择:学习率过大会导致参数震荡不收敛,过小则参数更新缓慢,需根据任务调整(如初始用0.1,后续逐步减小)。
2333

被折叠的 条评论
为什么被折叠?



