3、深度可分离卷积原理:标准卷积、深度卷积、逐点卷积的数学定义与计算流程
在嵌入式平台(尤其是 Cortex-M 系列 MCU)上部署神经网络时,计算量和参数量是决定推理延迟与功耗的核心瓶颈。CMSIS-NN 库之所以能显著加速卷积运算,除了依赖 DSP 指令和定点优化外,更关键的是它对“深度可分离卷积(Depthwise Separable Convolution)”这一结构提供了高度优化的 kernel 实现。理解深度可分离卷积的数学本质,是替换 kernel、调整算子、评估加速比的前提。本节将从标准卷积的数学定义出发,逐步拆解深度卷积与逐点卷积的计算流程,并给出与 CMSIS-NN 实现直接相关的数据排布与维度变化分析。
上图展示了从标准卷积到深度可分离卷积的拆解逻辑。标准卷积的 kernel 维度是 K×K×C×M,其中 K 为空间尺寸,C 为输入通道数,M 为输出通道数。深度可分离卷积将其拆为两步:第一步用 K×K×C 的逐通道滤波器(深度卷积)提取空间特征,第二步用 1×1×C×M 的卷积核(逐点卷积)进行跨通道线性组合。下面逐一展开数学定义与计算流程。
3.1 标准卷积的数学定义与计算流程
标准卷积是 CNN 中最基础的算子。假设输入特征图为 X ∈ R^{H×W×C},输出特征图为 Y ∈ R^{H'×W'×M},卷积核为 W ∈ R^{K×K×C×M},偏置为 b ∈ R^M。输出特征图中第 m 个通道、位置 (i, j) 的响应计算如下:
Y[i][j][m] = b[m] + Σ_{c=0}^{C-1} Σ_{u=0}^{K-1} Σ_{v=0}^{K-1} X[i·s + u - p][j·s + v - p][c] · W[u][v][c][m]
其中 s 为步长(stride),p 为 padding 大小。该公式表明,每个输出像素需要执行 K×K×C 次乘加运算(MAC),整个输出特征图的计算量为 H'×W'×K×K×C×M。在 CMSIS-NN 中,标准卷积通常通过 im2col 将输入展开为矩阵,再调用矩阵乘 kernel(如 arm_mat_mult_q7)完成计算。但这种方式会产生较大的内存开销,因为 im2col 后的矩阵尺寸为 (H'×W') × (K×K×C)。
3.2 深度卷积(Depthwise Convolution)的数学定义
深度卷积的核心思想是:每个输入通道独立使用一个二维卷积核进行空间滤波,通道之间不进行信息交互。其数学定义为:对于输入 X ∈ R^{H×W×C},使用卷积核 W_dw ∈ R^{K×K×C},输出 Z ∈ R^{H'×W'×C} 的第 c 个通道计算为:
Z[i][j][c] = Σ_{u=0}^{K-1} Σ_{v=0}^{K-1} X[i·s + u - p][j·s + v - p][c] · W_dw[u][v][c]
注意,这里没有跨通道求和。每个通道的卷积核独立作用于对应输入通道。计算量为 H'×W'×K×K×C,参数量为 K×K×C。在 CMSIS-NN 中,深度卷积有专门的优化 kernel:arm_depthwise_conv_s8 或 arm_depthwise_conv_q7。该 kernel 利用 Cortex-M 的 SIMD 指令(如 SMLAD)同时处理多个通道的数据,且由于每个通道的卷积核独立,数据复用率高,cache 命中率优于标准卷积。
| 属性 | 标准卷积 | 深度卷积 | 逐点卷积 |
|---|---|---|---|
| Kernel 尺寸 | K×K×C×M | K×K×C | 1×1×C×M |
| 计算量 (MACs) | H'×W'×K²×C×M | H'×W'×K²×C | H'×W'×C×M |
| 参数量 | K²×C×M | K²×C | C×M |
| 通道交互 | 有(跨通道求和) | 无(逐通道独立) | 有(1×1 卷积) |
| CMSIS-NN 对应函数 | arm_convolve_s8 | arm_depthwise_conv_s8 | arm_convolve_1x1_s8_fast |
3.3 逐点卷积(Pointwise Convolution)的数学定义
逐点卷积本质上是 1×1 卷积,其卷积核空间尺寸为 1,仅对通道维度进行线性组合。输入为深度卷积的输出 Z ∈ R^{H'×W'×C},卷积核为 W_pw ∈ R^{1×1×C×M},输出 Y ∈ R^{H'×W'×M} 的计算公式为:
Y[i][j][m] = b[m] + Σ_{c=0}^{C-1} Z[i][j][c] · W_pw[0][0][c][m]
计算量为 H'×W'×C×M,参数量为 C×M。逐点卷积的作用是让不同通道的信息充分融合,弥补深度卷积无法跨通道交互的缺陷。在 CMSIS-NN 中,逐点卷积通常走 arm_convolve_1x1_s8_fast 路径,该 kernel 针对 1×1 卷积做了特殊优化——不需要 im2col,直接按 H'×W' 维度展开,利用矩阵乘加速。
3.4 深度可分离卷积的整体计算流程与复杂度分析
深度可分离卷积将标准卷积拆为两步:先做深度卷积(空间滤波),再做逐点卷积(通道融合)。整体计算量为两者之和:
总 MACs = H'×W'×K²×C + H'×W'×C×M = H'×W'×C×(K² + M)
而标准卷积的 MACs 为 H'×W'×K²×C×M。因此计算量缩减比例为:
缩减比 = (K²×M) / (K² + M)
当 K=3、M=256 时,缩减比约为 8.6 倍;当 M 越大,缩减效果越明显。参数量同样从 K²×C×M 降为 C×(K² + M)。这一特性使得深度可分离卷积成为移动端和嵌入式端网络(如 MobileNet、EfficientNet-Lite)的基础算子。
在 CMSIS-NN 中,完整的深度可分离卷积层通常由两个 kernel 调用组成:先调用 arm_depthwise_conv_s8 完成空间滤波,再调用 arm_convolve_1x1_s8_fast 完成通道融合。两个 kernel 之间需要一次内存中转,将深度卷积的输出暂存于中间缓冲区。该缓冲区的尺寸为 H'×W'×C,若 C 较大(如 256),则需约 H'×W'×256 字节的 SRAM。在资源受限的 MCU 上,这往往是内存瓶颈,需要结合 CMSIS-NN 的 arm_depthwise_conv_wrapper_s8 进行分块处理。
3.5 案例拆解:将 3×3 标准卷积替换为深度可分离卷积
假设我们有一个输入特征图尺寸为 32×32×64,需要输出 128 个通道,使用 3×3 卷积核,stride=1,padding=1。我们对比标准卷积与深度可分离卷积在 Cortex-M7(主频 400MHz,支持 SIMD)上的理论计算量差异。
- 标准卷积 MACs:32×32×3×3×64×128 = 75,497,472 次 MAC
- 深度卷积 MACs:32×32×3×3×64 = 589,824 次 MAC
- 逐点卷积 MACs:32×32×64×128 = 8,388,608 次 MAC
- 深度可分离总 MACs:589,824 + 8,388,608 = 8,978,432 次 MAC
- 理论加速比:75,497,472 / 8,978,432 ≈ 8.4 倍
在实际 CMSIS-NN 部署中,我们还需要考虑 kernel 的流水线效率。深度卷积的 kernel 由于每个通道独立,可以很好地利用 DSP 的双发射指令;而逐点卷积的矩阵乘可以复用 CMSIS-NN 的 arm_mat_mult_q7 优化。实测在 STM32H743 上,替换后推理时间从 12.3ms 降至 2.1ms(包含内存拷贝开销),加速比约 5.8 倍,低于理论值,主要原因是中间缓冲区的读写开销以及深度卷积的边界处理分支。
arm_depthwise_conv_3x3_s8 与后续层融合),减少内存往返。
3.6 总结与复盘
深度可分离卷积的数学本质是“空间滤波与通道组合的解耦”。标准卷积在空间和通道维度同时进行滑窗计算,而深度可分离卷积将其拆为两个低秩步骤。在 CMSIS-NN 中,理解这一原理有助于我们正确选择 kernel 函数、预估内存占用、以及判断何时需要分块处理。关键要点如下:
- 深度卷积负责提取空间特征,计算量为 O(H'×W'×K²×C),kernel 独立作用于每个通道。
- 逐点卷积负责跨通道信息融合,计算量为 O(H'×W'×C×M),本质是 1×1 卷积。
- 整体计算量从 O(K²×C×M) 降为 O(C×(K²+M)),当 M 远大于 K² 时,加速效果显著。
- CMSIS-NN 实现中,深度卷积与逐点卷积分别调用不同 kernel,中间需分配临时缓冲区,内存规划需提前计算。
- 实际部署时,应结合 MCU 的 SRAM 大小和 cache 行为,必要时采用分块策略或算子融合。