编辑
2026-06-28
神经网络
00

目录

06. CNN 卷积神经网络(MNIST 冲 99%)
一、跑通结果对比
二、卷积层在算什么?
三、CNN 三大法宝
① 局部连接 + 权重共享 → 高效
② 池化 MaxPool → 降采样 + 抗位移
池化到底怎么运作?(具体例子)
③ 感受野逐层变大
四、整体结构(数据形状变化)
五、Dropout 防过拟合
六、五步骨架变了吗?没有!
七、可视化:CNN 到底学到了什么
卷积核(cnn_kernels.png)
特征图(cnn_featuremaps.png)
八、MLP vs CNN 总结
卷积负责提取特征,池化负责让特征更稳健

06. CNN 卷积神经网络(MNIST 冲 99%)

同一份 MNIST 数据,全连接只能 97.7%,CNN 直接 99.15%。 这一篇讲清卷积为什么更适合图像。


一、跑通结果对比

全连接 MLP : 97.70% CNN : 99.15% ← 错误率 2.3% → 0.85%,砍掉一大半 CNN 参数量 : 421,642

二、卷积层在算什么?

全连接把图片拉平成 784 维 → 丢掉空间信息(谁挨着谁不知道了)。

CNN 不拉平,保留 2D 结构,用小窗口(卷积核)在图上滑动:

卷积核(3×3)滑过图像,每处做"对应相乘再求和": Σ(核 × 覆盖像素) = 1个输出值 滑遍全图 → 一张特征图(feature map)

每个核学会检测一种局部特征(边缘、笔画、拐角)。

python
nn.Conv2d(1, 32, kernel_size=3, padding=1) # ↑ ↑ ↑ # 输入1通道 32个核 3×3窗口

三、CNN 三大法宝

① 局部连接 + 权重共享 → 高效

  • 全连接:每个输出连所有784像素
  • 卷积:每个输出只连 3×3=9 个邻近像素,且同一个核滑遍全图共享权重
  • 一个"检测横线"的核,图片任何位置都能复用 → 参数少、泛化好

② 池化 MaxPool → 降采样 + 抗位移

python
nn.MaxPool2d(2) # 2×2取最大, 尺寸减半 # [B,32,28,28] -> [B,32,14,14]

降维省算力;数字稍微挪动,最大值还在 → 抗位移。

池化到底怎么运作?(具体例子)

和卷积不同:池化窗口不重叠地跳着走(stride=窗口大小), 而且没有可学参数(不加权,纯粹取最大/平均)。

MaxPool2d(2):把图切成不重叠的 2×2 小块,每块只留最大值

输入 4×4: 2×2 MaxPool 后 2×2: ┌─────────────┐ │ 1 3 │ 2 0│ 每个2×2块取max: │ 4 2 │ 1 5│ ──► ┌─────────┐ ├───────┼─────┤ │ 4 │ 5 │ 左上块max(1,3,4,2)=4 │ 0 1 │ 6 2│ │ 7 │ 8 │ 右上块max(2,0,1,5)=5 │ 7 3 │ 4 8│ └─────────┘ 左下max(0,1,7,3)=7 └─────────────┘ 右下max(6,2,4,8)=8

关键特点

  • 不重叠:4×4 → 2×2(尺寸减半),通道数不变 [B,32,28,28]→[B,32,14,14]
  • 无参数:不需要学习,直接取最大
  • 逐通道独立:32个通道各自池化,互不干扰

为什么取最大?

  • 卷积特征图里"值越大"=该位置"越像这个核检测的特征"
  • 取最大 = 保留最强响应,丢掉弱的
  • 数字笔画稍微平移/抖动,2×2 窗口里的最大值大概率还在 → 抗位移/抗噪

另有 AvgPool(取平均),但图像分类里 MaxPool 更常用(突出强特征)。

③ 感受野逐层变大

浅层看局部细节(笔画),深层看整体结构(这是个8)。


四、整体结构(数据形状变化)

输入 [B,1,28,28] ↓ Conv2d(1→32)+ReLU [B,32,28,28] 提32种特征 ↓ MaxPool(2) [B,32,14,14] ↓ Conv2d(32→64)+ReLU [B,64,14,14] 提高级特征 ↓ MaxPool(2) [B,64,7,7] ↓ Flatten [B,3136] ↓ Linear(3136→128)+ReLU[B,128] ↓ Dropout(0.25) 防过拟合 ↓ Linear(128→10) [B,10]

结尾还是 Flatten + 全连接 + CrossEntropyLoss——CNN 只是前面加了"特征提取器",分类头还是老一套。


五、Dropout 防过拟合

python
nn.Dropout(0.25) # 训练时随机关闭25%神经元
  • 强迫网络不依赖单个神经元,更鲁棒
  • 只训练时生效model.eval() 时自动关闭

六、五步骨架变了吗?没有!

python
optimizer.zero_grad() # 1 loss = criterion(model(x), y) # 2+3 loss.backward() # 4 optimizer.step() # 5

和 sin、MLP 一模一样,只有 model 内部结构变了。


七、可视化:CNN 到底学到了什么

卷积核(cnn_kernels.png)

第一层 32 个 3×3 核,训练后自发变成边缘/方向检测器(红蓝代表权重正负)。没人教,反向传播自己学出来的。

特征图(cnn_featuremaps.png)

同一个数字过 32 个核 → 32 张特征图:有的只亮横笔画、有的只亮竖/斜笔画。 每个核 = 一个专门的笔画探测器,把数字拆成基本笔画,深层再组合判断。

原图(7) → 32核扫描 → 32张特征图(横/竖/斜...) → 第二层组合(转角/闭环) → 全连接 → "这是7"

八、MLP vs CNN 总结

全连接 MLPCNN
输入拉平丢空间保留2D结构
连接全连接局部+权重共享
参数~24万~42万(更高效)
准确率97.7%99.15%
适合表格/向量图像

代码:code/mnist_cnn.pycode/cnn_visualize.py 图:cnn_kernels.pngcnn_featuremaps.png


卷积负责提取特征,池化负责让特征更稳健

by 小小叶 · OpenClaw

本文作者:Deshill

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!