ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

卷积神经网络核心变体全解析:分组、深度可分离、空洞与转置卷积

卷积神经网络核心变体全解析:分组、深度可分离、空洞与转置卷积 开头CNN 入门时大家学的都是同一个东西一个卷积核在特征图上滑动对应位置相乘再求和。但真正进到工程里你会发现光会这一种远不够用。面试时我最喜欢抛的问题是分组卷积和深度可分离卷积底层逻辑有什么联系空洞卷积为什么能在不增加参数的情况下扩大感受野转置卷积的输出尺寸又是怎么算的很多人要么只背了公式要么压根没想过它们其实是同一个家族里的亲戚。这篇我把标准卷积、分组卷积、深度可分离卷积、空洞卷积、转置卷积这几兄弟放在一起逐个拆开再对比着讲顺带把工程里常见的选型思路和踩坑记录也整理进来。适合正在学 CNN、被各种卷积变体绕晕的初学者也适合做检测、分割、生成模型时不确定该选哪种卷积的工程师。后面还会带一点 1×1 卷积、可变形卷积、门控卷积、3D 卷积和图卷积的快速串联看完之后你至少能形成自己的判断这个任务该用什么卷积。1. 标准卷积先说透滑窗、参数和计算量到底怎么算1.1 卷积的三种等价理解标准卷积大家最熟的理解是一个小窗口滑过整张特征图窗口内的像素和卷积核做加权求和然后滑动到下一个位置。这种理解帮助很大但工程里我更推荐从另外两个角度看。第一个角度是“局部全连接”。输出的每个点其实只连接了输入的局部区域连接权重就是卷积核里的数字。把它想成一种非常稀疏的全连接层有助于理解后面为什么分组卷积、深度可分离卷积能省参数量——本质上都是在改“连接方式”。第二个角度是“矩阵乘法”。把输入特征图按窗口位置展开成一个大矩阵再把卷积核展开成另一个矩阵最后的卷积计算就变成了两个矩阵相乘。GPU 和很多加速框架比如 TensorRT、TVM实际干的就是这件事。所以平时你听到的 im2col、GEMM就是这种视角下的产物。有了这三个视角打底后面所有变体都不难理解要么改了连接方式要么改了采样位置要么改了输出尺寸的计算规则。1.2 参数量和计算量的手算公式标准卷积要先记两个公式后面所有对比都用得到。假设输入通道数是 C_in输出通道数是 C_out卷积核边长是 k输入特征图高宽是 H、Wstride 为 spadding 为 pdilation 为 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_in256C_out256kernel3输入 56×56stride1padding1。参数是 3×3×256×256589,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_inC_out256kernel3G4 时参数量从 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 卷积核处理等价于分组数 GC_in 的分组卷积。这一步完全不混合跨通道信息。第二步是 pointwise 卷积用 1×1 卷积把前面的结果在通道维度上重新融合。参数量公式参数量 kernel * kernel * C_in C_in * C_out对比标准卷积标准卷积 kernel * kernel * C_in * C_out用前面的例子C_inC_out256kernel3深度可分离卷积的参数是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。实际工程里你只要把标准卷积替换成 depthwisepointwise却保持原来的“卷积-BN-ReLU”写法很可能精度就会掉一截。建议照抄 MobileNet V2 的完整顺序升维 → depthwise → 激活 → 降维 → 无激活效果会稳很多。这里放一个 PyTorch 风格的实现基本等价于 MobileNet V2 的一个倒残差块class InvertedResidual(nn.Module): def __init__(self, in_ch, out_ch, stride1, expand_ratio6): 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, biasFalse)) layers.append(nn.BatchNorm2d(hidden_ch)) layers.append(nn.ReLU6(inplaceTrue)) layers [ nn.Conv2d(hidden_ch, hidden_ch, 3, stride, 1, groupshidden_ch, biasFalse), nn.BatchNorm2d(hidden_ch), nn.ReLU6(inplaceTrue), nn.Conv2d(hidden_ch, out_ch, 1, biasFalse), 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 用groupshidden_ch实现每个通道一个核最后降维的 1×1 卷积后面只有 BN没有 ReLUshortcut 只有 stride1 且通道数一致时才连上。3.3 MobileNet V2/V3 迭代逻辑MobileNet V1 的核心贡献就是深度可分离卷积本身V2 补上了 Linear Bottleneck 和倒残差V3 又加入了神经架构搜索、SE 模块和 h-swish 激活函数。如果你把这三代模型放在一起对比会发现在卷积本身的变体上已经没有太大变化了改进点全在“激活函数放哪”“注意力加在哪”“每个阶段的通道和步长怎么定”这些细节上。这给我们的启发是深度可分离卷积本身是个非常成熟的算子它并不保证 IP 的精度比标准卷积高只保证用更少的代价换相近的效果。所以做移动端模型时不要觉得换上它就是必胜必须同步调整激活、BN、残差连接甚至后面讲的 MAC 问题才能真正吃到它的红利。4. 空洞卷积白嫖感受野但小心 gridding 效应4.1 膨胀率与等效卷积核感受野空洞卷积的核心是 dilation 参数也叫膨胀率。它的作用是在卷积核的像素之间插入空格比如一个 3×3 的卷积核在 dilation2 时实际上会覆盖一个 5×5 的区域但真正参与计算的仍然只有 9 个点参数量不变。等效核大小的公式kernel_eff kernel (kernel - 1) * (dilation - 1)所以3×3 卷积 dilation1等效核 3×33×3 卷积 dilation2等效核 5×53×3 卷积 dilation4等效核 9×93×3 卷积 dilation8等效核 17×17这个“等效核变大但不增加参数量”的特性在需要大感受野的任务里非常划算。比如语义分割的输入是高分辨率图片既想要足够大的上下文又不想因为下采样丢失边界细节空洞卷积就成了首选。下面这段代码能帮你验证空洞卷积的输出尺寸注意 PyTorch 里当 dilation2 时要保持输出尺寸不变padding 也要跟着设成 2import torch.nn as nn # 输入 64x64输出还是 64x64 conv_d2 nn.Conv2d(256, 256, kernel_size3, stride1, padding2, dilation2) conv_d4 nn.Conv2d(256, 256, kernel_size3, stride1, padding4, dilation4)4.2 典型应用DeepLab 的 ASPP 与 WaveNet 的时间卷积空洞卷积最经典的用法是 DeepLab 系列里的 ASPP空洞空间金字塔池化。它的做法是几个不同膨胀率的空洞卷积并行然后把输出拼接起来相当于同一份特征图用不同大小的“眼睛”同时看兼顾小目标和大目标。早期版本用的是 dilation6、12、18 这种递增设计后来改进版又加了全局平均池化分支效果更好。另一个容易被忽略的应用是在语音合成里。WaveNet 做音频生成时一次要看的时序窗口非常长普通 1D 卷积根本堆不起那么大的感受野所以它用了一组 dilation 逐层翻倍的空洞因果卷积。这个思路后来也用在很多时序模型中比如 TCN。做时间序列预测的朋友如果发现普通卷积感受野不够可以先试试空洞卷积不用动整个网络结构。堆叠空洞卷积时感受野和普通卷积一样按层累积。比如一层 3×3 dilation2等效 5×5加在标准 3×3 后面整体感受野是 3 5 - 1 7×7。如果要算深层网络的感受野就按每层的等效核尺寸逐层累加即可。4.3 gridding 效应与膨胀率组合空洞卷积有个著名的坑叫 gridding artifact中文一般叫网格效应。现象是当你连续多层使用相同膨胀率比如连续三个 3×3 dilation2 的卷积模型学出来的特征图会出现蜂窝状或者棋盘格的纹理某些位置的信息根本没被覆盖到。原因是这样的连续 dilation2 的卷积等效于在一个大区域里隔点采样层与层之间采样点有规律地重叠或错过导致有一些像素始终没有梯度流入变成了“盲点”。这在人脸关键点、分割、检测这类对空间细节敏感的任务里影响很大。怎么避免我建议直接用 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 建议的组合方式实际操作中如果你不得不在大感受野和完整覆盖之间做取舍优先用“小膨胀率起步后面适当增大”的组合。不要一上来就全部 dilation2 堆到底这个坑我踩过几次训练曲线一开始看着挺好到后期 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是转置卷积独有的参数最容易让人产生困惑。它的作用不是真的在输出后面补像素而是当尺寸计算不能整除时用来修正输出大小让最终输出尺寸正好是你想要的。做上采样时最常用的两种配置kernel2, stride2, padding0, output_padding0可以把 H×W 变成 2H×2W。输入 4×4输出就是 8×8。kernel3, stride2, padding1, output_padding1同样可以把 H×W 变成 2H×2W。对应的 PyTorch 写法# 方式一kernel 大小等于 stride nn.ConvTranspose2d(64, 32, kernel_size2, stride2) # 方式二kernel 为奇数需要额外设置 padding 和 output_padding nn.ConvTranspose2d(64, 32, kernel_size3, stride2, padding1, output_padding1)送大家一个经验法则当 kernel_size、stride、padding 三者的奇偶性不同时输出尺寸很容易差 1 像素。这时不要硬调整输入尺寸优先考虑改output_padding。它不会增加太多计算量却能把 shape 对齐问题一次性解决。5.3 棋盘格效应怎么破转置卷积最大的视觉问题是棋盘格伪影尤其在图像生成任务中特别明显。成因是卷积核对不同位置的贡献重叠程度不一致有的位置被叠加多次有的位置只被叠加一次就形成了周期性的明暗差异。stride 越大kernel 又不能被 stride 整除时这种重叠不均匀越严重。举一个具体的例子stride2、kernel3 的转置卷积在输出上会出现“每个 2×2 小块里亮暗交替”的模式。stride2、kernel2 则没有这个问题因为每个位置重叠次数完全相同。工程上我的解决方案有三个层次第一优先把 kernel 设置成 stride 的整数倍比如 2×2 配 stride2或者 4×4 配 stride2这能从根上减少棋盘格。第二换成“插值 普通卷积”。先双线性插值把特征图放大到目标尺寸再过一个 3×3 标准卷积。这种方法在很多分割、超分网络里效果反而比转置卷积更稳。第三用 PixelShuffle也就是 sub-pixel convolution。它的思路是先用普通卷积把通道数变成原来的 r² 倍再通过重排把通道上的信息平铺到空间上。超分辨率任务里几乎默认用它图像生成也经常会选它而不是转置卷积。我自己在生成模型里的习惯是能用 PixelShuffle 就不用转置卷积如果网络结构已经写死只能加转置卷积那就至少用 kernel2、stride2 这种可整除组合再在后面接一个普通卷积层或残差块来抹平重叠不均。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 NetworkGCN处理的是非欧几里得数据比如社交网络、分子结构、推荐系统里的用户物品图。它的核心操作可以理解成“消息传递”每个节点的特征通过聚合邻居节点的特征来更新自己。空间域的做法很像把卷积变成“只对邻接节点做加权求和”。在图像这种网格数据上图卷积一般没有优势但在真正的图结构数据上它是一个绕不过去的基础模型。还有一些论文尝试把正方形卷积核改成三角、带状等特殊形状针对特定形态特征设计这类工作研究价值不小但工程落地相对少暂时了解即可。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 上。普通卷积想要保持尺寸不变kernel3 时 padding1kernel5 时 padding2。但一旦加了 dilationpadding 必须跟着扩大kernel3、dilation2 时想保持尺寸不变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很小与空间无关不变通道升降维、跨通道融合分组卷积groupsG标准卷积的 1/G同标准卷积轻量模型、多分支并行、ResNeXt深度可分离卷积depthwise pointwise约 1/C_out 1/k²主要看 depthwise 的 strideMobileNet 系列、移动端空洞卷积dilationd不变paddingd 时尺寸不变分割、检测、时序建模、大感受野转置卷积stride, output_padding较快依赖 kernel按公式放大上采样、生成网络可变形卷积offset 网络增加少量同普通卷积形变目标、姿态估计门控卷积双分支约 2 倍同普通卷积图像修复、语音生成3D 卷积kernel 增加一维大幅增加时空同时缩小视频、医学影像、体数据图卷积邻接矩阵聚合取决于图结构节点数不变社交网络、分子、推荐系统这张表不用死记真正需要决定的时候回来翻一下即可。我个人实际选型时一般会这样拍脑袋移动端优先深度可分离加少量分组分割或高分辨率任务先用空洞卷积把骨干感受野撑起来生成模型里的上采样尽量用 PixelShuffle实在需要转置卷积也要保证 kernel 能被 stride 整除。遇到替换后精度波动不用慌先把激活函数和 BN 位置对齐再检查 padding、dilation 是否同步调整。踩过几次坑之后你会形成一种直觉卷积家族看着花样多拆分下来无非是通道怎么连接、采样格子怎么排、特征图尺寸怎么变这三件事。
返回列表