共计 1108 个字符,预计需要花费 3 分钟才能阅读完成。
背景痛点
新手在首次实现 MNIST 分类时常遇到以下问题:

- 张量形状错误:全连接网络要求输入展平为 1D 向量(如 784 维),而 CNN 需要保持 2D 结构(28×28)。未正确转换维度会导致运行时错误
- 梯度消失:bp 神经网络使用 Sigmoid 激活函数时,深层网络容易出现梯度指数级衰减
- 过拟合:模型在训练集准确率达 99% 但测试集只有 85%,常见于参数过多的全连接网络
技术对比
| 指标 | BP 神经网络 | CNN |
|---|---|---|
| 测试准确率 | 92.3% | 98.7% |
| 训练时间 /epoch | 45s | 68s |
| 参数量 | 101,770 | 8,330 |
代码实现
数据预处理
# 必须进行的归一化:将像素值从 [0,255] 缩放到 [0,1] 区间
# 均值标准差归一化可加速收敛(MNIST 常用 mean=0.1307, std=0.3081)transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
BP 神经网络关键维度转换
class Net(nn.Module):
def forward(self, x):
x = x.view(-1, 784) # 必须将图像展平为向量
x = torch.sigmoid(self.fc1(x))
return F.log_softmax(x, dim=1) # dim= 1 指对每行做 softmax
CNN 特征提取层设计
self.conv1 = nn.Conv2d(1, 10, kernel_size=5) # 输入通道 1,输出通道 10
# 池化层减少空间维度
self.pool = nn.MaxPool2d(2, stride=2) # 28x28 → 14x14 → 7x7
实验分析
训练曲线对比
- BP 网络需要约 15 个 epoch 达到 90% 准确率
- CNN 在 5 个 epoch 后稳定在 97% 以上
混淆矩阵发现
CNN 对易混淆数字的区分能力显著提升:
– 5 与 6 的误判率从 12.3% 降至 3.1%
– 7 与 1 的误判率从 8.7% 降至 1.5%
避坑指南
- Batch Size 选择:
- 太小(如 16)导致训练不稳定
- 太大(如 1024)显存不足
-
推荐值:32-256
-
ReLU 死亡神经元:
- 现象:某些神经元输出恒为 0
-
解决:使用 LeakyReLU 或调小学习率
-
验证集使用:
- 每 epoch 结束后在验证集测试
- 早停机制防止过拟合
延伸思考
- 数据增强:
- 随机旋转(±15 度)
-
轻微弹性变形
-
正则化方法:
- 在全连接层后添加 Dropout(p=0.5)
-
使用 L2 权重衰减
-
模型结构优化:
- 在 CNN 中引入残差连接
- 尝试 Batch Normalization 层
通过本实验可以直观感受到:虽然 CNN 实现稍复杂,但其参数效率和学习能力显著优于传统全连接网络。建议新手先从 BP 网络理解基础概念,再过渡到 CNN 实践。
正文完
