共计 1857 个字符,预计需要花费 5 分钟才能阅读完成。
为什么说 BP 算法是深度学习的基石?
BP 算法是神经网络训练的引擎,通过误差反向传播调整权重;它解决了多层网络参数优化的核心难题;现代深度学习框架(如 PyTorch/TensorFlow)的自动微分机制本质仍是 BP 思想的延伸。

数学原理拆解
链式法则:误差传播的放大器
想象瀑布的多级落差,每层神经元误差信号如同水流:
$$\frac{\partial E}{\partial w_{ij}} = \frac{\partial E}{\partial o_j} \cdot \frac{\partial o_j}{\partial net_j} \cdot \frac{\partial net_j}{\partial w_{ij}}$$
其中 $net_j$ 是加权输入,$o_j$ 是激活输出,$E$ 是损失函数。
梯度下降的矩阵之美
对于全连接层,权重更新可向量化表示为:
$$W_{new} = W – \eta \cdot \frac{1}{m} (\delta^{l+1} \cdot (a^l)^T)$$
其中 $\eta$ 是学习率,$m$ 是样本数,$\delta$ 是误差项,$a$ 是激活值。
激活函数导数对比
- Sigmoid:$\sigma'(x) = \sigma(x)(1-\sigma(x))$(易梯度消失)
- tanh:$1 – \tanh^2(x)$(梯度略大于 Sigmoid)
- ReLU:$\text{max}(0,x)$ 的导数为阶跃函数(缓解梯度消失但可能神经元死亡)
Python 实现(NumPy 版)
import numpy as np
class ThreeLayerBP:
def __init__(self, input_size, hidden_size, output_size):
self.W1 = np.random.randn(input_size, hidden_size) * 0.01
self.b1 = np.zeros(hidden_size)
self.W2 = np.random.randn(hidden_size, output_size) * 0.01
self.b2 = np.zeros(output_size)
def sigmoid(self, x):
return 1 / (1 + np.exp(-x))
def forward(self, X):
self.z1 = np.dot(X, self.W1) + self.b1 # 隐藏层加权输入
self.a1 = self.sigmoid(self.z1) # 激活输出
self.z2 = np.dot(self.a1, self.W2) + self.b2
return self.sigmoid(self.z2)
def backward(self, X, y, lr=0.1):
m = X.shape[0]
# 输出层误差
delta2 = (self.a2 - y) * self.a2 * (1 - self.a2) # ∂E/∂z2
# 隐藏层误差(关键反向传播步骤)delta1 = np.dot(delta2, self.W2.T) * self.a1 * (1 - self.a1)
# 参数更新(注意矩阵转置顺序)self.W2 -= lr * np.dot(self.a1.T, delta2) / m
self.b2 -= lr * np.mean(delta2, axis=0)
self.W1 -= lr * np.dot(X.T, delta1) / m
self.b1 -= lr * np.mean(delta1, axis=0)
五大避坑实践
梯度裁剪:防止梯度爆炸
grad_norm = np.linalg.norm(gradients)
if grad_norm > threshold:
gradients = gradients * threshold / grad_norm
Batch Normalization 集成
推荐在隐藏层后添加:
from torch.nn import BatchNorm1d # 即使使用 NumPy 也可参考此逻辑
bn = BatchNorm1d(hidden_size)
normalized = bn(torch.from_numpy(a1)).numpy()
学习率衰减策略
initial_lr = 0.1
for epoch in range(epochs):
lr = initial_lr * (0.95 ** epoch) # 指数衰减
model.backward(X_batch, y_batch, lr)
思考题
- 如何用 PyTorch 的
autograd重构权重更新逻辑?提示:requires_grad=True和optimizer.step() - 对比发现:当使用 Adam 优化器时,初始学习率设为多少时效果优于 SGD?为什么?
正文完
