共计 1733 个字符,预计需要花费 5 分钟才能阅读完成。
背景
BP(Backpropagation)神经网络是深度学习的基础架构之一,因其强大的非线性拟合能力被广泛应用于分类、回归等任务。理解正向传播和反向传播的机制,不仅能帮助我们更好地调参优化模型,也是掌握更复杂神经网络结构的基石。

核心原理
1. 正向传播的数学推导
正向传播是数据从输入层流向输出层的过程,本质是复合函数的嵌套计算。以单隐层网络为例:
-
输入层到隐层 :
$$h = \sigma(W_1 x + b_1)$$
其中 $\sigma$ 为激活函数(如 Sigmoid、ReLU),$W_1$ 为权重矩阵,$b_1$ 为偏置 -
隐层到输出层 :
$$\hat{y} = \text{softmax}(W_2 h + b_2)$$
多分类任务常使用 softmax 激活函数将输出转化为概率分布
2. 反向传播的链式法则
反向传播通过梯度下降更新参数,核心是链式求导法则。定义损失函数 $L$(如交叉熵)后:
- 输出层梯度:
$$\frac{\partial L}{\partial W_2} = (\hat{y} – y) \cdot h^T$$ - 隐层梯度:
$$\frac{\partial L}{\partial W_1} = (W_2^T(\hat{y}-y) \odot \sigma'(z)) \cdot x^T$$
其中 $\odot$ 表示逐元素乘法,$\sigma’$ 为激活函数导数
优化实现
矩阵化计算实现
通过 NumPy 广播机制实现高效矩阵运算:
import numpy as np
def forward(x, W1, b1, W2, b2):
z1 = np.dot(W1, x) + b1 # 隐层加权和
h = 1 / (1 + np.exp(-z1)) # Sigmoid 激活
z2 = np.dot(W2, h) + b2
y_hat = np.exp(z2) / np.sum(np.exp(z2)) # softmax
return y_hat, h
def backward(x, y, y_hat, h, W2):
grad_z2 = y_hat - y # 输出层误差
grad_W2 = np.outer(grad_z2, h)
grad_z1 = np.dot(W2.T, grad_z2) * h * (1 - h) # Sigmoid 导数
grad_W1 = np.outer(grad_z1, x)
return grad_W1, grad_W2
梯度检查实践
通过数值梯度验证反向传播正确性:
def gradient_check(x, y, params, eps=1e-4):
for i in range(len(params)):
param_plus = params.copy()
param_minus = params.copy()
param_plus[i] += eps
param_minus[i] -= eps
numerical_grad = (loss(x,y,param_plus) - loss(x,y,param_minus))/(2*eps)
analytic_grad = compute_grad(x,y,params)[i]
assert np.allclose(numerical_grad, analytic_grad, rtol=1e-5)
避坑指南
学习率选择策略
- 初始尝试 0.001~0.1 范围
- 采用学习率衰减:$\eta_t = \eta_0 / \sqrt{t}$
- 高级优化器:Adam、RMSProp 等自适应方法
梯度消失 / 爆炸预防
- 权重初始化:Xavier/Glorot 初始化保持方差一致
$$W \sim N(0, \sqrt{2/(n_{in}+n_{out})})$$ - 梯度裁剪:限制梯度最大值
- 改用 ReLU 等非饱和激活函数
延伸思考
与自动微分的对比
现代框架(如 PyTorch/TensorFlow)通过计算图自动求导,但理解 BP 原理有助于:
– 自定义复杂层结构
– 调试梯度异常问题
– 优化内存占用(如 in-place 操作)
在 CNN/RNN 中的扩展
- CNN:局部连接和参数共享下的 BP 计算
- RNN:BPTT(时间反向传播)处理序列依赖
实践建议
建议在 MNIST 等小型数据集上手动实现完整 BP 流程,对比与框架实现的差异。这能深化对以下概念的理解:
– 计算图的构建方式
– 批量训练的内存管理
– 正则化项的实际影响
完整实现代码见 GitHub 仓库(示例链接)。遇到梯度异常时,优先检查激活函数导数的实现是否正确,这是手工实现中最常见的错误来源。
正文完
