在 C 村,村长常年为一块麦田安排巡逻。9 个队员站成 3×3 的方阵,一次只能看清相邻的 9 块地。为了让队伍看得更远,通常要么缩小地图,要么增加人手,但前者会丢掉细节,后者会抬高预算。空洞卷积给出的办法是:让这 9 个人拉开间距,每隔几垄站一个人。人还是 9 个,队伍却能覆盖更大范围。这个思路进入卷积神经网络后,就变成了“不增加参数扩大感受野”的经典操作——空洞卷积。

岗位关联

掌握空洞卷积,你将在语义分割、语音建模、实时检测等任务中,以几乎零额外参数成本换取更大的感受野,是调模型时非常实用的“性价比之王”。

目录
  1. 可视化演示
  2. 困境与动机
  3. 原理机制
  4. 空洞率设置
  5. 多尺度融合
  6. 网格效应消除
  7. 语义分割应用
  8. 实践实现要点
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

通过动画直观理解空洞率如何扩大卷积核感受野,观察多层堆叠的指数级感受野增长以及网格效应的产生与消除。

本节配有交互动效(进入视口后自动加载,约 3KB)。

空洞率与感受野 红色高亮为卷积核采样位置 灰色为未采样的输入位置 RF = (k-1)·r + 1 增大空洞率 r 可在不增加参数的前提下扩大感受野

困境与动机

在 C 村,村长让 9 名巡逻队员去检查麦田。普通 3×3 卷积就像队员们挤成一个紧密的方块,一次只能看到 9 块相邻的地。要想看得更远,要么把地图缩小,这对应池化操作;要么加派人手,这对应增加层数或通道数。缩小地图会损失细节,加派人手又会让预算升高。空洞卷积的想法很简单:不减地图、不加人,只让他们按更大的间距站,视野就出来了。

这个困境在卷积网络里经常出现。连续堆叠多个 3×3 卷积虽然能扩大感受野,但速度很慢;插进池化层能快速扩大,却会降低分辨率。尤其在语义分割这种“每个像素都要输出标签”的任务里,细节丢失非常致命。空洞卷积的出现,就是不依赖池化也能扩大感受野的关键手段。假设连续堆叠 N 层步长为 1 的 3×3 卷积,感受野的增长是线性的:

这个困境看似无解:想看得远要么堆更多层,要么引入池化。空洞卷积给出第三种答案——不缩小地图、不增加人手,只改变站位。

RFN=1+N×(3−1)=2N+1\displaystyle RF_N = 1 + N \times (3-1) = 2N + 1
这个公式说明:堆 3 层普通 3×3 卷积,视野也只有 7×7。如果不想堆叠太多层,就需要换一种拉开间距的思路。
  1. N 为层数这里假设连续使用 N 个步长为 1、卷积核大小为 3×3 的卷积层。
    NN
  2. 每层扩张量每个 3×3 卷积在上下左右各多看 1 格,所以每经过一层,感受野直径增加 2。
    (3−1)=2(3-1)=2
  3. 初始基准还没做任何卷积时,输出上的一个点只对应输入中的 1×1 区域。
    RF0=1RF_0 = 1
  4. 汇总通式把 N 层贡献相加,得到第 N 层输出点的感受野边长。
    RFN=1+2NRF_N = 1 + 2N

原理机制

假如村长让 9 个人站得更开,从“前后左右隔一格”变成一个大方阵,站在中间的人脚底仍有土地,只是他左右、上下、四角都隔着空地。这就是空洞卷积中的“洞”。人还是 9 个,但因为站位跨度变大,他们能同时观察到更大的矩形田块。在 CNN 里,所谓的“洞”就是卷积核中不参与计算的空位。

从数学上看,原始卷积核仍保存 9 个可学习权重。膨胀率 r 表示相邻有效权重之间隔着几个单位。r=1 就是普通卷积;r=2 时,权重不再落在相邻格点上,而是在跨度 5×5 的范围内按规律分布。中间那些没有权重的格子,就相当于被拉开的空地。把原始权重拷进一个更大的零矩阵,就是空洞卷积核的构造方式:

所以空洞卷积的“洞”不是把参数删掉,而是把参数之间的距离拉大。就像巡逻队没有少人,只是阵型变宽了。

w′[i⋅r,j⋅r]=w[i,j],其余位置为 0\displaystyle w'[i \cdot r, j \cdot r] = w[i,j], \quad \text{其余位置为 } 0
它说明:空洞卷积只是把原始权重放进更大采样网格,中间的空位不参与学习,因此参数量完全不变。
  1. 原始权重 w[i,j]普通卷积核中 \(K \times K\) 个可学习参数,比如 3×3 卷积有 9 个。
    w[i,j]w[i,j]
  2. 扩张后权重 w′[i·r, j·r]把原始权重复制到新矩阵的对应位置。
    w′[i⋅r,j⋅r]w'[i \cdot r, j \cdot r]
  3. i 和 j 是原始核内索引它们从 0 取到 K-1,描述权重在卷积核里的行和列。
    i,j∈{0,1,…,K−1}i, j \in \{0,1,\dots,K-1\}
  4. r 是膨胀率每两个有效权重之间被跳过的单位格数,r=1 时退化为标准卷积。
    r=1,2,3,…r = 1, 2, 3, \dots

空洞率设置

巡逻队拉开多大距离,直接决定能看多远。这个距离就是膨胀率 r。如果 r 取得小,队伍紧凑,适合观察近处细节;如果 r 取得大,队伍松散,能覆盖大片田地,但对脚下细小的庄稼变化可能不太敏感。工程上选择 r,就是在“看清局部”和“望得更远”之间做权衡。

对于一个卷积核大小为 K、膨胀率为 r 的空洞卷积,它单层能看到的范围有一个简洁公式:

实际使用中,通常不会只用一个大 r,而是让不同层或不同分支使用不同的 r。小 r 负责近处细节,大 r 负责远处结构,最后再把信息合并起来——这就是下一节的多尺度融合。

RFd=(K−1)×r+1\displaystyle RF_d = (K-1) \times r + 1
比如 3×3 卷积在 r=2 时能看 5×5,在 r=3 时能看 7×7:权重仍是 9 个,视野却成倍拉开。
  1. K 是原始卷积核边长以常用的 3×3 卷积为例,K=3。
    K=3K = 3
  2. r 是膨胀率它表示相邻有效采样点之间隔了几个格子。
    rr
  3. 间隔总量一条边上有 K-1 个间隔,每个间隔长度为 r 格,所以总跨度为 (K-1)×r。
    (K−1)×r(K-1) \times r
  4. 加上起点覆盖范围还要算上第一个采样点占据的 1 格。
    RFd=(K−1)×r+1RF_d = (K-1) \times r + 1

多尺度融合

村长发现,单靠一种间距没法同时看清蚂蚁和山。于是他把巡逻队分成几个小组,有的小组隔 1 垄站,有的隔 2 垄,有的隔 3 垄,最后把各组的观察报告拼成一张总图。空洞卷积也这样用:对同一输入特征图,并行跑多个不同膨胀率的卷积,再把结果沿通道方向拼接。这种并行多分支结构,就是多尺度感受野融合。

设输入特征图为 X,第 i 个分支使用膨胀率 \(r_i\) 的空洞卷积 \(f_{r_i}\),那么多尺度融合后的特征可以写成:

这种设计在 DeepLab 系列中非常有名,叫 ASPP,也就是空洞空间金字塔池化。它让网络既能识别细小物体,又能理解大范围背景,是语义分割里的标准操作。

F=Concat(fr1(X), fr2(X), fr3(X))\displaystyle F = \text{Concat}\Big(f_{r_1}(X),\, f_{r_2}(X),\, f_{r_3}(X)\Big)
这个式子表示:同一个地图被不同距离的“巡逻队”同时观察,最后把他们的观察结果拼在一起,既有细节又有全局。
  1. X 是输入特征图它来自上一层,比如大小为 H×W×C 的中间特征。
    XX
  2. f_{r_i} 是膨胀率为 r_i 的空洞卷积同一个输入通过不同分支,得到不同感受野的表达。
    fr1,fr2,fr3f_{r_1}, f_{r_2}, f_{r_3}
  3. Concat 表示拼接把多个分支的输出在通道维度上拼成一张更厚的特征图。
    Concat(⋅)\text{Concat}(\cdot)
  4. 整体 F融合后的特征同时包含小、中、大三种尺度的信息。
    FF

网格效应消除

如果所有巡逻队都按 r=2 等距站,几支队伍的位置会周期性地重合,结果有些田垄被反复检查,有些田垄却始终没人看。在特征图上,这种现象表现为棋盘格状的盲区,被称为“网格效应”。空洞卷积虽然扩大了感受野,但如果多个空洞卷积层使用相同的膨胀率堆叠,就容易漏掉局部信息。

为了消除这种漏检,研究人员提出混合空洞卷积,也就是 HDC。核心思路是:一组空洞卷积的膨胀率不要都选倍数关系,而是采用类似 r=1、2、3 的锯齿状设计,让不同层的采样点互相补位。一个常见的经验条件是:

所以,空洞卷积不是“拉开间距就完事”,还要让间距有节奏。就像多个巡逻队错峰值守,才能保证整片田没有死角。

gcd⁡(r1,r2,r3)=1\displaystyle \gcd(r_1, r_2, r_3) = 1
这里的 gcd 是最大公约数。最大公约数为 1 时,不同层的采样位置不易长期重复,能有效打破棋盘格规律。
  1. gcd 是最大公约数它描述两个或多个整数能否同时被某个数整除。
    gcd⁡(⋅)\gcd(\cdot)
  2. r₁、r₂、r₃ 是连续几层或几个分支的膨胀率例如 \((2,4,8)\) 的最大公约数是 2,容易产生规律性空洞。
    r1,r2,r3r_1, r_2, r_3
  3. 最大公约数为 1说明三个膨胀率没有公共因子,采样点不容易整齐地错开。
    gcd⁡(r1,r2,r3)=1\gcd(r_1, r_2, r_3) = 1
  4. 实践组合常见的锯齿状组合如 \((1,2,3)\),既能扩大感受野,又能让不同层的信息互相补齐。
    (r1,r2,r3)=(1,2,3)(r_1, r_2, r_3) = (1,2,3)

语义分割应用

语义分割要回答的问题是:图像中每一小块土地分别是什么作物?这类任务被称为密集预测,因为它要求对每个像素都输出类别。如果使用池化来扩大感受野,图像的细节会变模糊,分割边界就会像毛边一样粗糙。空洞卷积恰好能在不缩小特征图的情况下扩大视野,让网络保留高分辨率细节。

DeepLab 系列把这一思想发挥到极致。ASPP 模块中,同一输入分别经过 1×1 卷积和膨胀率为 6、12、18 的 3×3 空洞卷积,再把结果拼起来。写成公式就是:

除了语义分割,空洞卷积也常用于音频处理。WaveNet 就在时间轴上用膨胀率 1、2、4、8 的堆叠,让模型不用降低采样率也能听到足够长的声音片段。实时检测中的 RFB 模块同样借鉴了这种多尺度思想。

Y=Concat(C1×1(X), C3×3, r=6(X), C3×3, r=12(X), C3×3, r=18(X))\displaystyle Y = \text{Concat}\Big(C_{1\times1}(X),\, C_{3\times3,\,r=6}(X),\, C_{3\times3,\,r=12}(X),\, C_{3\times3,\,r=18}(X)\Big)
这相当于同时派四支不同间距的巡逻队,分别观察近、中、远三个层次,最后把观察报告合并成完整地图。
  1. C_{1×1}(X)用 1×1 卷积压缩通道并保留原图级别的局部信息。
    C1×1(X)C_{1\times1}(X)
  2. 三个空洞卷积分支使用膨胀率 6、12、18 的 3×3 卷积,分别覆盖不同大小的区域。
    C3×3, r=6, C3×3, r=12, C3×3, r=18C_{3\times3,\,r=6},\ C_{3\times3,\,r=12},\ C_{3\times3,\,r=18}
  3. Concat 拼接把四路输出在通道方向合并。
    Concat(⋅)\text{Concat}(\cdot)
  4. Y 是最终分割特征它既保留边界细节,又包含全局上下文,让每个像素的分类更准确。
    YY

实践实现要点

在代码中实现空洞卷积非常简单,但有几个细节值得注意。首先是参数账单:不管 r 取多大,原始卷积核里的权重数都不变。设输入通道数为 \(C_{in}\),输出通道数为 \(C_{out}\),卷积核大小为 K,则参数量为:

除参数量外,还要记得调整 padding。对于卷积核大小为 3、膨胀率为 r 的空洞卷积,通常设置 padding=r,才能让输出特征图保持原尺寸。PyTorch 里只需在 nn.Conv2d 中指定 dilation=r,框架会自动处理采样位置。使用空洞卷积时,既要享受大感受野的好处,也要像排兵布阵一样设计好膨胀率,才能真正做到不增参数、不留盲区。

P=Cin×Cout×K2\displaystyle P = C_{in} \times C_{out} \times K^2
注意公式里没有 r。膨胀率只改变权重的摆放位置,不改变权重个数,这是空洞卷积“物美价廉”的根本原因。
  1. C_in 是输入通道数上一特征图有多少个通道。
    CinC_{in}
  2. C_out 是输出通道数这一层想生成多少个新通道。
    CoutC_{out}
  3. K² 是单个卷积核的权重数3×3 就是 9,5×5 就是 25。
    K2K^2
  4. r 不出现说明空洞卷积的参数量与膨胀率无关。
    P=Cin×Cout×K2P = C_{in} \times C_{out} \times K^2

AI 应用场景

语义分割:让每块地都有自己的标签

阶段:模型结构设计 / 特征提取层

解决的问题:传统语义分割为了扩大感受野依赖池化,导致边界细节模糊、小物体丢失。空洞卷积可以在不缩小特征图的情况下扩大视野,再用多尺度融合聚合近处与远处信息。

具体案例:自动驾驶系统需要把街景图片逐像素识别为道路、行人、车辆和天空。DeepLab 使用 ASPP 模块,以膨胀率 6、12、18 的并行空洞卷积捕捉多尺度上下文,让分割边界更锐利。

语音建模:在时间轴上拉开视野

阶段:输入编码 / 序列特征提取

解决的问题:音频采样率很高,普通卷积想覆盖足够长的上下文,需要堆叠很多层或大幅降采样,而降采样会损失声音细节。空洞因果卷积能在不跳过输入点的情况下,让每个输出听到更长的历史片段。

具体案例:语音合成模型 WaveNet 在时间轴上堆叠膨胀率为 1、2、4、8 的空洞卷积,感受野指数增长,生成的语音更连贯自然。

实时目标检测:兼顾速度与尺度

阶段:检测头部 / 多尺度特征增强

解决的问题:工业质检中,细小划痕和大型污渍同时出现,单一固定感受野很难兼顾。若用多个普通大卷积核,参数和延迟会明显上升;空洞卷积则用同参数成本提供多种感受野组合。

具体案例:RFB-Net 在检测模块中引入不同膨胀率的空洞卷积,模拟人类视觉的感受野结构,让模型同时识别微小缺陷和整体形变。

Python 演示

python27 行
import torchimport torch.nn as nn def effective_kernel(kernel_size, dilation):    return (kernel_size - 1) * dilation + 1 def main():    torch.manual_seed(0)    x = torch.randn(1, 3, 32, 32)     conv_std = nn.Conv2d(3, 8, kernel_size=3, padding=1)    conv_dil = nn.Conv2d(3, 8, kernel_size=3, padding=2, dilation=2)     out_std = conv_std(x)    out_dil = conv_dil(x)     params_std = sum(p.numel() for p in conv_std.parameters())    params_dil = sum(p.numel() for p in conv_dil.parameters())     print("标准卷积输出:", tuple(out_std.shape))    print("空洞卷积输出:", tuple(out_dil.shape))    print("标准卷积参数量:", params_std)    print("空洞卷积参数量:", params_dil)    print("等效感受野:", effective_kernel(3, 2)) if __name__ == "__main__":    main()
目的:用 PyTorch 演示 3×3 普通卷积与膨胀率为 2 的空洞卷积,输出尺寸相同、参数量相同,但等效感受野从 3×3 变成 5×5。
  1. nn.Conv2d(3, 8, kernel_size=3, padding=2, dilation=2)创建一个空洞卷积层,膨胀率设为 2,padding 也设为 2 以保持输出尺寸。
  2. effective_kernel(3, 2)用公式 (K-1)*r+1 计算等效感受野,得到 5。
  3. sum(p.numel() for p in conv_dil.parameters())统计空洞卷积的所有参数数量,和普通卷积对比。
  4. torch.manual_seed(0)固定随机种子,保证每次运行结果可复现。

常见误区

误区空洞卷积的等效核从 3×3 变成了 5×5,那参数量不也应该从 9 变成 25 吗?我总觉得多出来的格子都是要学的参数。

正解等效核里多出来的格子只是空洞,权重仍然只有原始 9 个。就像 9 个巡逻队员站得更开,队伍覆盖 5×5 的田,但人数还是 9。零值位置不参与训练,也不占用参数量。

为何常见:人们习惯用“核大小”推测参数数量,而忽略了空洞卷积是稀疏采样的本质。

误区既然 r 越大感受野越大,那我直接把所有层都设成 r=8,是不是就能一眼看完整张图?

正解r 过大会让采样点过于稀疏,局部细节和小目标很容易被跳过。就像巡逻队员隔得太远,中间有小偷也看不见。实际中常把不同 r 组合起来,并配合 HDC 策略。

为何常见:因为只看到“感受野公式是线性增长”这一面,忽略了采样密度对局部信息的损害。

误区空洞卷积每隔 r 个格子取一个点,这不就是步长为 r 的卷积在跳着走吗?

正解步长卷积会减少输出位置,相当于巡逻队跳过某些田垄不记录;空洞卷积仍然对每个位置都产生输出,只是卷积核内部采样点之间有间隔。两者对输出特征图密度的作用完全不同。

为何常见:两者都有“隔格子”的视觉特征,初学者很容易混淆“核内间隔”和“输出间隔”。

误区空洞卷积不降分辨率还能扩大感受野,比池化强太多了,以后所有池化层都能换成空洞卷积。

正解空洞卷积确实能替代一部分池化带来的感受野扩展,但池化还能降低计算量、提供平移不变性。如果完全去掉下采样,计算和显存开销会变得很大,实践中常需要两者配合。

为何常见:因为空洞卷积“保持分辨率”的优势太抢眼,让人忽略了池化在计算效率和特征鲁棒性上的作用。

误区空洞卷积感受野更大,参数量又没变,那计算量应该也比普通卷积小很多吧。

正解如果输出位置数量相同、参与乘加的权重数相同,空洞卷积和同尺寸普通卷积的计算量基本一致。相比等效的大尺寸密集卷积,它确实更省;但相比标准 3×3 卷积,它并不天然更便宜。

为何常见:人们容易把“感受野大”和“计算量小”划等号,没注意到计算量主要取决于输出点数和参与运算的非零权重数。

面试题

Q1. 空洞卷积的核心能力是在不增加什么的前提下扩大感受野?

单选题 · easy

  • A.输入通道数量
  • B.卷积核参数量← 正确答案
  • C.输出特征图数
  • D.网络训练轮次

答案:B。空洞卷积只是把原始权重放到更大间距的采样网格中,权重个数不变,因此参数量不变。输入通道、输出通道和训练轮次都由其他设计决定,不是空洞卷积的收益点。

Q2. 一个 3×3 空洞卷积,膨胀率 r=2,等效卷积核大小是多少?

单选题 · easy

  • A.3×3
  • B.4×4
  • C.5×5← 正确答案
  • D.7×7

答案:C。根据公式 \( (K-1) \times r + 1 \),代入 K=3、r=2 得到 5,所以等效核是 5×5。注意它仍然只有 9 个非零权重。

Q3. 一个 3×3 空洞卷积,膨胀率 r=3,单层感受野是多少?

单选题 · mid

  • A.3×3
  • B.5×5
  • C.7×7← 正确答案
  • D.9×9

答案:C。代入 \( (3-1)\times 3 + 1 = 7 \),所以单层就能看到 7×7 的区域。它不需要堆叠多层,也不需要引入池化。

Q4. 以下哪些做法能缓解空洞卷积的网格效应?

多选题 · mid

  • A.使用混合空洞卷积HDC← 正确答案
  • B.所有空洞率保持相同
  • C.使用 r=1、2、3 组合← 正确答案
  • D.只使用最大池化层

答案:AC。HDC 和锯齿状膨胀率组合可以让不同层的采样点互相补位,减少棋盘格盲区。所有空洞率相同会加剧规律性空洞;只使用最大池化并不能解决稀疏采样带来的漏检问题。

Q5. 连续堆叠 3 层普通 3×3 卷积(步长为 1),感受野是多少?

单选题 · mid

  • A.5×5
  • B.7×7← 正确答案
  • C.9×9
  • D.11×11

答案:B。普通卷积堆叠时,每层只让感受野直径增加 2。3 层后就是 \(1+3\times2=7\),即 7×7。相比之下,空洞卷积用一层就能达到类似视野。

Q6. 下列哪项是空洞卷积的主要优势?

单选题 · easy

  • A.不增参数扩大感受野← 正确答案
  • B.堆叠大量网络层数
  • C.完全消除过拟合
  • D.自动确定学习率

答案:A。空洞卷积通过拉开权重间距来扩大感受野,参数数量保持不变。增加层数、消除过拟合、自动调学习率都不是它的核心作用。

Q7. 多尺度融合中,使用不同空洞率分支的原因有哪些?

多选题 · hard

  • A.捕获不同尺度目标← 正确答案
  • B.保留高分辨率特征← 正确答案
  • C.让参数量直接归零
  • D.平衡局部与全局信息← 正确答案

答案:ABD。不同 r 对应不同感受野,能同时看到小、中、大目标;不降采样使高分辨率特征得以保留;各分支互补可以平衡细节与语义。多分支并不会让参数量归零,C 明显错误。

Q8. 一个 3×3 空洞卷积 r=2 的参数量与普通 3×3 卷积相比如何?

单选题 · mid

  • A.参数多了一倍
  • B.参数少了一半
  • C.参数完全相同← 正确答案
  • D.参数取决于输入尺寸

答案:C。空洞卷积改变的只是权重分布位置,不是权重个数。9 个权重还是 9 个,和输入尺寸无关,也不受膨胀率影响。

Q9. 关于空洞卷积与池化,下列说法正确的是?

多选题 · hard

  • A.空洞卷积能扩大感受野而不降分辨率← 正确答案
  • B.空洞卷积可以完全替代池化层
  • C.空洞卷积可能漏掉细小目标← 正确答案
  • D.空洞卷积计算量一定明显变小

答案:AC。空洞卷积确实能在保持分辨率的同时扩大感受野;但如果膨胀率过大或设计不当,也会造成网格效应,漏掉细节。它不能完全替代池化,计算量也不一定明显变小。

Q10. 混合空洞卷积 HDC 在设置一组膨胀率时,通常建议满足什么条件?

单选题 · hard

  • A.最大公约数为1← 正确答案
  • B.全部设为偶数
  • C.全部保持相等
  • D.空洞率越大越好

答案:A。当一组膨胀率的最大公约数为 1 时,不同层采样点的错位更丰富,不容易形成棋盘格。全部取偶数或全部相等都会让采样位置周期性重叠,加剧网格效应。