一、前言:为什么会出现深度可分离卷积?
在卷积神经网络(CNN)早期阶段(如 VGG、ResNet),我们通常使用标准卷积(Standard Convolution) 。
虽然这种操作能有效提取空间特征和通道特征,但计算量极大,尤其在移动端或嵌入式设备上难以部署。
核心矛盾:
想提取更多特征 → 卷积核越多 → 参数量激增
想减少计算量 → 卷积层变浅 → 表达能力下降
为解决这种"性能与效率"的矛盾,Google 在 MobileNet(2017) 中提出了 深度可分离卷积(Depthwise Separable Convolution) ,它将传统卷积分解为两步:
"空间卷积" + "通道融合",在保持精度的同时极大地降低了计算量。
二、标准卷积回顾
设输入特征图尺寸为:
输出特征图为:
卷积核大小为 ( )。
标准卷积的输出第 ( j ) 个通道计算为:
其中 ( )。
🧮 参数量与计算量:
-
参数量:
-
计算量(FLOPs):
显然,参数和计算量都与输入通道和输出通道呈乘积关系 ,当 ( )、(
) 较大时,计算代价极其高。
三、深度卷积(Depthwise Convolution)
3.1 数学定义
深度卷积的思想是:
"每个输入通道单独做卷积",不再跨通道混合。
即对每个输入通道 ( ) 仅使用一个卷积核 (
):
其中 ( )。
这样,输出通道数 = 输入通道数。
3.2 参数量分析
相比标准卷积:参数减少
3.3 计算量
计算量随通道线性增长,而非二次增长。
四、逐点卷积(Pointwise Convolution)
4.1 数学定义
逐点卷积就是 1×1 卷积,它的作用是:
将前一步的深度卷积结果进行通道融合与线性变换。
此时卷积核尺寸为 ( )。
4.2 参数量与计算量
-
参数量:
-
计算量:
五、深度可分离卷积整体结构(DW + PW)
深度可分离卷积将标准卷积分为两步:
-
Depthwise Conv:独立提取每个通道的空间特征;
-
Pointwise Conv:1×1卷积混合通道特征,生成新通道组合。
🧮 参数与计算量总和:
与标准卷积相比:
\\text{计算量比} = \\frac{F_{DSC}}{F_{standard}} = \\frac{1}{C_{out}} + \\frac{1}{K\^2}
例如当 ( K=3,
) 时:
即 仅需约 12% 的计算量!
六、MobileNet 中的应用
6.1 结构替换思想
MobileNet V1(2017)首次全面采用深度可分离卷积:
Standard Conv → Depthwise Conv + Pointwise Conv
每一层替换后,网络结构示意:
Input → DWConv → BN → ReLU → PWConv → BN → ReLU → Output
6.2 实际效果
| 模型 | Top-1 精度 | 计算量(FLOPs) | 参数量 | 相比ResNet加速 |
|---|---|---|---|---|
| VGG-16 | 71.5% | 15.3B | 138M | ×1 |
| MobileNet V1 | 70.6% | 0.57B | 4.2M | ≈27倍更快 |
深度可分离卷积虽然略损精度,但换来了数量级的效率提升,尤其适合移动端、嵌入式平台。
七、PyTorch 实现(两种方式)
7.1 使用 groups 参数实现 Depthwise
python
import torch
import torch.nn as nn
# 深度卷积 + 逐点卷积 实现
class DepthwiseSeparableConv(nn.Module):
def __init__(self, in_ch, out_ch, kernel_size=3, stride=1, padding=1):
super().__init__()
# 深度卷积: 每个输入通道单独卷积
self.depthwise = nn.Conv2d(in_ch, in_ch, kernel_size, stride,
padding, groups=in_ch, bias=False)
# 逐点卷积: 1x1卷积融合通道
self.pointwise = nn.Conv2d(in_ch, out_ch, 1, bias=False)
self.bn = nn.BatchNorm2d(out_ch)
self.relu = nn.ReLU(inplace=True)
def forward(self, x):
x = self.depthwise(x)
x = self.pointwise(x)
x = self.bn(x)
return self.relu(x)
# 示例
x = torch.randn(1, 32, 112, 112)
model = DepthwiseSeparableConv(32, 64)
print(model(x).shape) # torch.Size([1, 64, 112, 112])
7.2 自定义实现(手写两步)
python
class DW_PW_Custom(nn.Module):
def __init__(self, in_ch, out_ch):
super().__init__()
self.dw = nn.Conv2d(in_ch, in_ch, 3, padding=1, groups=in_ch)
self.pw = nn.Conv2d(in_ch, out_ch, 1)
def forward(self, x):
return self.pw(self.dw(x))
八、优缺点总结
| 优点 | 缺点 |
|---|---|
| 参数量、计算量显著下降(约 1/9) | 减少跨通道特征交互,特征表达能力下降 |
| 支持高并行性,适合移动端部署 | 不适合通道间关系复杂的任务(如检测) |
| 可与BN/激活轻松组合 | 单独使用时精度下降明显 |
✅ 结论:深度可分离卷积是一种"效率优先"的设计,特别适合轻量化模型(MobileNet、EfficientNet、ShuffleNet 等)。
九、适用与不适用场景
适用:
-
移动端/实时推理(如手机端检测、人脸识别)
-
参数量受限模型
-
部署在嵌入式设备上(如 Jetson、Raspberry Pi)
不适用: