假设你管理一片菜地,菜畦整整齐齐,每棵菜之间相隔半米。想给整片菜地浇水,最省事的办法是拿一块 3×3 的洒水板,贴着地面一块一块地浇。它一次能照顾到的,只有眼前这九个位置;想看更远的菜,就必须站到远处,但中间那些菜就顾不上了。空洞卷积(Dilated Conv)的思路很巧妙:不把洒水板上的九个孔挤在一起,而是把孔距拉开——每隔一格开一个孔。同样的九孔洒水板,覆盖范围从 3×3 一下子变成 5×5,甚至更大。这就是给卷积装上了“可调焦”的视野:孔距越大,看得越远,却不需要增加任何一个孔。 不过,孔距拉得太整齐也有麻烦。如果所有洒水板都用同样的大间隔,浇完一遍,总有一些菜畦被漏掉,留下“棋盘格”一样的干斑。聪明的做法是把不同孔距的洒水板混着用,让每一层漏掉的地方被另一层补上。这篇文章就用“洒水板浇菜地”的故事,把空洞卷积的数学定义、感受野、网格伪影、混合空洞率、多尺度设计以及时序建模一次讲透。

岗位关联

学习空洞卷积,是掌握语义分割、语音生成等高阶模型的钥匙;它教你在不显著增加参数的前提下,把视野从“身边三格”扩展到“整片田”。

目录
  1. 可视化演示
  2. 卷积基础回顾
  3. 空洞卷积定义
  4. 感受野扩展
  5. 网格伪影
  6. 混合空洞卷积
  7. 多尺度层次
  8. 时序因果空洞
  9. 参数配置实战
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

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

标准卷积 (d=1) 感受野:3x3 | 覆盖9个连续像素 扩大感受野需池化或步长 不增加参数即可扩大感受野 等效核大小 = k + (k-1)(d-1) = 3 + 2(d-1) 相比标准卷积需要7层才能达到类似感受野(3^7=2187)>> 空洞卷积可视化...

卷积基础回顾

在菜地这套比喻里,标准卷积就是最朴素的洒水板。它的九个出水孔紧紧挨在一起,滑过一行菜畦时,只读取紧挨着的九个位置:中心点、上、下、左、右以及四个对角。每个出水孔的出水量由一个可学习的权重控制,哪些位置重要,权重就会在训练中变大。

技术世界里,这个洒水板被称为卷积核。输入是一张特征图,卷积核在特征图上按固定步长滑动,每次把窗口内像素值与核权重相乘再相加,得到一个输出值。这个过程叫“局部连接”,因为它只关注一个小邻域;也叫“参数共享”,因为同一块洒水板在整个特征图上重复使用。卷积核覆盖的范围,决定了输出特征的一个点能看到输入图像多大区域,这就是感受野。

标准卷积的局限很明显:要想看更远,只能堆更多层,或者用池化把图缩小。但池化会丢失细节,就像为了看远处,先把整片菜地缩小成一片模糊的绿色。空洞卷积正是为了“看得远又不丢细节”而生的。

y(p)=∑i=−11∑j=−11wi,j x[px+i,  py+j]y(\mathbf p)=\sum_{i=-1}^{1}\sum_{j=-1}^{1}w_{i,j}\,x[p_x+i,\;p_y+j]
这个公式是说:输出位置 p 的值,等于输入在 p 周围 3×3 邻域内所有像素的加权求和。
  1. 输出响应在菜地坐标 p 处放一滴水,需要参考周围九个位置;y(p) 就是这个位置的最终湿度。
    y(p)y(\mathbf p)
  2. 核偏移i 和 j 在 -1、0、1 之间遍历,表示九个出水孔相对中心的相对位置。
    (i,j)∈{−1,0,1}2(i,j)\in\{-1,0,1\}^2
  3. 累加求和把每个孔读到的像素值乘以对应权重,再全部加起来,完成一次局部特征提取。
    ∑i=−11∑j=−11wi,j x[⋅]\sum_{i=-1}^{1}\sum_{j=-1}^{1}w_{i,j}\,x[\cdot]

空洞卷积定义

既然把九孔洒水板的孔距拉开,就能照顾到更远的菜,那卷积为什么不能这样做呢?空洞卷积就是这么做的。它引入了一个新参数:dilation rate,中文叫空洞率或孔距。rate=1 时就是普通卷积;rate=2 时,原来相邻的采样点中间空出一格;rate=3 时,空出两格。孔距越大,洒水板覆盖的菜地范围越大。

数学上,空洞卷积只是在标准卷积的偏移量上乘了一个 rate。假设卷积核大小是 3×3,孔距为 d,那么输出位置会去读取输入上 p + (d·i, d·j) 这些位置的值。实现时并不真的把核放大,而是直接按计算好的偏移去取点,因此参数数量完全不变。

所以,空洞卷积等效于在普通卷积核的权重之间插入 d-1 个 0,得到一个更大的“稀疏卷积核”。但我们不会真的去建那个大核,而是直接跳着取点,既省内存又省计算。

y(p)=∑i=−11∑j=−11wi,j x[px+d i,  py+d j]y(\mathbf p)=\sum_{i=-1}^{1}\sum_{j=-1}^{1}w_{i,j}\,x[p_x+d\,i,\;p_y+d\,j]
这个公式描述了一块“九孔洒水板”如何按孔距 d 跳着浇水。
  1. 孔距参数d 是空洞率,d=1 时就是普通卷积,d=2 时采样点之间隔一格。
    d∈{1,2,3,… }d\in\{1,2,3,\dots\}
  2. 偏移放大原来相邻的核偏移 (i,j) 被放大成 (d·i,d·j),所以洒水板能覆盖更远。
    (d i,  d j)(d\,i,\;d\,j)
  3. 稀疏采样集合rate=2 时,九个采样点的相对坐标变成 {-2,0,2}×{-2,0,2},中间那些位置并没有真正读取。
    {(d i,d j):i,j∈{−1,0,1}}\{(d\,i,d\,j): i,j\in\{-1,0,1\}\}

感受野扩展

感受野可以理解为“某层输出里的一个点,最终能看到输入图像上的多大范围”。普通卷积堆 L 层,感受野呈线性增长;空洞卷积因为孔距 d 的加入,每一层向外推得更远。用洒水板来说,标准洒水板每移动一层只往外多照顾一行的菜;孔距为 2 的洒水板,每层能多照顾两行。

更一般地,如果每一层卷积核大小为 k,孔距为 d,第 t 层对感受野的贡献是 d_t × (k-1)。把所有层的贡献加起来,再加上初始的一个点,就得到总感受野:

举例来说,三层的标准卷积感受野是 1+2+2+2=7;如果三层都用 rate=2,感受野是 1+4+4+4=13。更妙的是,空洞卷积不缩小特征图分辨率,因此语义分割这类需要逐像素分类的任务,能在不丢失细节的情况下看到足够大的上下文。

RL=1+∑t=1Ldt(k−1)R_L=1+\sum_{t=1}^{L}d_t(k-1)
这个公式把“浇菜范围”拆成了每一层洒水板的累计视野。
  1. 初始视野还没有任何卷积时,输出点对应的输入范围可以看作只有 1 个像素。
    R0=1R_0=1
  2. 单层贡献第 t 层的孔距为 d_t,卷积核宽度为 k,它能把上一层的视野向两侧各推 d_t(k-1)/2,加起来贡献 d_t(k-1)。
    ΔRt=dt(k−1)\Delta R_t=d_t(k-1)
  3. 累计视野总感受野等于所有层贡献相加,再加上初始的 1。
    RL=1+∑t=1LΔRtR_L=1+\sum_{t=1}^{L}\Delta R_t

网格伪影

是不是 rate 越大越好?当然不是。想象你把洒水板的孔距调成 2,所有孔都落在偶数格上;再叠一层同样孔距为 2 的洒水板,所有浇水位置依然落在偶数格上。奇数格永远浇不到,菜地就出现了棋盘状的干斑。这就是空洞卷积著名的“网格伪影”。

技术上的解释是:如果多层空洞卷积使用相同或有公倍数的 rate,它们真正采样的坐标会形成固定周期。以 1D 为例,每层可选的采样偏移是 {-d,0,d},多层叠加后的偏移集合为:

网格伪影的可怕之处在于,它不像噪声那样肉眼可见,却会让高层特征丢失周期性分布的信息。尤其在语义分割中,物体边缘会出现规则的“栅栏”或“棋盘”纹理。要消除它,不能只用一种大孔距,而要把不同孔距混起来。

ΩL={∑t=1Litd  |  it∈{−1,0,1}}\Omega_L=\left\{\sum_{t=1}^{L} i_t d \;\middle|\; i_t\in\{-1,0,1\}\right\}
这个集合里的每个数都是 d 的倍数,说明存在大量永远不被采样的位置。
  1. 每层偏移第 t 层只从 {-1,0,1} 里选一个乘数 i_t,乘以公共孔距 d。
    it∈{−1,0,1}i_t\in\{-1,0,1\}
  2. 多层叠加把每一层的偏移相加,得到最终在输入上命中的位置。
    ∑t=1Litd\sum_{t=1}^{L} i_t d
  3. 周期现象因为每一项都能被 d 整除,所以总和一定是 d 的倍数,非倍数位置天然成为盲区。
    ΩL⊆dZ\Omega_L\subseteq d\mathbb{Z}

混合空洞卷积

既然单一 rate 会产生盲区,那就把几种不同孔距的洒水板轮着用。比如第一层用孔距 1,第二层用孔距 2,第三层用孔距 3。这样,第一层漏掉的菜畦,第二层或第三层可能就被浇到了。这就是混合空洞卷积,简称 HDC。

HDC 的核心原则是:一组 rate 的最大公约数应该等于 1,并且不要出现像 2、4、8 这样有清晰倍数的序列。更推荐的是 1、2、3、5 这类“锯齿形”设计,让每层采样的相对位置互相错开。

HDC 并非简单随机挑几个 rate,它还要考虑总感受野是否足够、rate 是否与层深匹配。通常越靠后的层,孔距可以越大,但一定要保证前面层的“洒水范围”能覆盖后面层跳过的间隙。

gcd⁡(d1,d2,…,dn)=1\gcd(d_1,d_2,\dots,d_n)=1
这个公式要求所有孔距之间不存在“公共周期”,从而把空格补全。
  1. 最大公约数gcd 表示一组数里能同时整除它们的最大的数。
    gcd⁡(d1,d2,…,dn)\gcd(d_1,d_2,\dots,d_n)
  2. 等于 1说明这组 rate 没有比 1 更大的公共周期,不会反复跳过同一批位置。
    gcd⁡(⋅)=1\gcd(\cdot)=1
  3. 反例对比gcd(2,4,8)=2,所有采样点都会落在偶数列上,必然产生棋盘伪影;gcd(1,2,3)=1,更安全。
    gcd⁡(2,4,8)=2\gcd(2,4,8)=2

多尺度层次

语义分割中,同一张图片里可能有大象也有蚂蚁,如果只用一种孔距,就像一个只会浇远不浇近的园丁。DeepLab 系列提出的 ASPP(空洞空间金字塔池化)模块,同时布置四块不同孔距的洒水板:孔距 1、6、12、18,让它们平行工作,再把浇水结果拼在一起。

这种“多尺度并行”的好处是:孔距小的分支负责精细的局部纹理,孔距大的分支负责宏观的全局语义。四个分支共享同一输入,最后在通道维度拼接,再通过 1×1 卷积融合,形成一个同时理解远近场景的特征。

层次化设计则是把不同孔距的空洞卷积串联起来,一层一层扩大视野。串联更省参数,但容易累积伪影;并行更稳,但显存开销更大。实际中,DeepLab 会把 ASPP 放在高分辨率特征图的顶端,结合编码器-解码器结构使用。

y=Concat⁡(fd=1(x),  fd=6(x),  fd=12(x),  fd=18(x))y=\operatorname{Concat}\big(f_{d=1}(x),\;f_{d=6}(x),\;f_{d=12}(x),\;f_{d=18}(x)\big)
这个公式表示把四块不同孔距的洒水板同时打开,再把各自动态拼接成一张“全景湿度图”。
  1. 并行分支f_d 表示使用孔距为 d 的空洞卷积处理输入 x。
    fd(x)f_{d}(x)
  2. 通道拼接Concat 把四路输出在通道维度拼在一起,而不是像素相加。
    Concat⁡(⋅)\operatorname{Concat}(\cdot)
  3. 多尺度融合不同 d 对应不同视野,拼接后模型既能看细节,又能看全局。
    {1,6,12,18}\{1,6,12,18\}

时序因果空洞

空洞卷积不只在二维图像上发光,它还能给一维时间序列建模。以 WaveNet 为代表的语音生成模型,需要根据过去的音频样本预测下一个样本。它有两个要求:第一,只能看过去,不能偷看未来;第二,要能记住足够长的历史,否则声音会断断续续。

因果空洞卷积把“洒水板”改成了“单向洒水板”:卷积核只向过去的方向取点。对时间步 t 来说,它读取 t, t-d, t-2d, ... 这些过去的时刻。WaveNet 把 rate 设成 1、2、4、8 倍增,层数加深后,时间感受野呈指数增长。

WaveNet 使用 k=2 的因果空洞卷积,rate 从 1 开始每层翻倍。十层之后,感受野长度达到 1+1×(2^10−1)=1024,可以覆盖约一秒钟的 16kHz 音频。相比循环神经网络,这种结构还能并行计算,训练速度快得多。

y_t=\sum_{i=0}^{k-1} w_i\,x_{t-d_t i},\qquadRF_T=1+\sum_{t=1}^{L}d_t(k-1)
这个公式说明:因果空洞卷积只回看过去,却能靠成倍增大的孔距听到很远的历史。
  1. 因果约束采样索引 i 从 0 到 k-1,不出现负数,因此永远不会读到未来样本。
    i∈{0,1,…,k−1}i\in\{0,1,\dots,k-1\}
  2. 时间跳步rate 为 d_t 时,读取过去的时间点间隔为 d_t。
    t−dtit-d_t i
  3. 时间感受野把所有层的 d_t(k-1) 累加,就是模型能回看的最长历史。
    RFT=1+∑t=1Ldt(k−1)RF_T=1+\sum_{t=1}^{L}d_t(k-1)

参数配置实战

空洞卷积并不是“把 rate 调大就完事”,实际配置需要像设计滴灌系统一样精细。一个常用经验是:先在网络前端做少量下采样,让特征图尺寸降到一个可控范围,再用空洞卷积恢复大感受野,避免从头到尾使用超大分辨率导致显存爆炸。

具体参数选择上,DeepLab 系列是很好的范本。DeepLabV2 使用 ASPP,rate 为 6、12、18、24;DeepLabV3 调整为 6、12、18,并加上全局平均池化分支。这些 rate 都是递增且互质的组合,既覆盖了多尺度,又没有严重的公共周期。实时分割模型则会进一步降低 rate 上限,用 1、2、5 之类的小孔距组合,在速度和精度之间取平衡。

配置时还要检查感受野是否覆盖目标物体。如果希望看到 100×100 像素的大目标,而计算出的感受野只有 30×30,那就需要增加层数或提高 rate;如果感受野已经覆盖全图,继续增大 rate 只会让采样越来越稀疏,反而损害细节。记住一句话:孔距要够大,但别大到“中间全是干斑”。

AI 应用场景

语义分割中的“多孔距洒水板”

阶段:模型架构设计、特征提取

解决的问题:传统语义分割需要大感受野来理解物体上下文,但如果用池化缩小特征图,物体边缘会变得粗糙。空洞卷积在高分辨率特征图上直接扩大感受野,再用 ASPP 并行捕捉多尺度信息,让“大象”和“蚂蚁”都能被识别出来。

具体案例:DeepLabV3+ 在 Cityscapes 街景分割数据集上,用空洞卷积保持 1/8 分辨率的特征图,配合 ASPP 模块,既能看清道路边缘,又能理解整幅街景的布局。

语音合成中的“单向远眺”

阶段:时序建模、生成模型

解决的问题:语音是高度依赖历史的一维信号,普通卷积看不见足够长的过去,循环神经网络又难以并行训练。因果空洞卷积只读过去、不读未来,同时用指数增长的 rate 快速扩大时间感受野。

具体案例:WaveNet 用 10 层因果空洞卷积生成原始音频,一层一层地把 rate 从 1 翻倍到 512,让模型能够感知约 1 秒的音频上下文,生成自然连贯的语音。

实时分割中的“省水方案”

阶段:模型压缩与推理优化

解决的问题:自动驾驶需要实时分割,但高分辨率特征图计算量巨大。使用少量空洞卷积代替多层普通卷积,可以在不增加太多参数的前提下快速扩大视野,并通过混合互质 rate 避免伪影,实现速度与精度的平衡。

具体案例:某些轻量级实时分割模型在主干网络末尾使用 rate 为 1、2、5 的空洞卷积组合,既让每个像素感知到足够上下文,又保持每秒几十帧的推理速度。

Python 演示

python24 行
import numpy as np def dilated_conv2d(x, w, rate=1):    c, h, w_in = x.shape    _, _, kh, kw = w.shape    out_h = h - rate * (kh - 1)    out_w = w_in - rate * (kw - 1)    out = np.zeros((c, out_h, out_w))    for ci in range(c):        for i in range(out_h):            for j in range(out_w):                acc = 0.0                for p in range(kh):                    for q in range(kw):                        acc += w[ci, ci, p, q] * x[ci, i + rate * p, j + rate * q]                out[ci, i, j] = acc    return out if __name__ == "__main__":    x = np.random.randn(1, 9, 9)    kernel = np.random.randn(1, 1, 3, 3)    y = dilated_conv2d(x, kernel, rate=2)    print("输入大小:", x.shape)    print("输出大小:", y.shape)
目的:用纯 Python 循环实现一个最小的空洞卷积,演示 rate=2 时如何跳过中间像素取点。
  1. out_h = h - rate * (kh - 1)输出尺寸缩小程度取决于孔距,rate 越大,边界少算的像素越多。
  2. for p in range(kh)遍历卷积核行,p 是核内行号。
  3. x[ci, i + rate * p, j + rate * q]关键所在:取点时乘上 rate,实现“跳格采样”。
  4. rate=2调用时指定孔距为 2,卷积核实际覆盖 5×5 区域,但只采样 9 个点。
  5. print("输出大小:", y.shape)输入 9×9 时,rate=2 的 3×3 卷积输出为 5×5,符合空洞卷积的尺寸规律。

常见误区

误区我以为空洞卷积 rate 越大,看得越远,所以直接调到 18,感受野不就更牛了吗?

正解rate 越大,采样点之间空隙越大,就像把洒水板孔距拉得过大,中间大片菜地反而浇不到。过大的 rate 会丢失细节,产生网格伪影,甚至让特征图变成几个孤立点的集合。选择 rate 要看目标大小和网络层数,而不是一味求大。

为何常见:大家常把“看得远”等同于“看得好”,忽略了采样密度和感受野之间的平衡。

误区既然空洞卷积既能扩大感受野又能保持分辨率,那就把所有池化层都换成大 rate 空洞卷积吧。

正解空洞卷积确实可以替代一部分下采样,但它不能提供池化的“空间不变性”,也不会减少特征图尺寸。如果彻底不用池化,大分辨率的特征图会让计算量和显存爆炸。工程中通常是少量下采样加空洞卷积,而不是全盘替换。

为何常见:把“视野”和“尺度”混为一谈,忽略了池化还承担着降维和计算优化作用。

误区rate=2 的 3×3 卷积覆盖 5×5,那它岂不是跟 5×5 普通卷积一模一样?

正解两者感受野尺寸相同,但空洞卷积只采样其中的 9 个点,5×5 普通卷积采样 25 个点。空洞卷积相当于在 5×5 核里插入大量 0,信息利用率不同,表达能力也不完全等价。

为何常见:只比较“覆盖范围”,忽略了实际参与计算的像素数量。

误区HDC 不就是随便选几个递增的 rate 吗?我用 2、4、8 也算混合吧。

正解2、4、8 有公因数 2,多层叠加后所有采样点都落在同一周期上,正是网格伪影的典型来源。HDC 要求 rate 之间尽量互质,且设计成 1、2、3、5 这类锯齿形,才能让每层漏掉的位置被其他层补上。

为何常见:只看到“每层感受野变大”,没考虑多层采样位置的周期叠加效应。

面试题

Q1. 空洞卷积中,rate=2 的 3×3 卷积等效覆盖范围是?

单选题 · easy

  • A.3×3 的局部窗口
  • B.5×5 的稀疏窗口← 正确答案
  • C.7×7 的连续窗口
  • D.9×9 的连续窗口

答案:B。rate=2 使核内相邻采样点之间空 1 格,最左到最右跨 4 格,因此覆盖 5×5 范围;但实际只采样其中 9 个点,所以是“稀疏窗口”。

Q2. 相比普通 3×3 卷积,空洞卷积最直接的收益是?

单选题 · mid

  • A.减少可训练参数
  • B.降低显存占用
  • C.扩大感受野← 正确答案
  • D.提高输入分辨率

答案:C。空洞卷积参数个数不变,只是把采样点间隔放大,因此最直接收益是感受野变大,而不是参数或分辨率的改变。

Q3. DeepLab 的 ASPP 模块主要做了什么?

单选题 · mid

  • A.用五种不同尺寸池化
  • B.并行多个不同 rate 的空洞卷积← 正确答案
  • C.将多个全连接层串联
  • D.对输入做随机裁剪拼接

答案:B。ASPP 把 rate=1、6、12、18 的空洞卷积并行作用在同一特征图上,再将结果拼接起来,从而同时获取多尺度上下文。

Q4. 下列哪些属于 HDC 混合空洞卷积的设计要点?

多选题 · mid

  • A.各层 rate 的最大公约数为 1← 正确答案
  • B.避免使用 2、4、8 这种等比序列← 正确答案
  • C.rate 从小到大且与层深匹配← 正确答案
  • D.所有层必须使用相同 rate

答案:ABC。HDC 希望各层采样位置错开覆盖,公约数为 1 才能避开公共周期;等比 2、4、8 容易形成棋盘伪影;所有层用相同 rate 恰恰是问题本身,因此 D 错误。

Q5. 堆叠 4 层 rate=2 的 3×3 空洞卷积,感受野大小为?

单选题 · hard

  • A.9×9
  • B.13×13
  • C.17×17← 正确答案
  • D.33×33

答案:C。每层贡献 (k−1)×d = 2×2 = 4,4 层总贡献 16,再加初始 1 得 17×17。普通 3×3 卷积堆 4 层只有 9×9。

Q6. 网格伪影(棋盘格现象)产生的原因包括?

多选题 · mid

  • A.多层 rate 存在共同周期← 正确答案
  • B.采样点形成固定间隔的错位← 正确答案
  • C.使用 1×1 卷积提升通道
  • D.训练数据全部来自同一分布

答案:AB。当各层 rate 呈倍数关系或有公共因子时,所有有效采样点都落在同一周期上,一些位置被反复采样,另一些永远缺席,因而出现棋盘格。1×1 卷积和数据分布不是伪影的根因。

Q7. 当 stride=1 且 padding 合适时,空洞卷积输出图分辨率会?

单选题 · easy

  • A.强制缩小一半
  • B.变大两倍
  • C.保持不变← 正确答案
  • D.无法预测

答案:C。空洞卷积本身不改变输入输出尺寸关系;只要 padding 按 rate 设置,输出分辨率可以与输入一致,这正是它适合语义分割的关键。

Q8. WaveNet 使用 k=2,rate 序列 1,2,4,…,512,共 10 层,其时间感受野长度约为?

单选题 · hard

  • A.512 个采样点
  • B.1024 个采样点← 正确答案
  • C.2048 个采样点
  • D.5120 个采样点

答案:B。k=2 时每层增加 d×(k−1)=d,总感受野为 1+sum(1+2+…+512)=1024,因此能覆盖约 1024 个过去时间步。

Q9. 适合使用空洞卷积的典型应用有?

多选题 · hard

  • A.语义分割需要高分辨率输出← 正确答案
  • B.语音合成需要长时依赖← 正确答案
  • C.小目标检测仅需要局部纹理
  • D.实时分割模型需要大视野← 正确答案

答案:ABD。语义分割、语音合成、实时分割都要求大感受野且不希望丢失分辨率。小目标检测若只需要局部纹理,没有强上下文需求,空洞卷积的收益不明显。

Q10. 避免伪影时,下列哪组 rate 设计更合理?

单选题 · mid

  • A.2, 4, 8
  • B.4, 2, 8
  • C.1, 2, 3← 正确答案
  • D.8, 8, 8

答案:C。1、2、3 最大公约数为 1,且递增合理,能错开采样周期;2、4、8 和 8、8、8 都会造成公共周期,4、2、8 顺序混乱同样不推荐。