卷积基础回顾:标准卷积、深度可分离卷积、分组卷积的原理与计算量对比
说实话,很多做轻量化模型的朋友,一上来就搞什么 MobileNet、ShuffleNet,结果连最基础的卷积变体都说不清楚。我个人觉得,搞懂这三种卷积,就像学功夫要先扎马步一样重要。今天咱们就掰开揉碎了聊聊。
一、标准卷积:最朴素的“全连接”式扫描
标准卷积,说白了就是用一个固定大小的窗口,在输入特征图上滑来滑去。每个窗口内的像素,都和卷积核里的每个权重做乘法,然后累加。
举个例子,输入是 H×W×C_in,卷积核是 K×K,输出通道是 C_out。那计算量是多少?
计算量 = H × W × C_in × C_out × K × K
嗯,这里要注意,这个公式是假设 stride=1、padding 合适的情况。我在项目中遇到过,很多人算计算量时忘了乘 H×W,结果模型跑起来才发现 FLOPs 爆炸。
核心特点:每个输出通道都和所有输入通道做卷积。说白了就是“全连接”式的空间-通道联合处理。
二、深度可分离卷积:把一件事拆成两步做
深度可分离卷积,我习惯叫它“偷懒卷积”。它把标准卷积拆成了两步:
- 深度卷积(Depthwise Conv):每个输入通道单独用一个卷积核处理,通道之间不交流。
- 逐点卷积(Pointwise Conv):用 1×1 卷积把通道信息融合起来。
你想想看,这样一拆,计算量立马就降下来了。
深度卷积计算量 = H × W × C_in × K × K
逐点卷积计算量 = H × W × C_in × C_out × 1 × 1
总计算量 = H × W × C_in × (K×K + C_out)
对比标准卷积,计算量比例大约是:
比例 = (K×K + C_out) / (C_out × K×K)
当 C_out 很大时,这个比例接近 1/C_out。说白了就是计算量能降到原来的几十分之一。
我的经验:我曾经在 MobileNetV1 的部署中踩过坑——深度卷积虽然计算量小,但内存访问更频繁,实际推理速度不一定线性下降。所以别光看 FLOPs,还得看硬件特性。
三、分组卷积:把通道分成几组来干
分组卷积,其实就是标准卷积的一个变种。把输入通道分成 G 组,每组独立做标准卷积。每组输出通道数是 C_out/G。
计算量公式:
每组计算量 = H × W × (C_in/G) × (C_out/G) × K × K
总计算量 = G × 每组计算量 = H × W × C_in × C_out × K × K / G
你看,计算量直接除以 G。这就是为什么 ShuffleNet 喜欢用分组卷积——便宜啊。
避坑指南:我曾经在某个项目里把分组数设得太大,结果组间信息完全不流通,模型精度掉得一塌糊涂。后来加了通道混洗(Channel Shuffle)才救回来。分组卷积不是万能的,组数太多会导致信息孤岛。
四、三种卷积的对比表格
| 卷积类型 | 计算量公式 | 参数量 | 特点 |
|---|---|---|---|
| 标准卷积 | H×W×C_in×C_out×K² | C_in×C_out×K² | 通道全连接,计算量大 |
| 深度可分离卷积 | H×W×C_in×(K²+C_out) | C_in×K² + C_in×C_out | 计算量小,适合移动端 |
| 分组卷积 | H×W×C_in×C_out×K²/G | C_in×C_out×K²/G | 计算量可控,需注意组间通信 |
五、核心逻辑结构图
下面这张图,我画出了三种卷积的核心逻辑。你看一眼就能明白它们的区别。
六、实际项目中的选择建议
说实话,没有最好的卷积,只有最合适的。我一般会这样选:
- 追求极致精度:标准卷积,没得商量。但要注意控制通道数。
- 移动端部署:深度可分离卷积是首选。MobileNet 系列就是最好的例子。
- 通道数特别大:分组卷积。比如 ResNeXt 里用 32 组,效果就很不错。
- 混合使用:我经常在网络的浅层用标准卷积,深层用深度可分离卷积。这样精度和速度都能兼顾。
一个小技巧:如果你不确定用哪种,可以先跑一个标准卷积的 baseline,然后逐层替换成轻量卷积,观察精度变化。这样能精准定位哪些层可以“偷懒”。
好了,卷积基础就聊到这儿。这三种卷积是后续所有轻量 Transformer 和卷积融合的基础,搞懂了它们,后面讲什么 MobileViT、EfficientFormer 你就不会懵了。
可可精品资料库