池化层
介绍最大池化与平均池化,在不增加参数的前提下减少特征图尺寸。
为什么 CNN 还需要降低特征图尺寸
卷积层在数学上对 输出分辨率 几乎没做什么—— 默认 stride 为 1、padding 选合适值时,特征图的高与宽 不会随层数增加而变小 。 于是经过几层卷积之后,特征图通常还是和输入差不多大: 一张 224×224 的图,跑过 4 层卷积后还是 224×224,只是通道数从 3 涨到了几十。
但 CNN 的 末端 常常会接一个全连接层用于分类。 如果特征图保持 224×224、通道 64,展平后就是约 320 万维输入—— 一接全连接层,参数量又奔着千万级去了。 所以我们需要一种 简单、不引入更多参数 的方式, 在网络中段把特征图的空间分辨率适度降下来——这就是 池化 (pooling)的作用。
池化:滑动窗口里的"聚合"
池化的运算形式与卷积非常像——同样是 用一个窗口在特征图上滑动 —— 但每次"停下来"做的不是加权求和,而是更简单的 聚合 操作:
上面两个公式延续了《卷积运算》里的索引风格,描述的是窗口在输入图上"逐格"落下的基本聚合方式; 要真正 把分辨率降下来 ,还得让窗口"跳着滑"——这就是 步长 stride , 含义和《卷积运算》里完全一致:步长 表示窗口每往输出图前进一格, 在输入图上要跨过 列(或 行)。
池化与卷积最大的不同: 池化层没有可学习参数 —— 它只有两个超参数: 窗口大小 和 步长 。 通常二者相等(如 2×2 窗口配 stride 2),让相邻窗口"严丝合缝"不重叠。
输入尺寸怎么变?
池化层的输出尺寸与卷积同形,只是没有 padding 的 + 2p 项(默认不补边):
以经典 CNN(LeNet、VGG 等)中常见的 为例, 每过一次池化就把宽高 各减半 :
- 28 × 28 → 14 × 14
- 224 × 224 → 112 × 112
- 32 × 32 → 16 × 16
当然 并不是唯一选择—— AlexNet、ResNet 等模型常用 3×3 窗口配 stride 2 的 重叠池化 , 现代网络也有用 stride 卷积替代池化的做法(本节末尾再讨论)。 本节为了便于手算与对照,统一以 为例。
通道数不变 ,每个通道独立做池化—— 因为池化只关心空间维度上的聚合。
下面用 PyTorch 在同一张 4×4 特征图上分别跑 max / avg 池化, 与上面交互演示的手算结果对照:
池化层带来了什么
考虑最大池化:窗口里的最大值在窗口内 挪一两个像素 ,结果仍然是同一个最大值—— 即 窗口内的小幅平移不会改变输出 。
这种"鲁棒性"虽然只覆盖一个窗口大小的尺度(如 2 像素), 但多层堆叠后能积累到一定程度,部分缓解上一章提到的 MLP 位置敏感问题。
讨论:池化 vs. stride 卷积
细心的同学可能会发现: 卷积层把 stride 设为 2,同样能让分辨率减半 —— 那池化层是不是有点多余?
这两种降采样方式在现代 CNN 中确实是 共存的 ,但各有取舍:
简单结论:两种方式都是 有效的降采样手段 。 本章主线沿用经典 CNN 的范式以"卷积 + 池化"为主,看到 stride 卷积时知道它是池化的替代方案即可。