共计 2072 个字符,预计需要花费 6 分钟才能阅读完成。
BP 算法是深度学习模型训练的基石,它通过误差反向传播实现参数的自动优化。理解反向传播过程能帮助我们诊断梯度消失 / 爆炸等常见问题,是模型调试的核心能力。本文将从数学原理到代码实现,带你完整走一遍误差反向传播的流程。

数学原理
-
链式法则的应用 :反向传播的核心是链式法则。对于损失函数 $L$ 和权重 $w_{ij}^{(l)}$,梯度计算公式为:
$$\frac{\partial L}{\partial w_{ij}^{(l)}} = \frac{\partial L}{\partial z_j^{(l+1)}} \cdot \frac{\partial z_j^{(l+1)}}{\partial w_{ij}^{(l)}} = \delta_j^{(l+1)} \cdot a_i^{(l)}$$
其中 $\delta_j^{(l+1)}$ 是第 $l+1$ 层第 $j$ 个神经元的误差项。 -
误差反向传播示意图 :
- 输入层 → 隐藏层 → 输出层(前向传播)
- 输出层误差 $\delta^{(L)}$ = 损失函数梯度 $\nabla_a L$ ⊙ 激活函数导数 $\sigma'(z^{(L)})$
- 隐藏层误差 $\delta^{(l)} = (W^{(l+1)T} \delta^{(l+1)}) ⊙ \sigma'(z^{(l)})$
-
参数更新:$W^{(l)} ← W^{(l)} – \eta \cdot \delta^{(l)} a^{(l-1)T}$
-
激活函数对比 :
- Sigmoid:梯度 $\sigma'(z) = \sigma(z)(1-\sigma(z))$,最大值仅 0.25,易导致梯度消失
- ReLU:梯度为 0 或 1,缓解梯度消失但可能造成神经元死亡
Python 实现
import numpy as np
class NeuralNetwork:
def __init__(self, layers):
self.weights = [np.random.randn(y, x)*0.1
for x, y in zip(layers[:-1], layers[1:])]
def forward(self, x):
"""前向传播"""
self.activations = [x]
self.zs = []
for w in self.weights:
z = np.dot(w, self.activations[-1])
self.zs.append(z)
self.activations.append(self.sigmoid(z))
return self.activations[-1]
def backward(self, x, y, learning_rate=0.1):
"""反向传播"""
# 输出层误差
delta = (self.activations[-1] - y) * self.sigmoid_derivative(self.zs[-1])
# 反向传播误差
gradients = []
for l in range(len(self.weights)-1, -1, -1):
gradients.append(np.dot(delta, self.activations[l].T))
if l > 0:
delta = np.dot(self.weights[l].T, delta) * self.sigmoid_derivative(self.zs[l-1])
# 更新参数
for l in range(len(self.weights)):
self.weights[l] -= learning_rate * gradients[::-1][l]
# 打印梯度
print(f"梯度范数: {[np.linalg.norm(g) for g in gradients[::-1]]}")
def sigmoid(self, z):
return 1/(1+np.exp(-z))
def sigmoid_derivative(self, z):
s = self.sigmoid(z)
return s*(1-s)
工程实践
- 梯度问题解决 :
- 梯度消失:使用 ReLU、LeakyReLU 等激活函数,配合 BatchNorm
-
梯度爆炸:梯度裁剪(
np.clip(grad, -1, 1))、权重正则化 -
Xavier 初始化 :
# 对于 tanh 激活函数 scale = np.sqrt(1./layers[l-1]) self.weights = [np.random.randn(y, x)*scale for x, y in zip(layers[:-1], layers[1:])]数学原理:保持各层输入输出的方差一致
-
L2 正则化影响 :
- 反向传播时增加权重衰减项:$\frac{\partial L}{\partial w} += \lambda w$
- 实现代码:
gradients[l] += lambd * self.weights[l]
思考题
- 如何验证反向传播实现的正确性?
-
答:使用数值梯度检验(gradient checking),比较解析梯度和数值梯度的差异
-
批量归一化如何改变梯度传播路径?
-
答:BN 层引入两个可学习参数 $\gamma$ 和 $\beta$,梯度需通过这两个参数传播
-
二阶优化算法需要怎样的梯度信息?
- 答:需要 Hessian 矩阵或其近似,如 Adam 使用梯度的一阶矩和二阶矩估计
