卷积神经网络的结构
把卷积层、池化层、全连接层组合为完整的 CNN,并理解感受野与特征层次。
把三种层组装起来
到上一节为止,CNN 的三种主要层都已经介绍完毕:
- 卷积层 :用可学习的卷积核提取局部特征,参数共享;
- 池化层 :降采样、提供有限的平移鲁棒性,无参数;
- 全连接层 :MLP 章节熟悉的层,负责把特征映射到分类输出。
本节把它们组装成一个 完整的卷积神经网络 , 并由此引出两个新的关键概念—— 感受野 与 特征层次 。
CNN 的标准组成
典型的卷积神经网络遵循这样一个范式:
这个结构可以分成 两段 来理解:
形状演算:跟着 LeNet 走一遍
用上一节的输出尺寸公式,把 LeNet 风格结构在 28×28 MNIST 输入下逐层的张量形状手算一遍。 LeNet 是 1998 年由 Yann LeCun 提出的早期 CNN,用于处理本章的 MNIST 手写数字识别任务。
每一行 Conv 都是 (padding = 0 时); 每一行 Pool 都是 。 建议你拿张纸自己重新算一遍 24、12、8、4 这几个数字—— 把上一节的输出尺寸公式在实战前先用一次。
下图把上表中每一层的 输出张量形状 按等比例可视化。 Conv / Pool 阶段的输出形状为 , 用一组堆叠的方块表示:单个方块边长正比于空间尺寸 , 堆叠的方块数等于通道数 ; Flatten 及之后的全连接层输出为一维向量,用一根竖条表示,长度正比于向量维数。 每个方块或竖条 下方 标注该张量的具体形状; 产生该张量的层名标注在 指向它的箭头上方 , 输入张量没有前置层,因此在其上方直接标注"输入"; 颜色仅用于区分层的类型。当一行排不下时图示会换至下一行继续。
感受野:深层元素与输入像素的依赖范围
关键点:
- 感受野的 主体 是 深层特征图上的某个元素 ,而不是整张特征图;
- 感受野的 对照对象 始终是 原始输入图像 ,而不是中间层的特征图;
- 由于卷积、池化都是基于局部窗口的运算,感受野必然是输入图像上的一个连续矩形区域。
逐层推导:多个卷积层串联时的感受野
这里讨论的"多层卷积",指的是 多个卷积层首尾相接、前一层的输出作为后一层的输入 , 而不是把卷积运算重复施加在同一张图上。 考虑 个 卷积层串联, 每层都用 stride = 1、padding = 0:
- :第 1 层每个输出元素由输入图像的一个 邻域计算得到,感受野为 。
- :第 2 层某个输出元素由第 1 层的 个相邻元素计算; 这 9 个第 1 层元素各自来自输入图像上 的邻域, 相邻邻域之间在水平 / 垂直方向均错开 1 个像素,取并集恰好是输入上的一个 矩形——感受野 。
- :按同样方式继续展开,感受野 。
交互演示:点选深层元素,查看它在输入上的感受野
下图是 层 卷积串联的结构: 左边是 输入,中间是第 1 层 输出, 右边是第 2 层 输出。第 2 层的每个格子,只由第 1 层的一个 邻域、以及输入图像上的一个 区域决定。
用法:悬浮或点击右侧第 2 层的任意格子,左侧两层会高亮出影响它取值的范围。
stride > 1 时:感受野的逐层放大
上面的逐层推导默认每一层都用 stride = 1。当网络中第 层的 stride (CNN 中最典型的是池化层), 从该层起,后续每一层在特征图上"相邻一格"所对应到输入图像上的像素距离被放大 倍,因此该层之后每一层贡献的感受野增量也按相同倍数放大。 stride 越大、所在层数越靠前,对后续层感受野的累积放大作用就越显著。
特征层次:从边缘到物体
感受野的扩张带来另一个直接结果: 不同深度的卷积层学到的特征性质不同 。 这是 CNN 一个经过大量实验观察得到的特性,并不是某条公式推出来的—— 但它对理解后续的网络设计十分关键。
和 MLP 一样的训练框架
CNN 的训练流程与 MLP 是 一致的 —— 前向、计算损失、反向传播、参数更新; DataLoader 、 optimizer 、损失函数都不变。 反向传播会自动计算每个卷积核的梯度,无需我们额外做什么。 变化的只是 模型结构 ,训练循环可以直接复用上一章 MLP 的代码骨架。