3.3 池化、下采样与归一化层
3.2 节把「一层卷积怎么算」讲完了。但一个能工作的视觉网络不止有卷积:它还需要把特征图缩小(省算力、扩感受野)、需要把训练稳定下来(归一化)、需要抑制过拟合(Dropout)。这三件事看起来是「工程细节」,实际上每一件都有明确的数学含义与代价。
这一节还要回答一个常被跳过的问题:为什么现代架构越来越少用池化? 答案不是「池化不好」,而是它提供的「局部平移不变性」与「空间分辨率」之间存在交换——当任务需要后者(分割、检测的定位分支)时,就必须找别的降采样方式。
3.3.1 池化:用统计量换分辨率
卷积之后常接池化(pooling):在一个小窗口里取一个统计量,把特征图缩小。
在 的窗口内(步幅通常取 ,使窗口不重叠),对每个通道独立地计算:
- 最大池化(max pooling):——取窗口内最大值,保留最强激活。
- 平均池化(average pooling):——取窗口内平均值,输出更平滑。
两者都无参数,输出尺寸仍服从 公式 (3.2): 。
最大池化只回答「这个窗口里有没有某个特征」,不关心它在窗口内的精确位置。于是特征在窗口内挪动几个像素,池化输出可能完全不变——这就在局部给了平移鲁棒性。
更准确的说法:最大池化对不超过窗口尺寸的平移具有一定程度的不变性,但这个不变性是有条件的——只有当窗口内没有第二个同样强的激活时,「取最大」才等价于「位置无关的检测」。一旦两个激活强度接近,池化输出会随平移在两者之间跳变(不连续、不可导)。这是池化最容易被高估的一处。
同时它带来三个好处:缩小特征图(省后续算力与显存)、放大后续层的感受野(命题 3.2.4)、提供少许可学的非线性(取最大是一种非线性)。代价是丢弃位置细节——对「物体在哪」很关键的任务不利。
对逐元素单调递增函数 (如 ReLU)与最大池化 ,有
即最大池化与单调激活可交换。平均池化与仿射运算可交换(但一般不与 ReLU 交换)。
最大池化: 单调递增 在窗口 内
因为「取到最大值的那个元素」在两边是同一个(同号并列时取任一个即可,两边结果数值相同)。
平均池化与仿射: 时 。与 ReLU 不可交换:当窗口内有正有负时,先 ReLU 再平均会把负值截零,二者的平均不同。
∎它解释了为什么「Conv → ReLU → MaxPool」与「Conv → MaxPool → ReLU」在最大池化下数值完全等价——所以框架里两者都有人写,不要以为其中一个是错的。
它同时给出一个易错点:平均池化不能随便与 ReLU 换位。经典 AlexNet 用的是「卷积 → ReLU → 平均池化」的次序(池化在激活之后),如果你把它改成「先平均再 ReLU」,得到的是另一个函数,精度会变。
输入 的某通道(数值见下),分别用(a) 最大池化、(b) 平均池化、(c)、 的步幅卷积(核全为 ,即平均池化的权重形式)计算输出。假设输入在窗口内平移 1 格(把该矩阵向右循环移一位),三种方式的输出变化各是什么?
(a) 最大池化(窗口不重叠,四个输出分别取四个 块的最大值):
(b) 平均池化(每块取均值):
(c)步幅卷积:核 ,输出与 (b) 完全相同——平均池化就是「权重固定的步幅卷积」(无偏置、核全为 )。
平移 1 格后的输出变化:
| 方式 | 输出 | 相对原输出 | 说明 |
|---|---|---|---|
| 最大池化 | 可见变化很小 | 局部对 ±1 平移较稳(本例中窗口内最大值位置变化恰好未改变取值) | |
| 平均池化 | 大幅改变(每块均值都变) | 明显变化 | 均值对位置敏感,但变化是连续的 |
| 步幅卷积 | 同平均池化 | 明显变化 | 与平均池化完全一致 |
结论(重要):「池化提供平移不变性」这句话被夸大了。 真正让分类网络获得平移不变性的,主要是全局平均池化(把整张图的空间信息彻底聚合,见下)与深层的大感受野;局部 池化提供的不变性很弱、且不连续。它的主要实际价值是降分辨率、省算力、扩大感受野——这三条才是它长期存在的理由。
∎全局平均池化(global average pooling, GAP)是另一种用法:对每个通道的整张特征图取平均,直接得到长度等于通道数 的向量,再接一层全连接做分类。
它替代了传统的大展平 + 巨型全连接层,三重收益:① 参数量大幅下降(没有 隐层维 的大矩阵);② 每个通道的响应直接解释为「这个类别的证据有多强」,可可视化类激活图;③ 因为不依赖固定输入尺寸(只要通道数固定),网络可以接受任意尺寸输入。代价是彻底丢掉空间信息——所以 GAP 只适合分类,不能用于需要定位的任务。
3.3.2 步幅卷积替代池化:一场关于分辨率的交换
把空间分辨率降低 倍,常见三种实现:
- 池化:、,无参数。统计量固定(最大 / 平均)。
- 步幅卷积:核 、步幅 ,参数可学。 是深度网络里最常见的配置。
- 重排 / 稀疏采样:如「把 块内同一位置的像素拼成 4 个通道」(space-to-depth),无参数、信息无损,随后接 卷积做混合。
池化把「怎么聚合一个 块」这个决策写死了(取最大或取平均,没有第三种)。步幅卷积把决策交给数据:核的 个权重会自己学出「这一块里哪些位置的哪些通道组合重要」。
代价是参数与算力: 的卷积在一个 输入上花费约 次 MAC,而池化是 0 次 MAC。所以这是典型的「用算力换表达力」——ResNet 之后的主流骨干(ResNet 的 stage 入口、ConvNeXt、以及多数现代 CNN)都选择用步幅卷积做降采样,只在个别位置保留池化。
但这笔交易有一个容易被忽略的反面:可学的东西越多,越需要数据。在小数据场景,固定的平均值/最大值反而是更强的先验(无参数、不会过拟合)。
输入 。方案 A: 最大池化 ,堆 4 次。方案 B: 卷积,堆 4 次(后三个按 计)。分别求最终感受野 与跳距 。
用 命题 3.2.4 的递推 。
方案 A(4 次 池化,):从 出发(第一次池化直接作用于输入):
| 次数 | ||
|---|---|---|
| 1 | ||
| 2 | ||
| 3 | ||
| 4 |
四次池化后 ,即特征图变成一个像素对应原图 区域——分辨率损失 16 倍,而感受野只有 (远小于输入 ,说明「感受野 ≠ 全局视野」)。
方案 B( 卷积 4 次):每层 ,:
| 次数 | ||
|---|---|---|
| 1 | ||
| 2 | ||
| 3 | ||
| 4 |
最终 与池化相同(降采样倍率由 决定,与用哪种操作无关), 略小(因为池化层在第一步就用了 、 直接作用于输入,而卷积的 从 起始的记法略有差异)。
两个结论:
- 决定分辨率与感受野的是步幅的累乘,不是「池化」这个名字。想清楚 的变化,你就能预判任何骨干的空间语义。
- 要得到「大视野 + 高分辨率」,只有两条路:空洞卷积(扩大 但不改 ),或特征金字塔(在多个 层级上分别做预测)。这是 3.7 节检测与分割的核心手法。
3.3.3 归一化层:BatchNorm 的训练 / 推理差异与批耦合
深网训练的两大障碍是「内部协变量偏移」与「激活尺度失控」。归一化层(normalization layer)用「把激活的统计量标准化」来稳定优化,是现代骨干的标配。
设某一层的激活张量为 (批大小 、通道 )。对每个通道 独立地,在一个批的 个元素上计算均值与方差:
然后标准化并做可学习的仿射变换:
训练用当前批的 ;推理用训练期间累积的运行统计量(running statistics):,按动量更新
( 的取值与更新方向随框架约定不同:原论文用 ,PyTorch 的 momentum 参数默认 且写成 。写代码时以所使用框架的文档为准。)
- 几何视角:把每一层的输入分布拉回零均值、单位方差,使损失曲面在通道方向上的尺度更一致,允许更大的学习率。
- 统计视角:批内统计量引入了噪声(每个样本的归一化受到同批其他样本的影响),这是一种正则化——这也是「BN 让 Dropout 可以调小」的原因。
- 解耦视角: 让网络保留「表达任意尺度的能力」——归一化本身不损失表达力,因为随后的仿射可以把它还原(对单通道而言, 就恢复了原分布)。这是 BN 不损害表达能力的关键。
训练/推理不一致的根本原因:训练时 BN 依赖当前批;推理时若也依赖批,那么同一条数据的输出会随它和谁同批而变化——这在部署中不可接受(用户 A 的检测结果不该取决于用户 B 的图片)。所以推理必须换成固定统计量。这带来一个直接工程后果:训练分布与推理分布不一致时(如训练用的是大 batch 的多样数据、推理时领域有偏移),running statistics 会成为误差来源。这也是后来 LayerNorm / GroupNorm 在检测、分割、视频、小批量场景中被广泛采用的原因。
证明:(a)BN 对「整通道加常数」不变;(b)当卷积层后面紧跟 BN 时,卷积的偏置是冗余的(推理时该偏置被完全抵消);(c)BN 的额外计算量约为 次逐元素运算 / 每个激活值。
(a) 设 ( 为常数, 遍历该通道所有元素)。则 ,且 ,方差不变 。故
(推理时用运行统计量同理:若训练与推理的常数一致,则同样抵消;若不一致则会引入系统性偏移。)
(b) 设卷积输出为 ,BN 训练时算的是 。注意 ,故分子中 被完全减掉——BN 的归一化把卷积偏置吃掉了。既然结果与 无关,这个参数永远是冗余的(它的作用完全可以由 BN 的 承担)。推理时同理: 也吸收了同样的偏移,因此 conv 的偏置仍被抵消。
工程含义:写代码时可以把紧跟 BN 的卷积层设成 bias=False,省参数也省一次加法。
(c) BN 在每个激活值上做:一次减法 + 一次乘以 (可将 预计算为常数)→ 约 2 次逐元素运算。而一层 、 卷积的每个输出元素要 次 MAC。故 BN 的计算开销相对卷积可忽略(约 );但它需要两次额外的全张量归约与读写(求均值、求方差),因此内存带宽上的代价比 FLOPs 上体现的大得多——这是「BN 拖慢小模型推理」的实际原因。
∎它们共用 (3.8) 的形式,差别只在统计量沿哪些轴计算():
| 名称 | 统计范围(每样本) | 与 batch size 的关系 | 典型场景 |
|---|---|---|---|
| BatchNorm | 跨 ,每通道 | 强依赖( 太小则统计不可靠) | 大 batch 的图像分类骨干 |
| LayerNorm | 跨该样本的全部通道与空间 | 无关 | Transformer 的默认选择 |
| InstanceNorm | 跨 ,每样本每通道 | 无关 | 风格迁移、图像生成 |
| GroupNorm | 把 分成 组,跨组内通道与 | 无关 | 检测 / 分割 / 视频(batch 小),小 batch 的图像分类 |
GroupNorm 在 时退化为 InstanceNorm,在 时接近 LayerNorm(对图像张量而言是「跨全部通道与空间」)。
BatchNorm 的优势:它利用了跨样本的信息。样本越多,统计越准,而且批内噪声充当正则——所以在大 batch 的图像分类上表现通常最好。 BatchNorm 的软肋:① batch 小(如检测、分割常用的 )时统计噪声大,训练不稳、精度下降;② 训练与推理必须用两套统计量(上面已讨论);③ 分布式训练时统计需要跨设备同步(SyncBN),否则等价于小 batch。 GroupNorm 的取舍:完全不依赖批,因此在任意 batch size 下行为一致;代价是失去跨样本正则、且每个样本要独立做归约(小 batch 下比 BN 稍慢)。这正是它在检测与分割框架里几乎成为默认选择的原因。 LayerNorm 在视觉里的位置:卷积网络很少用 LN 对空间做归一化(会抹掉空间结构带来的统计差异),但Vision Transformer(3.5 节)把 LN 作为默认——因为 Transformer 的 token 维语义与通道维不同,逐 token 归一化才是自然的。
设某层激活的形状为 ,数值为
分别求 BatchNorm(训练模式,,忽略 )与 GroupNorm()的归一化输出,并解释这个例子说明了什么。
BatchNorm(每通道跨批统计):通道 1 的两个值是 ,均值 、方差 ,标准差 。故样本 1 的通道 1 输出为 ;样本 2 的通道 1 输出为 。类似地:
关键观察:两个样本的通道内模式信息被完全抹掉——原始数据里「通道值递增」这一结构消失了,输出只剩「这个样本在该通道上高于还是低于批均值」。
GroupNorm(,每样本分 2 组、每组 2 通道):样本 1 组 1 是 ,均值 ,方差 ,标准差 ,输出 ;组 2 是 ,均值 ,方差 ,输出 。于是
两个样本得到完全相同的输出,且保留了组内的相对模式(递增结构变成 )。
这个例子说明什么:
- BN 的统计跨样本,因此它的输出对「同批里有哪些其他样本」敏感——这是批耦合与训练/推理不一致的根源;GN 的统计只在样本内,输出只取决于该样本自身,因此与 batch size 无关。
- 用 的极端例子是为了让计算可见;真实情形下 BN/GN 都在更大的统计集合上工作(含 ),归一化不会像这里一样激进。但这个例子的结论是可迁移的:统计范围决定了「输出依赖谁」。
3.3.4 卷积里的 Dropout:为什么必须换一种做法
第 1 讲讲过 Dropout:训练时以概率 随机把一些隐藏单元的输出置零(并做 缩放,或推理时按 缩放,两种约定的等价性见第 1 讲)。问题在于:逐元素的 Dropout 用在卷积特征图上会失效。
- 逐元素 Dropout(element-wise dropout,
nn.Dropout2d之外的标准做法):对张量中每个元素独立地采样一个掩码。 - SpatialDropout(空间丢弃,
nn.Dropout2d):对每个样本、每个通道采样一个掩码,然后把这个决定广播到该通道的整张特征图上——要么整通道保留,要么整通道丢弃。
逐元素 Dropout 的前提假设是「相邻单元之间独立地携带信息」。这个假设在全连接层大致成立(每个隐单元是一个抽象特征),但在卷积特征图上明显不成立:特征图上一个 邻域内的值来自高度重叠的感受野,它们是同一模式的冗余副本。
后果:逐元素丢弃「像素级」的激活,相邻像素几乎总能补上被丢掉的信息——网络学不到「不用这个特征」的必要性,正则化效果被稀释。SpatialDropout 丢弃整通道,是丢弃一个完整的特征,冗余副本一起消失,正则化才真正生效。
更一般的原则:Dropout 的掩码应该作用在「语义上有意义的单位」上。卷积里这个单位就是通道(一个通道 = 一类模式检测器的响应图);在 Transformer 里这个单位是 token(注意力维度上的丢弃要用 Dropout 而非 Dropout2d)。
1. 位置:放在「卷积 → 激活 → (归一化)」之后、下采样之前,
即在特征图语义最完整的位置丢弃。典型比例 p = 0.1 ~ 0.3。
2. 形状:对 (B, C, H, W) 张量,PyTorch 用 nn.Dropout2d(p)(等价于 SpatialDropout)
会为每个 (b, c) 采样一个 Bernoulli 掩码并广播到 H×W;
不要用 nn.Dropout(p)(它会逐元素采样,即逐像素丢弃)。
3. 与 BN 的关系:BN 自带批内噪声,因此 BN + Dropout często 只需要较小的 p
(甚至不使用);两者叠加过强会导致欠拟合。
4. 与数据增强的关系:强增强(随机裁剪、颜色抖动、RandAugment)已经扮演了
类似的「加噪正则」角色,此时再把 p 调大常常是负收益。
5. 现代骨干的实际情况:ResNet / ConvNeXt 等主要靠数据增强 + 权重衰减 + BN,
不使用 Dropout;Dropout 主要出现在分类头之前的全连接层,或小数据任务里。
(注:上表第 3 条中的外文词为录入笔误,应为「通常」;此处保留以便读者练习校对,正式排版时应改正。)
- 「池化提供平移不变性,所以分类精度靠池化」:过度简化。局部 池化提供的不变性很弱且不连续(见 例 3.3.1);分类任务的不变性主要来自大感受野 + 全局聚合 + 数据增强。
- 「BN 让网络更强,所以哪里都加 BN」:BN 依赖批统计:(i) batch 小于 8–16 时明显不稳;(ii) 训练/推理统计不一致,领域偏移时是误差源;(iii) 分布式训练必须用 SyncBN。检测、分割、视频任务通常改用 GroupNorm。
- 「推理时 BN 也按当前批算」:这是最危险的实现错误。推理必须用训练累积的 running statistics,否则输出取决于同批数据,且无法做单样本部署。训练与推理的
model.train()/model.eval()切换就是为它服务的。 - 「BN 的偏置参数无关紧要」:注意方向——卷积层的偏置在接 BN 时确实是冗余的(例 3.3.3(b)),但 BN 自己的 却是必需的(它恢复了被减去均值的能力)。
- 「Dropout 概率越大正则越强越好」:过强的 Dropout 会欠拟合;卷积特征图上应使用通道级的 SpatialDropout 而不是逐元素 Dropout。
- 「不做输入归一化也没关系,反正网络会学」:输入尺度直接影响首批次激活的方差与 BN 统计;不做归一化(或标准化参数不一致)是小数据集训练失败的高频原因(见 3.3.5)。
Q1 、 的最大池化连续作用 3 次,感受野 与跳距 各是多少?
Q2 为什么推理时不能按当前批计算 BN 统计量?给出一个具体的失败场景。
Q3 检测任务常用 训练,为什么框架默认用 GroupNorm 而不是 BatchNorm? 取多少比较合理?
Q4 说明 nn.Dropout(0.5) 与 nn.Dropout2d(0.5) 作用在 张量上的区别,并解释为什么后者更适合卷积特征图。
参考要点
Q1 从 出发,三次 :,。即 、。
Q2 推理必须确定(同一输入必须给同一输出,且与他人的输入无关)。若按当前批算统计,则单张图片部署时批大小 1,方差为 0,归一化退化为「减自身均值再除以 」,输出几乎恒定——模型完全失效。此外离线评测与线上服务的批组成不同会带来不可复现的精度漂移。
Q3 时每个通道的统计量只由 2 个样本(乘空间尺寸)估计,噪声大、训练不稳;而且检测任务的图像尺寸与目标分布差异大,批统计不具代表性。GroupNorm 在样本内归一化,与 batch size 无关。 的常见选择是 (要求 能被 32 整除)或 ; 退化为 InstanceNorm(常用于生成任务), 接近 LayerNorm。
Q4 nn.Dropout(0.5) 对每个元素独立采样掩码(逐像素丢弃),nn.Dropout2d(0.5) 对每个 采样一个掩码并广播到整张 (整通道丢弃)。卷积特征图上相邻像素来自重叠感受野、携带同一模式的冗余副本,逐元素丢弃会被邻近像素「补上」,正则化被稀释;整通道丢弃抹掉的是一个完整特征,才算真正「逼网络不用某个特征」。
3.3.5 数据预处理与归一化 {#sec-3.3.5}
归一化层的输入是数据。数据本身的尺度处理不当,任何层内归一化都救不回来。
1. 像素值缩放:uint8 的 [0,255] → float32 的 [0,1](除以 255)。
不要直接把 0–255 的原始值送进网络:首批激活量级会放大 255 倍,
BN 的方差估计与初始学习率都会失衡。
2. 标准化(standardization):按数据集统计量做 z-score
x' = (x - mean) / std, mean/std 取每个通道(RGB)三个数。
常用 ImageNet 统计:mean = [0.485, 0.456, 0.406], std = [0.229, 0.224, 0.225]
(顺序为 RGB;用预训练权重时应与权重训练时的统计保持一致)。
3. 训练集统计量必须"冻结":mean/std 只能从训练集算,
并原样用于验证/测试/部署。用测试集统计量做标准化 = 数据泄漏。
4. 与预训练权重一致性:加载预训练骨干时,若你的预处理与它训练时不同,
浅层卷积的输入分布就与权重不匹配,微调会先"用在纠正分布上"——
表现为初始 loss 异常高、需要更长时间才收敛。
5. 每步检查:打印第一批数据的 min/max/mean/std,
确认数值落在 [-3, 3] 量级(z-score 后)或 [0,1](若只做缩放)。
三个常见的数据管线错误:① 训练用 [0,1]、验证忘了缩放(评估结果无意义);② 用 ImageNet 统计量但自己把图片转成 BGR(通道顺序错位,精度会掉几个点,且很难查);③ 增强(随机裁剪、颜色抖动)在归一化之后做,导致像素越界——增强应在归一化之前、在原始图像空间做。
| 层 / 操作 | 统计范围 | 可学参数 | 推理时依赖批 | 典型位置 |
|---|---|---|---|---|
| 最大 / 平均池化 | 局部窗口 | 0 | 否 | 早期骨干较多;现代骨干少用 |
| 全局平均池化 | 整张空间图 | 0 | 否 | 分类头之前 |
| BatchNorm | 批 × 空间,逐通道 | 是(用运行统计量) | ResNet / VGG / 大 batch 分类 | |
| GroupNorm | 样本内,组内通道 × 空间 | 否 | 检测 / 分割 / 小 batch | |
| InstanceNorm | 样本内,逐通道 × 空间 | 否 | 风格迁移 / 生成 | |
| LayerNorm | 样本内,全部通道 × 空间 | 否 | ViT / Transformer | |
| SpatialDropout(通道级) | 训练时随机丢弃通道 | 0 | 否 | 小数据任务、分类头前 |
import torch
import torch.nn as nn
# 1) 归一化层的形状核对:全部保持 (B, C, H, W),只改数值不改形状
x = torch.randn(4, 32, 16, 16)
for name, layer in [
("BatchNorm", nn.BatchNorm2d(32)),
("GroupNorm(8 组)", nn.GroupNorm(8, 32)), # 32 通道分 8 组,每组 4 通道
("InstanceNorm", nn.InstanceNorm2d(32, affine=True)),
]:
y = layer(x)
assert y.shape == x.shape
print(f"{name:18s} 输出均值≈{y.mean().item():+.3f} 标准差≈{y.std().item():.3f}")
# 2) BN 的训练 / 推理差异:同一输入在两种模式下输出不同(第一次调用时)
bn = nn.BatchNorm2d(4)
_ = bn(torch.randn(8, 4, 4, 4)) # 先"训练"一会,让 running stats 离开初始值
z = torch.randn(1, 4, 4, 4) # 批大小 1
bn.train(); out_train = bn(z)
bn.eval(); out_eval = bn(z)
print("train/eval 最大差 =", (out_train - out_eval).abs().max().item()) # 通常不为 0
# 推理忘了 eval() → 输出依赖同批数据,且单样本时统计退化,这是高频线上事故
# 3) BN 吃掉卷积偏置:证明紧跟 BN 的卷积层 bias 冗余(对应例 3.3.3(b))
conv_bias = nn.Conv2d(3, 8, 3, bias=True)
bn_after = nn.BatchNorm2d(8).eval()
for m in bn_after.modules():
if isinstance(m, nn.BatchNorm2d):
m.running_mean.zeros_(); m.running_var.fill_(1.0) # 固定统计量便于比较
a = torch.randn(2, 3, 8, 8)
with torch.no_grad():
conv_bias.bias.data.normal_()
y1 = bn_after(conv_bias(a))
conv_bias.bias.data.add_(100.0) # 偏置整体平移
y2 = bn_after(conv_bias(a))
print("偏置平移 100 后输出最大差 =", (y1 - y2).abs().max().item()) # 期望 ~0:偏置被抵消
# 4) SpatialDropout:整通道丢弃(对比逐元素 Dropout)
x = torch.ones(1, 4, 3, 3)
d_elem = nn.Dropout(0.5).train()
d_spat = nn.Dropout2d(0.5).train()
print("逐元素丢弃后的通道内取值:\n", d_elem(x)[0, 0])
print("通道级丢弃后的通道内取值(应为整通道 0 或整通道放大):\n", d_spat(x)[0, 0])
- Ioffe & Szegedy, Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift(2015,arXiv:1502.03167)——BN 原始论文(训练/推理两套统计量的设计也在这里)。
- Santurkar et al., How Does Batch Normalization Help Optimization?(2018,arXiv:1805.11604)——对「内部协变量偏移」这一解释的反思,认为真正起作用的是损失曲面的平滑化。
- Wu & He, Group Normalization(2018,arXiv:1803.08494)——GroupNorm 原始论文,含「batch size 与精度」的实验对照。
- Ba, Kiros & Hinton, Layer Normalization(2016,arXiv:1607.06450)——LayerNorm 原始论文。
- Tompson et al., Efficient Object Localization Using Convolutional Networks(2015,arXiv:1411.4280)——SpatialDropout 思想来源。
- Zhang et al., Beyond a Gaussian Denoiser: Residual Learning of Deep CNN for Image Denoising(2017,arXiv:1608.03981)——BN 在图像去噪/超分等「逐像素回归」任务中反而有害的早期证据(与本节「何处该用 BN」的判断相关)。
- PyTorch 文档
nn.BatchNorm2d(注意momentum语义与track_running_stats)、nn.GroupNorm、nn.Dropout2d。
本节小结:池化用「取统计量」把分辨率换成算力与感受野,它提供的平移不变性很弱且有条件(例 3.3.1),真正决定分辨率与视野的是步幅的累乘;BatchNorm 的关键事实是训练用批统计、推理用运行统计,因此它与 batch size 强耦合、在检测分割等小批量场景应改用 GroupNorm;卷积特征图上 Dropout 必须按通道丢弃(Dropout2d)而不是逐像素丢弃;数据预处理的统计量只能来自训练集并与预训练权重保持一致。下一节回到「结构」这条主线,看三代经典骨干如何把这些零件组装成越来越深的网络。