共计 1842 个字符,预计需要花费 5 分钟才能阅读完成。
神经网络的核心训练流程就像教孩子认图的过程:前向传播是让孩子看图片说答案,反向传播是根据错误调整认知,参数更新则是不断优化判断标准。掌握这个闭环,就能让模型从数据中自动学习规律。

一、数学原理图解
1. 前向传播的矩阵运算
假设输入数据 $X\in\mathbb{R}^{n\times d}$(n 个样本,d 维特征),第一层权重 $W_1\in\mathbb{R}^{d\times h}$,则隐藏层输出为:
$$H = \text{ReLU}(XW_1 + b_1)$$
其中 ReLU 函数 $\text{ReLU}(z)=\max(0,z)$ 引入非线性。
2. 反向传播的链式法则
以交叉熵损失 $L$ 对 $W_1$ 的梯度为例:
$$\frac{\partial L}{\partial W_1} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial H} \cdot \frac{\partial H}{\partial (XW_1+b_1)} \cdot \frac{\partial (XW_1+b_1)}{\partial W_1}$$
实际计算时从右向左逐层求导,就像沿着计算图的反方向传递误差。
3. 学习率与批量大小的关系
- 大批量:梯度估计更稳定,但需要更大学习率
- 小批量:每次更新方向波动大,需减小学习率
经验公式:$\text{新学习率} = \text{原学习率} \times \sqrt{\frac{\text{ 原批量}}{\text{ 新批量}}}$
二、NumPy 代码实现
import numpy as np
class ThreeLayerMLP:
def __init__(self, input_dim, hidden_dim, output_dim):
# He 初始化适应 ReLU
self.W1 = np.random.randn(input_dim, hidden_dim) * np.sqrt(2/input_dim)
self.b1 = np.zeros(hidden_dim)
self.W2 = np.random.randn(hidden_dim, output_dim) * np.sqrt(2/hidden_dim)
self.b2 = np.zeros(output_dim)
def forward(self, X):
self.z1 = X @ self.W1 + self.b1
self.h1 = np.maximum(0, self.z1) # ReLU
self.z2 = self.h1 @ self.W2 + self.b2
self.probs = np.exp(self.z2) / np.sum(np.exp(self.z2), axis=1, keepdims=True)
return self.probs
def backward(self, X, y, lr=0.01):
m = X.shape[0] # 批量大小
# 输出层梯度
dz2 = self.probs
dz2[range(m), y] -= 1
dz2 /= m
# 隐藏层梯度
dh1 = dz2 @ self.W2.T
dz1 = dh1 * (self.z1 > 0) # ReLU 导数
# 参数更新
self.W2 -= lr * self.h1.T @ dz2
self.b2 -= lr * np.sum(dz2, axis=0)
self.W1 -= lr * X.T @ dz1
self.b1 -= lr * np.sum(dz1, axis=0)
三、实战避坑指南
1. 梯度问题识别
- 梯度爆炸 :参数突然变成 NaN 或极大值
- 梯度消失 :深层网络参数几乎不更新
解决方案: - 使用梯度裁剪(
np.clip(grad, -5, 5)) - 改用残差连接
2. 参数初始化
| 激活函数 | 推荐初始化方法 |
|---|---|
| ReLU | He 初始化 |
| Tanh | Xavier/Glorot |
| Sigmoid | Xavier/Glorot |
3. 学习率调整策略
- 阶梯下降 :每 N 轮学习率减半
- 余弦退火 :$\eta_t = \eta_{min} + \frac{1}{2}(\eta_{max}-\eta_{min})(1+\cos(\frac{t}{T}\pi))$
- 热重启 :周期性重置学习率
四、扩展思考
- Dropout 实现 :在前向传播时随机屏蔽部分神经元,注意测试阶段要缩放输出
- 批量归一化位置 :通常放在全连接层后、激活函数前
- 优化器内存 :Adam 需保存每个参数的动量变量,比 SGD 多 2 倍显存
通过这次手写实现,最让我惊讶的是反向传播中矩阵求导的优雅对称性——每一层的梯度计算都像是前向传播的镜像过程。建议读者用玩具数据(如螺旋数据集)可视化训练过程,能直观看到决策边界如何逐步优化。
正文完
