共计 2328 个字符,预计需要花费 6 分钟才能阅读完成。
BP 算法的核心地位
反向传播(Backpropagation,BP)是深度学习模型训练的基石算法。它通过高效计算梯度,使得多层神经网络的参数优化成为可能。没有 BP 算法,现代深度学习的爆发式发展将无从谈起。

数学原理推导
前向传播的矩阵表示
对于一个 L 层全连接网络,第 l 层的输出可表示为:
$$
\mathbf{h}^{(l)} = f(\mathbf{z}^{(l)}) = f(\mathbf{W}^{(l)}\mathbf{h}^{(l-1)} + \mathbf{b}^{(l)})
$$
其中 $\mathbf{W}^{(l)}$ 是权重矩阵,$\mathbf{b}^{(l)}$ 是偏置向量,$f$ 是激活函数。
损失函数的偏导推导
以均方误差损失为例,对权重 $W_{ij}^{(l)}$ 的偏导计算过程:
-
计算输出层误差:
$$
\delta^{(L)} = \frac{\partial L}{\partial \mathbf{z}^{(L)}} = (\mathbf{h}^{(L)} – \mathbf{y}) \odot f'(\mathbf{z}^{(L)})
$$ -
反向传播误差(链式法则):
$$
\delta^{(l)} = ((\mathbf{W}^{(l+1)})^T \delta^{(l+1)}) \odot f'(\mathbf{z}^{(l)})
$$ -
计算权重梯度:
$$
\frac{\partial L}{\partial W_{ij}^{(l)}} = h_j^{(l-1)}\delta_i^{(l)}
$$
激活函数导数的作用
常用激活函数导数示例:
- Sigmoid: $\sigma'(z) = \sigma(z)(1-\sigma(z))$
- ReLU: $\text{ReLU}'(z) = \begin{cases} 1 & \text{if} z > 0 \ 0 & \text{otherwise} \end{cases}$
Python 实现
import numpy as np
class ThreeLayerNet:
def __init__(self, input_size, hidden_size, output_size):
# He 初始化
self.W1 = np.random.randn(input_size, hidden_size) * np.sqrt(2/input_size)
self.b1 = np.zeros(hidden_size)
self.W2 = np.random.randn(hidden_size, output_size) * np.sqrt(2/hidden_size)
self.b2 = np.zeros(output_size)
def forward(self, x):
self.z1 = np.dot(x, self.W1) + self.b1
self.h1 = np.maximum(0, self.z1) # ReLU
self.z2 = np.dot(self.h1, self.W2) + self.b2
self.h2 = 1/(1+np.exp(-self.z2)) # Sigmoid
return self.h2
def backward(self, x, y, lr=0.01):
# 输出层误差
d_z2 = (self.h2 - y) * self.h2 * (1 - self.h2) # 含 Sigmoid 导数
# 隐藏层误差
d_h1 = np.dot(d_z2, self.W2.T)
d_z1 = d_h1 * (self.z1 > 0) # ReLU 导数
# 更新参数
self.W2 -= lr * np.dot(self.h1.T, d_z2)
self.b2 -= lr * np.sum(d_z2, axis=0)
self.W1 -= lr * np.dot(x.T, d_z1)
self.b1 -= lr * np.sum(d_z1, axis=0)
工程实践
优化器比较
# SGD with Momentum
v_W = 0
beta = 0.9
v_W = beta * v_W + (1-beta) * dW
W = W - lr * v_W
# Adam 实现
m_W = 0
v_W = 0
beta1 = 0.9
beta2 = 0.999
eps = 1e-8
m_W = beta1*m_W + (1-beta1)*dW
v_W = beta2*v_W + (1-beta2)*(dW**2)
m_hat = m_W/(1-beta1**t)
v_hat = v_W/(1-beta2**t)
W = W - lr*m_hat/(np.sqrt(v_hat)+eps)
梯度裁剪
grad_norm = np.sqrt(sum(np.sum(g**2) for g in grads))
max_norm = 5.0
if grad_norm > max_norm:
ratio = max_norm / grad_norm
grads = [g*ratio for g in grads]
学习率衰减
initial_lr = 0.1
decay_rate = 0.95
epoch = 100
lr = initial_lr * (decay_rate ** epoch)
避坑指南
- 权重初始化 :
- 使用 Xavier/Glorot 初始化(Sigmoid)
-
使用 He 初始化(ReLU)
-
激活函数选择 :
- 隐藏层优先使用 ReLU/LeakyReLU
-
输出层根据任务选择(Sigmoid 二分类,Softmax 多分类)
-
批量归一化 :
# 在激活函数前插入 batch_mean = np.mean(z, axis=0) batch_var = np.var(z, axis=0) z_hat = (z - batch_mean) / np.sqrt(batch_var + eps) out = gamma * z_hat + beta
思考问题
- 当网络层数很深时,除了 ReLU 还有哪些方法可以缓解梯度消失问题?
- 为什么 Adam 优化器在实际应用中通常比 SGD 表现更好?背后的数学原理是什么?
- 在移动端部署模型时,如何在不显著影响精度的情况下简化 BP 计算过程?
