上一章《CNN 卷积神经网络》只留下一枚 3×3 的小印章, 连一只眼睛都看不全。但堆到 20 层之后,最上面一个神经元却能看到整张图。 这背后是一次「换地图」:放大镜还是同一把,换一张更粗的地图,同样的挪动就盖住更大的地方—— 这场"从局部到全局"的交换怎么发生,就是这一章要回答的。
先认三个词:
核心大图 · 亲手堆层,看
剖面图 · 同一个神经元,对着同一条输入带,一层比一层盖得宽
如果只有一层,网络永远只能看到 3×3 的局部。
深度不是为了"更强",是为了"看得更远"。
但注意:纯粹靠堆 3×3 来扩大
下采样(池化或步长卷积)把图变小。这一步有个不直观但极其重要的后果:
后面每一层在原图上的"步长"被放大了,于是
把鼠标停在公式里的 k、d、j、s 上——有滑块的会亮起来。膨胀率 d = 核里相邻两个格子之间隔开几格;d = 1 就是普通的紧挨着(第 4 节会把它调大)。j 和 s 挂在同一个滑块上:s 是「这一层跳几格」,j 是「到这一层为止,前面所有步长乘起来」。d = 1(普通卷积)时,加号后面那一项就是 (k−1)·jin。
关键在于那个 jin:它就是「到这一层为止,前面所有步长乘起来」,会累积。
每次
互动 · 对比"只堆卷积" vs "加
像看地图。你手里永远是一把 3×3 的放大镜,但换地图的缩放层级之后,
同样一次放大镜移动,覆盖的真实距离就变了。
省城地图上的 3 厘米移动和小区地图上的 3 厘米移动,完全是两回事。
上面说了两句话:「每加一层 3×3,
动画 · 顶层那个神经元在原始输入上盖住了多大一片(每一步都当场递推)
公式 ·
把「
再把「膨胀率 d」拖大:参数量一个字都没变,感受野却变宽了(回扣第 4 节)。
感受野从来不是靠参数买来的,是靠「排列」和「少看一半像素」买来的。
| 对比项 | 最大池化 Max Pool | 平均池化 Avg Pool | 步长卷积 Stride Conv |
|---|---|---|---|
| 怎么做 | 窗口里取最大值 | 窗口里取平均 | 卷积核一次跳 2 格 |
| 有没有 | 没有 | 没有 | 有(要训练) |
| 平移不变性 | 最强——挪一格通常最大值不变 | 中等 | 较弱 |
| 信息保留 | 只留最强的那个 | 让所有值参与,更平滑 | 边 |
| 今天用得多吗 | 经典 CNN 常用 | 少了 | 现代网络(ResNet:2015 年一种很深的卷积网络,靠 |
互动 · 同一块 2×2 数字,三种
所以下采样丢掉的主要是「精确在哪」,也丢掉一部分内容(最大值池化只留一个数,另外三个直接扔)。
ResNet 之后,越来越多的网络用步长卷积替代池化:
它能在降维的同时学出"该保留什么"。
今天最常保留池化的是网络开头的 maxpool(一上来先把图快速缩小一半)
和结尾把整张特征图取平均、压成 1×1 做分类的全局平均池化。
有时候你不想把图变小(比如分割任务,输出必须和输入同尺寸),
但又需要更大的
互动 · 同一个 3×3 核,不同膨胀率
| 膨胀率 d | 核的实际覆盖 | 参数量 | 感受野 | 用在哪 |
|---|---|---|---|---|
| 1 | 3×3 | 9 | 3 | 普通卷积 |
| 2 | 5×5(但只取 9 个点) | 9 | 5 | DeepLab v3、实时分割 |
| 4 | 9×9(只取 9 个点) | 9 | 9 | 需要大视野但保持分辨率 |
| 8 | 17×17(只取 9 个点) | 9 | 17 | 语音合成(WaveNet) |
示意 · 为什么连续用同一个膨胀率会漏像素
这是二维网格效应的一维剖面。两层都用 d = 2 时,采样点落在完全相同的偶数位置上, 奇数位置永远进不了任何一层——这就是那个“棋盘格”。把膨胀率混起来用就不会漏了(Wang et al. 2018 那篇论文专门讨论过这个坑)。
那能不能用空洞卷积代替下采样?不能:图还是那么大,计算量一点没省(第 6 节那张表),连续用还会漏像素——它只解决「看得远」,不解决「算得省」。
分割(给每个像素贴标签)、生成(造一张图)这类任务,需要把特征图放大回原尺寸,
这是前面每一步
具体就这四种:最近邻、双线性、转置卷积、PixelShuffle(把通道重排成更大的图,本身不学参数)——区别只在「怎么把值铺开」,谁也找不回位置。
逐个当场算给你看,在《语义分割》那一章。
扩大感受野、或者在保持视野的前提下换算力,一共就这几条路。要挑哪条先看这张表;哪条会亏,看下一节。 参数量一列含偏置(每个输出通道 +Cout),与《MLP》《CNN》章口径一致。
| 操作 | 空间尺寸 | 通道数 | 感受野 | 参数量 |
|---|---|---|---|---|
| 3×3 卷积,stride 1 | 不变 | 可指定 | +2 | 9×Cin×Cout + Cout |
| 3×3 卷积,stride 2 | ÷2 | 可指定 | + (2×j) | 同上 |
| 2×2 最大池化 | ÷2 | 不变 | 略增 | 0 |
| 3×3 空洞卷积,d=2 | 不变 | 可指定 | +4 | 9×Cin×Cout + Cout |
| 1×1 卷积 | 不变 | 可升可降 | +0 | Cin×Cout + Cout |
| 全局平均池化 | →1×1 | 不变 | 全图 | 0 |
账本 · 分辨率减半、通道翻倍、j 翻倍(ResNet-50 的那条路线)
盒子高度 = 特征图分辨率,j = 当前一个像素对应原图多少像素。
同样一块 3×3 卷积,在最后那个盒子里贡献的
它看起来毫无意义:核只有 1 个像素,能卷出什么?
但它做的是跨通道的信息融合:对每个位置,把 Cin 个通道线性组合成 Cout 个。
它不改变空间尺寸,只改变通道数,而且几乎没有计算成本。
ResNet 的瓶颈结构(先用 1×1 把通道数压低,做一次 3×3 卷积,再用 1×1 升回来)就是靠它省参数:
同样输入输出通道下,参数量只有直接用一块 3×3 卷积的约 1/8。
前面把「怎么变大」讲完了。这一节只回答一个问题:什么时候这条路是亏的。
| 这条路 | 什么时候用 | 什么时候别用 | 付的是什么 |
|---|---|---|---|
| 只堆 3×3 不降分辨率 |
图小、要精确定位、不想丢任何像素 | 想看整张 224×224(要 112 层) | 层数线性涨:算力、显存、反向传播的路径一起线性涨 |
| 下采样 池化 / 步长卷积 |
分类、要全局视野、要省钱 | 小目标、精细边界 | 位置精度不可逆:20 像素的目标经 32× 下采样只剩 0.6 像素 (FPN 是一种把不同尺寸的特征图组合起来的检测网络,整篇都在治这个病) |
| 空洞卷积 | 不能降分辨率(语义分割) | 连续几层用同一个膨胀率 | 网格效应(第 4 节):一半像素永远没人看 |
| 上采样 | 把特征图放大回原尺寸 | 指望把丢掉的位置找回来 | 内容是猜的;还债要靠跳连(第 5 节 + 《分割》章) |
最后留个底:公式算出的 19×19 是「理论感受野」——理论上能影响到的范围;实际起作用的,往往只集中在中间一小块(Luo et al. 2016)。
没有。上面那句说的是理论范围:实际影响力从中心向边缘近似高斯衰减,边缘几乎影响不到输出(「有效感受野」,Luo et al. 2016)。
这一章全是能直接算出来的几何。但它藏着一笔和常识相反的交易。
一笔交易 · 一边付掉位置精度,一边买回视野
天平两头坐的是同一个操作:
回到第 2 节那张图,把「层数」滑块从 30 拖到 60:橙色虚线(不下采样)61 → 121,
绿色实线(每 3 层下采样一次)6,139 → 6,291,451,涨了约 1000 倍。
两条曲线用的是完全同一套 3×3 卷积核,唯一的差别是中间有没有把图变小——
| 暗线 | 这一章的回答 |
|---|---|
| A 信息流动 | 数据形状在这个阶段做两件相反的事: 反向的 |
| B 什么被牺牲了 | 空间分辨率换 |
| C 参数账本 | ResNet-50 最后那一段(7×7、512 通道、j = 32)一块 3×3 就是 9 × 512 × 512 ≈ 2.36M 参数、贡献 64 像素; 同样参数放在输入层(j = 1)只贡献 2 像素——深层的“视野性价比”是浅层的 32 倍。 空洞卷积更极端:d=8 时参数和计算量都不变(9C²+C 个参数、9C²HW 次计算),增量却有 16 像素 |
| D 跑在什么上 | ResNet-50 在 224×224 输入下约 41 亿次乘加(MACs:一次乘法加一次加法算一次;4.1 G,不同工具的统计口径有差异)。 把 14×14 那一段强行保持 56×56,计算量就是 16 倍((56/14)²);分辨率减半,要留的中间结果(激活)也少 4 倍。 最贵的动作是高分辨率上的卷积,所以第一段(112×112)只放 64 个通道、参数也最少:7×7×3×64+64 = 9472 个(约 0.0095M)。完整的算力账(Roofline 模型)在 《硬件与算力账本》 |
| E 它假设了什么 | 假设“多看几眼”可以代替“看得更广”:只要把相邻的局部信息一层层拼起来,
拼到足够深就能代表远处的信息(最后一层的一个 3×3,在原图上已经盖住整只猫)
(回看 CNN 章的局部性假设,那条假设就是一种 这条假设对图像大致成立,但对“左上角的猫和右下角的球有关系”这种任意长程依赖不成立: 卷积要么堆到极深,要么必须先把图变小。把这条假设拆掉的方案只有一个: 让任意两个位置直接互相看见,这就是 |
| F 违背了哪个直觉 | “丢掉信息”通常是坏事,但在这里它是唯一便宜的付款方式。
更反直觉的是:一个没有参数、粗暴到只会取最大值的 2×2 池化,
对 在这个位置上,“更聪明”输给了“更粗暴”,而这也是 ResNet 之后大家改用步长卷积的真正理由: 既然要付这笔钱,不如让训练决定买什么 |
它接住了上一章的什么:《CNN 卷积神经网络》用 3×3 的小印章省下了参数, 却没回答这么小的窗口怎么可能认出整只猫——这一章补上这个缺口。
它给后面留了什么:下一章 《经典 CNN 家族》接着问:既然降下去有用,怎么堆才又深又准? 更后面的 《语义分割》要还这笔债(U-Net 跳连); 同一件事换到图数据上,是更后面的 《图神经网络》第 3 节:一个点传 k 轮,就听到 k 步以内的邻居。
上面讲的都是「够用」的版本。想往下挖,这里有三个入口—— 它们不是必修内容,是给想再往前走一步的读者准备的。