共计 2213 个字符,预计需要花费 6 分钟才能阅读完成。
背景介绍
1986 年,David Rumelhart 等人在《自然》杂志发表的论文《Learning representations by back-propagating errors》首次系统阐述了反向传播算法(Backpropagation,简称 BP 算法),这一成果被认为是神经网络研究的复兴起点。BP 算法通过链式法则实现了误差的逆向传播,使得多层神经网络的训练成为可能,为现代深度学习奠定了基础。

核心原理
BP 算法的核心分为三个关键步骤:
-
前向传播 :输入数据通过各层权重和激活函数逐层计算,最终得到预测输出。用公式表示为:
$$\mathbf{h}l = \sigma(\mathbf{W}_l \mathbf{h}_l)$$
其中 $\sigma$ 为激活函数,$\mathbf{W}_l$ 和 $\mathbf{b}_l$ 分别是第 $l$ 层的权重和偏置。} + \mathbf{b -
损失计算 :比较预测输出与真实标签的差异。对于分类问题常用交叉熵损失:
$$L = -\sum y_i \log(\hat{y}_i)$$ -
反向传播 :从输出层开始,逐层计算损失对参数的梯度并更新权重。梯度计算遵循链式法则:
$$\frac{\partial L}{\partial \mathbf{W}l} = \frac{\partial L}{\partial \mathbf{h}_l} \odot \sigma'(\mathbf{z}_l) \mathbf{h}^T$$
代码实现
以下是使用 NumPy 实现的完整 BP 算法示例:
import numpy as np
class NeuralNetwork:
def __init__(self, layer_sizes):
# He 初始化权重
self.weights = [np.random.randn(y, x) * np.sqrt(2./x)
for x, y in zip(layer_sizes[:-1], layer_sizes[1:])]
self.biases = [np.zeros((y, 1)) for y in layer_sizes[1:]]
def forward(self, x):
a = x
for w, b in zip(self.weights, self.biases):
z = np.dot(w, a) + b
a = self.relu(z) # 使用 ReLU 激活函数
return a
def backward(self, x, y, learning_rate=0.01):
# 前向传播并保存中间结果
activations = [x]
zs = []
a = x
for w, b in zip(self.weights, self.biases):
z = np.dot(w, a) + b
zs.append(z)
a = self.relu(z)
activations.append(a)
# 反向传播
delta = (activations[-1] - y) * self.relu_derivative(zs[-1])
nabla_w = [np.zeros_like(w) for w in self.weights]
nabla_b = [np.zeros_like(b) for b in self.biases]
nabla_w[-1] = np.dot(delta, activations[-2].T)
nabla_b[-1] = delta
for l in range(2, len(self.weights)+1):
z = zs[-l]
delta = np.dot(self.weights[-l+1].T, delta) * self.relu_derivative(z)
nabla_w[-l] = np.dot(delta, activations[-l-1].T)
nabla_b[-l] = delta
# 参数更新
self.weights = [w - learning_rate*nw for w, nw in zip(self.weights, nabla_w)]
self.biases = [b - learning_rate*nb for b, nb in zip(self.biases, nabla_b)]
实战技巧
参数初始化方法
- Xavier 初始化 :适用于 Sigmoid/tanh 激活函数,缩放因子为 $1/\sqrt{n_{in}}$
- He 初始化 :更适合 ReLU 家族,缩放因子为 $\sqrt{2/n_{in}}$
激活函数选择
- Sigmoid:容易导致梯度消失,不推荐用于深层网络
- ReLU:计算简单且缓解梯度消失,是现代网络的首选
学习率调整
- 指数衰减 :$\eta_t = \eta_0 \cdot e^{-kt}$
- 周期调整 :如 CosineAnnealing
避坑指南
- 梯度消失问题 :
- 症状:深层网络前期层梯度接近 0
-
解决方案:使用 ReLU 激活、残差连接、批归一化
-
过拟合预防 :
- 添加 L2 正则化项
- 使用 Dropout 层(随机失活)
-
早停法(Early Stopping)
-
训练不收敛调试 :
- 检查梯度数值(应处于 1e- 3 到 1e- 1 范围)
- 可视化损失曲线(理想情况应平滑下降)
- 尝试更小的学习率
延伸思考
BP 算法虽然经典,但现代深度学习已发展出诸多改进:
1. 优化算法演进 :从 SGD 到 Adam/Adagrad 等自适应方法
2. 计算图优化 :自动微分框架(如 PyTorch/TensorFlow)的实现
3. 二阶优化 :利用 Hessian 矩阵信息的优化方法
通过理解 BP 算法这一基础,我们不仅能掌握神经网络的核心训练机制,更能为学习现代深度学习框架打下坚实基础。建议读者在实践中多尝试不同的网络结构和超参数组合,直观感受算法行为。
