共计 1902 个字符,预计需要花费 5 分钟才能阅读完成。
1. 反向传播的数学原理
反向传播(Backpropagation)的核心是链式法则。假设有一个三层的神经网络,其前向传播过程可以表示为:

$$
\begin{aligned}
z^{[1]} &= W^{[1]}x + b^{[1]} \
a^{[1]} &= \sigma(z^{[1]}) \
z^{[2]} &= W^{[2]}a^{[1]} + b^{[2]} \
a^{[2]} &= \sigma(z^{[2]})
\end{aligned}
$$
反向传播时,我们需要计算损失函数 $L$ 对各个参数的梯度。以 $W^{[2]}$ 为例:
$$
\frac{\partial L}{\partial W^{[2]}} = \frac{\partial L}{\partial a^{[2]}} \cdot \frac{\partial a^{[2]}}{\partial z^{[2]}} \cdot \frac{\partial z^{[2]}}{\partial W^{[2]}}
$$
这就是链式法则的具体应用。
2. 梯度消失问题与解决方案
梯度消失常发生在深层网络中使用 sigmoid/tanh 激活函数时。因为:
- sigmoid 导数最大值为 0.25
- 多层连乘后梯度指数级减小
解决方案:
- 使用 ReLU 激活函数:$f(x)=max(0,x)$
- 残差连接(ResNet)
- 批量归一化(BatchNorm)
3. Python 实现核心代码
网络层基类
class Layer:
def __init__(self):
self.params = {}
def forward(self, x):
raise NotImplementedError
def backward(self, grad):
raise NotImplementedError
全连接层实现
class Dense(Layer):
def __init__(self, input_dim, output_dim):
super().__init__()
# Xavier 初始化
self.params['W'] = np.random.randn(input_dim, output_dim) * np.sqrt(2./input_dim)
self.params['b'] = np.zeros((1, output_dim))
def forward(self, x):
self.x = x # 保存输入用于反向传播
return x @ self.params['W'] + self.params['b']
def backward(self, grad):
# 计算本层梯度
dW = self.x.T @ grad
db = np.sum(grad, axis=0, keepdims=True)
# 返回传给前一层的梯度
return grad @ self.params['W'].T, dW, db
4. 训练过程可视化
使用 Matplotlib 绘制训练曲线:
plt.figure(figsize=(12,4))
plt.subplot(1,2,1)
plt.plot(losses, label='训练损失')
plt.xlabel('迭代次数')
plt.ylabel('损失值')
plt.subplot(1,2,2)
plt.plot(accuracies, label='测试准确率')
plt.xlabel('迭代次数')
plt.ylabel('准确率')
plt.show()
5. 关键优化技巧
学习率调整策略
- 线性预热:前 1000 步从 0 线性增加到目标学习率
- 余弦退火:$\eta_t = \eta_{min} + \frac{1}{2}(\eta_{max}-\eta_{min})(1+cos(\frac{t}{T}\pi))$
梯度裁剪实现
def clip_grads(grads, max_norm):
total_norm = 0
for grad in grads:
total_norm += np.sum(grad**2)
total_norm = np.sqrt(total_norm)
clip_coef = max_norm / (total_norm + 1e-6)
if clip_coef < 1:
for grad in grads:
grad *= clip_coef
6. 实践经验总结
- 输入数据归一化到 [0,1] 或标准正态分布
- 参数初始化推荐:
- ReLU 网络使用 He 初始化
- Tanh 网络使用 Xavier 初始化
- 调试时可以先在小数据集上过拟合
7. 扩展思考
- Adam 优化器在 SGD 基础上增加了:
- 动量项(一阶矩估计)
- 自适应学习率(二阶矩估计)
- 不同优化器对比:
- SGD 收敛慢但最终精度可能更高
- Adam 收敛快但可能陷入局部最优
完整的实现代码已上传到 GitHub 仓库,包含更多细节和注释。建议读者尝试修改网络结构、调整超参数来观察训练效果的变化。
正文完
