☰
卷积神经网络核心变体全解析:分组、深度可分离、空洞与转置卷积
2026/10/3 13:17:10 网站建设 项目流程

开头

CNN 入门时大家学的都是同一个东西:一个卷积核,在特征图上滑动,对应位置相乘再求和。但真正进到工程里你会发现,光会这一种远不够用。面试时我最喜欢抛的问题是:分组卷积和深度可分离卷积,底层逻辑有什么联系?空洞卷积为什么能在不增加参数的情况下扩大感受野?转置卷积的输出尺寸又是怎么算的?很多人要么只背了公式,要么压根没想过它们其实是同一个家族里的亲戚。

这篇我把标准卷积、分组卷积、深度可分离卷积、空洞卷积、转置卷积这几兄弟放在一起,逐个拆开再对比着讲,顺带把工程里常见的选型思路和踩坑记录也整理进来。适合正在学 CNN、被各种卷积变体绕晕的初学者,也适合做检测、分割、生成模型时不确定该选哪种卷积的工程师。后面还会带一点 1×1 卷积、可变形卷积、门控卷积、3D 卷积和图卷积的快速串联,看完之后你至少能形成自己的判断:这个任务,该用什么卷积。

1. 标准卷积先说透:滑窗、参数和计算量到底怎么算

1.1 卷积的三种等价理解

标准卷积大家最熟的理解是一个小窗口滑过整张特征图,窗口内的像素和卷积核做加权求和,然后滑动到下一个位置。这种理解帮助很大,但工程里我更推荐从另外两个角度看。

第一个角度是“局部全连接”。输出的每个点,其实只连接了输入的局部区域,连接权重就是卷积核里的数字。把它想成一种非常稀疏的全连接层,有助于理解后面为什么分组卷积、深度可分离卷积能省参数量——本质上都是在改“连接方式”。

第二个角度是“矩阵乘法”。把输入特征图按窗口位置展开成一个大矩阵,再把卷积核展开成另一个矩阵,最后的卷积计算就变成了两个矩阵相乘。GPU 和很多加速框架(比如 TensorRT、TVM)实际干的就是这件事。所以平时你听到的 im2col、GEMM,就是这种视角下的产物。

有了这三个视角打底,后面所有变体都不难理解:要么改了连接方式,要么改了采样位置,要么改了输出尺寸的计算规则。

1.2 参数量和计算量的手算公式

标准卷积要先记两个公式,后面所有对比都用得到。假设输入通道数是 C_in,输出通道数是 C_out,卷积核边长是 k,输入特征图高宽是 H、W,stride 为 s,padding 为 p,dilation 为 d。

输出尺寸公式:

H_out = floor((H_in + 2*padding - dilation*(kernel-1) - 1)/stride + 1) W_out 同理

参数量公式:

参数量 = kernel * kernel * C_in * C_out

计算量公式(乘法次数):

FLOPs = kernel * kernel * C_in * C_out * H_out * W_out

这里有个很容易漏的地方:dilation 默认是 1,当它大于 1 时,等效核的大小会变大,所以输出公式里要单独把 dilation 项算进去。很多人自己写网络维度死活对不上,查到最后多半是这里漏了。

举个具体例子,C_in=256,C_out=256,kernel=3,输入 56×56,stride=1,padding=1。参数是 3×3×256×256=589,824,也就是约 59 万个参数。如果输出分辨率也是 56×56,那么这层网络的乘法次数是 589,824×56×56,约 18.5 亿次。这个数字先记着,到深度可分离卷积那一节我们会拿它对比。

1.3 四个痛点引出一堆变体

标准卷积什么问题都有,但问题恰恰是后面所有变体的出发点。

第一,参数和计算量太大。一个 3×3 卷积的参数量是 C_in 和 C_out 相乘,通道数一上去,模型立刻膨胀。于是有了分组卷积、深度可分离卷积。

第二,感受野扩得慢。浅层网络用 3×3 一层层堆,感受野是线性增长的,对于需要大范围上下文的语义分割、语音合成来说不够用。于是有了空洞卷积。

第三,空间分辨率一旦降下来就很难回去。编码器-解码器结构、超分、生成模型都需要把特征图上采样回大尺寸。于是有了转置卷积,以及它的各种替代方案。

第四,连接方式太死板。标准卷积每个输出通道都和全部输入通道相连,但有些任务希望网络自己决定看哪里、怎么融合。于是有了 1×1 卷积、可变形卷积、门控卷积、图卷积这些“非常规”操作。

这四个痛点,就是整篇的索引。下面逐个展开。

2. 分组卷积:不止省算力,还改变信息通路

2.1 分组卷积怎么算:参数直接变成原来的 1/G

分组卷积的做法很简单:把输入通道分成 G 组,每组各自做一次独立的普通卷积,最后在输出通道上拼起来。公式上和标准卷积一一对应:

参数量 = kernel * kernel * (C_in/G) * (C_out/G) * G = kernel * kernel * C_in * C_out / G

也就是说,G 越大,参数量越小。比如 C_in=C_out=256,kernel=3,G=4 时参数量从 589,824 降到 147,456,省了 75%。

但要注意,它跟标准卷积省的不只是参数,还有计算量,因为每组只在对应的通道子集上做卷积,总计算量也是原来的 1/G。所以早期大家用分组卷积的第一动机就是“算不动了,分组顶上”。

可以打个比方:标准卷积相当于一个全能员工负责所有产品的所有工序;分组卷积相当于把产品线分成 G 条流水线,每条流水线只负责一部分通道,工人减少了但各自负责的内容也少了。

2.2 从 AlexNet 到 ResNeXt:分组不是单纯为了省显存

分组卷积第一次大规模进入视野,其实是 AlexNet 时期。当时的 GPU 显存有限,两块卡只能各算一半,于是把通道劈成两组,每组跑一块卡。后来大家发现,这个被迫的“分组”反而带来了一些奇特效果:不同组学到了不同的特征模式,某种程度上起到了类似集成学习的正则化作用。

真正把分组卷积发扬光大的是 ResNeXt。它提出一个叫 cardinality 的概念——就是分组数 G。ResNeXt 的设计思路是:与其把每个 block 里的通道数加宽,不如保持参数量不变,把结构拆成更多组并行子网络。实验证明在同等参数量下,增大 G 往往比加宽通道更有效。

还有一个不太容易被注意的点:分组卷积在现代骨干网络里经常以“CSP 风格”出现,也就是把输入通道拆成两部分,一部分走主分支,一部分直接跳过到后面拼接。YOLOv4 的 CSPDarknet 就是这个思路。它看似和分组卷积不完全一样,但本质上都是在控制信息通路,避免所有通道都无脑全连接。

2.3 channel shuffle 与适用场景

分组卷积有一个明显短板:组与组之间老死不相往来。每一组的输出只来自这一组的输入,通道间没有信息交换。这会导致网络的表达能力被限制,尤其是分组数很大时。

解决办法是 ShuffleNet 提出的 channel shuffle。做法很朴素:把分组卷积的输出通道重新打乱,再送给下一层分组卷积,这样第二层分组时,每一组都能看到来自不同源组的信息。你可以把它理解成“人员轮岗”:上一轮分到 A 组、B 组、C 组的人,下一轮重新混合分配,避免小圈子固化。

工程上我的建议是:如果你只是想让模型更轻量,分组卷积是首选;但一旦分组数超过 8 或者 16,务必考虑是否要配 shuffle 或换用深度可分离卷积。分组太多会带来两个问题,一是通道间信息融合不足,二是后面第 7 章会讲的 MAC(内存访问成本)会变大,实际推理速度未必更好。

3. 深度可分离卷积:MobileNet 系列的命根子与两个坑

3.1 从参数到计算量:为什么省了约 8 倍

深度可分离卷积其实是分组卷积的极端情况。它分成两步。第一步是 depthwise 卷积:每个输入通道单独用一个 k×k 卷积核处理,等价于分组数 G=C_in 的分组卷积。这一步完全不混合跨通道信息。第二步是 pointwise 卷积:用 1×1 卷积把前面的结果在通道维度上重新融合。

参数量公式:

参数量 = kernel * kernel * C_in + C_in * C_out

对比标准卷积:

标准卷积 = kernel * kernel * C_in * C_out

用前面的例子,C_in=C_out=256,kernel=3,深度可分离卷积的参数是:

depthwise: 3*3*256 = 2,304 pointwise: 1*1*256*256 = 65,536 合计: 67,840

标准卷积是 589,824,所以大约省了 8.7 倍。大致比例关系是:

深度可分离 / 标准卷积 ≈ 1/C_out + 1/(kernel^2)

当 C_out 很大时,第一项趋近于 0,核心省的就是 1/(kernel^2)。3×3 卷积等于省到九分之一左右,5×5 卷积省到二十五分之一。这也是为什么 MobileNet 系列用的是 3×3 而不是更大核,核越大省得越多,但精度下降也更明显。

3.2 Depthwise 和 Pointwise 的 BN 与激活放置坑

理论上省了 8 倍参数和时间,但很多人把 MobileNet 里的深度可分离卷积抄走用到自己的网络里,发现效果并没有论文中那么稳定。为什么?因为细节在结构之外的 BN 和激活函数里。

MobileNet V1 的结构是:3×3 depthwise → BN → ReLU,然后 1×1 pointwise → BN → ReLU。问题在于 ReLU 会把信息里小于 0 的部分全部截断,当通道数本来就少的时候,信息损失很严重。MobileNet V2 观察到,在低维空间里做 ReLU 几乎一定会永久丢掉一部分信息,所以提出了倒残差结构:先用 1×1 把通道升上去,比如升 6 倍,再做 3×3 depthwise,最后用 1×1 降维回目标通道,并且降维后不再加 ReLU,只接 BN。这个“降维后不加激活”的设计叫 Linear Bottleneck。

实际工程里,你只要把标准卷积替换成 depthwise+pointwise,却保持原来的“卷积-BN-ReLU”写法,很可能精度就会掉一截。建议照抄 MobileNet V2 的完整顺序:升维 → depthwise → 激活 → 降维 → 无激活,效果会稳很多。

这里放一个 PyTorch 风格的实现,基本等价于 MobileNet V2 的一个倒残差块:

class InvertedResidual(nn.Module): def __init__(self, in_ch, out_ch, stride=1, expand_ratio=6): super().__init__() hidden_ch = in_ch * expand_ratio self.use_shortcut = (stride == 1 and in_ch == out_ch) layers = [] if expand_ratio != 1: layers.append(nn.Conv2d(in_ch, hidden_ch, 1, bias=False)) layers.append(nn.BatchNorm2d(hidden_ch)) layers.append(nn.ReLU6(inplace=True)) layers += [ nn.Conv2d(hidden_ch, hidden_ch, 3, stride, 1, groups=hidden_ch, bias=False), nn.BatchNorm2d(hidden_ch), nn.ReLU6(inplace=True), nn.Conv2d(hidden_ch, out_ch, 1, bias=False), nn.BatchNorm2d(out_ch), ] self.conv = nn.Sequential(*layers) def forward(self, x): if self.use_shortcut: return x + self.conv(x) return self.conv(x)

上面的代码里有几个值得注意的点:depthwise 用groups=hidden_ch实现,每个通道一个核;最后降维的 1×1 卷积后面只有 BN,没有 ReLU;shortcut 只有 stride=1 且通道数一致时才连上。

3.3 MobileNet V2/V3 迭代逻辑

MobileNet V1 的核心贡献就是深度可分离卷积本身,V2 补上了 Linear Bottleneck 和倒残差,V3 又加入了神经架构搜索、SE 模块和 h-swish 激活函数。如果你把这三代模型放在一起对比,会发现在卷积本身的变体上已经没有太大变化了,改进点全在“激活函数放哪”“注意力加在哪”“每个阶段的通道和步长怎么定”这些细节上。

这给我们的启发是:深度可分离卷积本身是个非常成熟的算子,它并不保证 IP 的精度比标准卷积高,只保证用更少的代价换相近的效果。所以做移动端模型时,不要觉得换上它就是必胜,必须同步调整激活、BN、残差连接,甚至后面讲的 MAC 问题,才能真正吃到它的红利。

4. 空洞卷积:白嫖感受野,但小心 gridding 效应

4.1 膨胀率与等效卷积核感受野

空洞卷积的核心是 dilation 参数,也叫膨胀率。它的作用是在卷积核的像素之间插入空格,比如一个 3×3 的卷积核在 dilation=2 时,实际上会覆盖一个 5×5 的区域,但真正参与计算的仍然只有 9 个点,参数量不变。

等效核大小的公式:

kernel_eff = kernel + (kernel - 1) * (dilation - 1)

所以:

  • 3×3 卷积 dilation=1,等效核 3×3
  • 3×3 卷积 dilation=2,等效核 5×5
  • 3×3 卷积 dilation=4,等效核 9×9
  • 3×3 卷积 dilation=8,等效核 17×17

这个“等效核变大但不增加参数量”的特性,在需要大感受野的任务里非常划算。比如语义分割的输入是高分辨率图片,既想要足够大的上下文,又不想因为下采样丢失边界细节,空洞卷积就成了首选。

下面这段代码能帮你验证空洞卷积的输出尺寸,注意 PyTorch 里当 dilation=2 时,要保持输出尺寸不变,padding 也要跟着设成 2:

import torch.nn as nn # 输入 64x64,输出还是 64x64 conv_d2 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=2, dilation=2) conv_d4 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=4, dilation=4)

4.2 典型应用:DeepLab 的 ASPP 与 WaveNet 的时间卷积

空洞卷积最经典的用法是 DeepLab 系列里的 ASPP(空洞空间金字塔池化)。它的做法是几个不同膨胀率的空洞卷积并行,然后把输出拼接起来,相当于同一份特征图用不同大小的“眼睛”同时看,兼顾小目标和大目标。早期版本用的是 dilation=6、12、18 这种递增设计,后来改进版又加了全局平均池化分支,效果更好。

另一个容易被忽略的应用是在语音合成里。WaveNet 做音频生成时,一次要看的时序窗口非常长,普通 1D 卷积根本堆不起那么大的感受野,所以它用了一组 dilation 逐层翻倍的空洞因果卷积。这个思路后来也用在很多时序模型中,比如 TCN。做时间序列预测的朋友,如果发现普通卷积感受野不够,可以先试试空洞卷积,不用动整个网络结构。

堆叠空洞卷积时感受野和普通卷积一样按层累积。比如一层 3×3 dilation=2(等效 5×5)加在标准 3×3 后面,整体感受野是 3 + 5 - 1 = 7×7。如果要算深层网络的感受野,就按每层的等效核尺寸逐层累加即可。

4.3 gridding 效应与膨胀率组合

空洞卷积有个著名的坑叫 gridding artifact,中文一般叫网格效应。现象是当你连续多层使用相同膨胀率,比如连续三个 3×3 dilation=2 的卷积,模型学出来的特征图会出现蜂窝状或者棋盘格的纹理,某些位置的信息根本没被覆盖到。

原因是这样的:连续 dilation=2 的卷积,等效于在一个大区域里隔点采样,层与层之间采样点有规律地重叠或错过,导致有一些像素始终没有梯度流入,变成了“盲点”。这在人脸关键点、分割、检测这类对空间细节敏感的任务里影响很大。

怎么避免?我建议直接用 HDC(混合膨胀卷积)的思路:不要所有层都一样,把膨胀率设计成锯齿状,比如 1、2、3、1、2、3,或者 1、2、5、9,让不同层的采样格子尽量错开,这样才能覆盖完整区域。下面用表格直观对比一下:

连续两层 3×3 卷积的 dilation 组合等效感受野是否有网格盲点说明
1, 15×5无普通卷积
2, 29×9有典型 gridding 问题
1, 27×7无混合设计,覆盖更均匀
1, 2, 313×13基本无HDC 建议的组合方式

实际操作中,如果你不得不在大感受野和完整覆盖之间做取舍,优先用“小膨胀率起步,后面适当增大”的组合。不要一上来就全部 dilation=2 堆到底,这个坑我踩过几次,训练曲线一开始看着挺好,到后期 loss 降不下去,最后定位到是空洞卷积的组合问题。

5. 转置卷积:上采样神器与棋盘格问题

5.1 两种视角看转置卷积:上采样与矩阵转置

转置卷积这个名字容易让人误解,很多人也叫它反卷积,但这个叫法不严谨,因为它不是普通卷积的逆运算。假设标准卷积可以用一个大的权重矩阵 W 表示,前向计算是 y = Wx,那么转置卷积干的事相当于 y = W^T x,也就是把同一个 W 转置后作用在输入上,所以叫“转置卷积”更准确。

直观理解上采样视角:普通卷积是把一个周围区域“浓缩”成一个点,转置卷积则把一个点“铺开”到一个区域。它的具体做法是先在输入特征图的每个像素周围补零,再做一次标准卷积。因此你可以理解为:转置卷积 = 插零 + 标准卷积。

PyTorch 里的 API 是nn.ConvTranspose2d,新手最容易搞混的地方是它的参数含义和nn.Conv2d完全不同。普通卷积的 padding 是让输出变小多少,转置卷积的 padding 是让输出收敛多少,padding 越大,输出反而越小,这个方向要理解反。

5.2 维度变化与 output_padding 到底怎么用

转置卷积输出尺寸的公式:

H_out = (H_in - 1) * stride - 2 * padding + dilation * (kernel - 1) + output_padding + 1

这里面的output_padding是转置卷积独有的参数,最容易让人产生困惑。它的作用不是真的在输出后面补像素,而是当尺寸计算不能整除时,用来修正输出大小,让最终输出尺寸正好是你想要的。

做上采样时最常用的两种配置:

  • kernel=2, stride=2, padding=0, output_padding=0,可以把 H×W 变成 2H×2W。输入 4×4,输出就是 8×8。
  • kernel=3, stride=2, padding=1, output_padding=1,同样可以把 H×W 变成 2H×2W。

对应的 PyTorch 写法:

# 方式一:kernel 大小等于 stride nn.ConvTranspose2d(64, 32, kernel_size=2, stride=2) # 方式二:kernel 为奇数,需要额外设置 padding 和 output_padding nn.ConvTranspose2d(64, 32, kernel_size=3, stride=2, padding=1, output_padding=1)

送大家一个经验法则:当 kernel_size、stride、padding 三者的奇偶性不同时,输出尺寸很容易差 1 像素。这时不要硬调整输入尺寸,优先考虑改output_padding。它不会增加太多计算量,却能把 shape 对齐问题一次性解决。

5.3 棋盘格效应怎么破

转置卷积最大的视觉问题是棋盘格伪影,尤其在图像生成任务中特别明显。成因是卷积核对不同位置的贡献重叠程度不一致,有的位置被叠加多次,有的位置只被叠加一次,就形成了周期性的明暗差异。stride 越大,kernel 又不能被 stride 整除时,这种重叠不均匀越严重。

举一个具体的例子:stride=2、kernel=3 的转置卷积,在输出上会出现“每个 2×2 小块里亮暗交替”的模式。stride=2、kernel=2 则没有这个问题,因为每个位置重叠次数完全相同。

工程上我的解决方案有三个层次:

第一,优先把 kernel 设置成 stride 的整数倍,比如 2×2 配 stride=2,或者 4×4 配 stride=2,这能从根上减少棋盘格。

第二,换成“插值 + 普通卷积”。先双线性插值把特征图放大到目标尺寸,再过一个 3×3 标准卷积。这种方法在很多分割、超分网络里效果反而比转置卷积更稳。

第三,用 PixelShuffle,也就是 sub-pixel convolution。它的思路是先用普通卷积把通道数变成原来的 r² 倍,再通过重排把通道上的信息平铺到空间上。超分辨率任务里几乎默认用它,图像生成也经常会选它而不是转置卷积。

我自己在生成模型里的习惯是:能用 PixelShuffle 就不用转置卷积,如果网络结构已经写死只能加转置卷积,那就至少用 kernel=2、stride=2 这种可整除组合,再在后面接一个普通卷积层或残差块来抹平重叠不均。

6. 其它常见变体快速串一遍:1×1、可变形、门控、3D、图卷积

6.1 1×1 卷积:最不起眼但最常用

1×1 卷积又叫 pointwise 卷积,它不做任何空间上的采样,只是把每个位置的通道重新线性组合一遍。参数量是 C_in×C_out,和空间尺寸完全无关。它最大的价值有三个:降通道、升通道、跨通道融合。ResNet 的 bottleneck、注意力机制里的通道压缩、MobileNet 的第二阶段,全都要靠它。

1×1 卷积本质上就是“对通道做全连接”,这也是为什么很多网络结构在最后用全局池化接全连接层,但它又不丢失空间位置信息。工程中如果你发现某层网络通道数太多导致计算量爆炸,先用 1×1 把通道压下去,再接大核卷积,往往是性价比最高的改法。

6.2 可变形卷积与门控卷积:让网络自己调整采样和门控

可变形卷积(Deformable Convolution)的思路是:不再用固定的矩形网格采样,而是让网络自己学习每个采样点的偏移量。它特别适合目标存在形变的任务,比如人体姿态、工业缺陷检测里的不规则目标。代价是需要额外一套卷积来预测偏移量,显存和运行时间都会增加。DCN v2 在 v1 基础上增加了可学习的采样权重,效果更稳定,但工程部署会更麻烦。

门控卷积(Gated Convolution)是图像修复任务里很受欢迎的一个结构。它的计算公式可以简单理解成两个分支:一个分支学“内容”,一个分支学“门控权重”,最后按元素相乘。公式可以写成:

output = sigmoid(conv_gate(x)) * conv_value(x)

门控卷积的好处是网络能自适应控制哪些位置的信息该保留、该放大,哪些位置该抑制。图像修复里经常需要处理不规则遮挡,普通卷积会把遮挡区域的信息也混进来,门控卷积就能学到对遮挡区域自动“关门”。这类思路也被引入了语音合成、语言模型等任务中。

如果你在代码里看到有人把一个卷积层的输出接 Sigmoid,再与另一个卷积层的输出逐元素相乘,那就是门控卷积的常见实现。

6.3 3D 卷积与图卷积:处理视频、点云和图结构

3D 卷积把 2D 卷积的滑窗扩展到了 3 个维度,适合视频行为识别、医学影像、体素数据这类有空间深度或时间维度的输入。早期 C3D、I3D 等网络用的就是这种结构。缺点同样明显:参数和计算量都会暴涨,因为核从 k×k 变成了 k×k×k。工程上见到 3D 卷积自编码器,一般是拿来做视频或体数据的无监督重建和特征提取,但如果没有很强的 GPU 资源,建议先用 2D 卷积逐帧处理,再在时间维上做融合,否则很容易把显存烧穿。

图卷积(Graph Convolutional Network,GCN)处理的是非欧几里得数据,比如社交网络、分子结构、推荐系统里的用户物品图。它的核心操作可以理解成“消息传递”:每个节点的特征,通过聚合邻居节点的特征来更新自己。空间域的做法很像把卷积变成“只对邻接节点做加权求和”。在图像这种网格数据上,图卷积一般没有优势,但在真正的图结构数据上,它是一个绕不过去的基础模型。还有一些论文尝试把正方形卷积核改成三角、带状等特殊形状,针对特定形态特征设计,这类工作研究价值不小,但工程落地相对少,暂时了解即可。

7. 工程实战经验:维度公式、性能瓶颈与问题速查表

7.1 输出尺寸对不上时的排查套路

Shape 报错是卷积系列问题里最常见的。我的排查顺序是先把两个公式抄下来:

普通卷积输出:

H_out = floor((H_in + 2*padding - dilation*(kernel-1) - 1)/stride + 1)

转置卷积输出:

H_out = (H_in - 1)*stride - 2*padding + dilation*(kernel-1) + output_padding + 1

然后逐项核对这五个参数:kernel、stride、padding、dilation、output_padding。很多人的错误都出在 padding 上。普通卷积想要保持尺寸不变,kernel=3 时 padding=1,kernel=5 时 padding=2。但一旦加了 dilation,padding 必须跟着扩大,kernel=3、dilation=2 时想保持尺寸不变,padding 要设成 2,而不是 1。

如果是多层叠加之后的 mismatch,先切到单层用随机张量测试,逐层打印 shape,很快就能定位到具体哪一层出了问题。

7.2 模型变慢但算力没涨:MAC 与访存问题

这是一个非常隐形的坑。你把模型的 FLOPs 算下来明明降了很多,但实际推理时间反而变长了,尤其在 GPU 上。原因在内存访问成本(MAC)。

ShuffleNet V2 那篇论文里有一个著名结论:内存访问成本和分组数相关,分组越多,MAC 越高。同样是 1 FLOPs,分组卷积和深度可分离卷积因为需要频繁读写分组后的特征图,访存开销会比标准卷积大。GPU 上这些算子也可能没有像普通卷积那样有 cuDNN 级别的深度优化,实际跑起来经常到不了理论加速比。

所以我对团队的要求是:衡量一个卷积改动好不好,不要只看 FLOPs,要看实际延迟。移动端 CPU 上深度可分离卷积通常收益明显;服务端大 GPU 上如果模型已经不小了,深度可分离的收益会打折扣,甚至可能变慢。这时候可以尝试把标准卷积和深度可分离卷积混合使用,只在通道数高的层用深度可分离,低通道层保留标准卷积,折中效果常常比极端替换更好。

7.3 常用卷积变体速查表

最后放一张速查表,方便你平时选型和核对:

卷积类型核心参数参数量变化输出尺寸变化典型场景
标准卷积kernel, stride, padding基线按公式缩小通用特征提取
1×1 卷积C_in, C_out很小,与空间无关不变通道升降维、跨通道融合
分组卷积groups=G标准卷积的 1/G同标准卷积轻量模型、多分支并行、ResNeXt
深度可分离卷积depthwise + pointwise约 1/C_out + 1/k²主要看 depthwise 的 strideMobileNet 系列、移动端
空洞卷积dilation=d不变padding=d 时尺寸不变分割、检测、时序建模、大感受野
转置卷积stride, output_padding较快,依赖 kernel按公式放大上采样、生成网络
可变形卷积offset 网络增加少量同普通卷积形变目标、姿态估计
门控卷积双分支约 2 倍同普通卷积图像修复、语音生成
3D 卷积kernel 增加一维大幅增加时空同时缩小视频、医学影像、体数据
图卷积邻接矩阵聚合取决于图结构节点数不变社交网络、分子、推荐系统

这张表不用死记,真正需要决定的时候回来翻一下即可。

我个人实际选型时一般会这样拍脑袋:移动端优先深度可分离加少量分组,分割或高分辨率任务先用空洞卷积把骨干感受野撑起来,生成模型里的上采样尽量用 PixelShuffle,实在需要转置卷积也要保证 kernel 能被 stride 整除。遇到替换后精度波动不用慌,先把激活函数和 BN 位置对齐,再检查 padding、dilation 是否同步调整。踩过几次坑之后你会形成一种直觉:卷积家族看着花样多,拆分下来无非是通道怎么连接、采样格子怎么排、特征图尺寸怎么变这三件事。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询