OctaveConv:用频域分解减少卷积冗余
最近在看模型压缩方向的论文,翻到了一篇很有意思的工作——Drop an Octave: Reducing Spatial Redundancy in Convolutional Neural Networks with Octave Convolution。它的切入点不是参数量,而是 feature map 本身的冗余。
核心思路:把 feature map 当成频率的叠加
作者的出发点是:一张图片可以分解为低频和高频两个部分,卷积网络中间层的 feature map 同样可以这样理解。
低频部分对应全局性的、模糊的、整体轮廓的信息;高频部分对应局部细节和边缘。既然低频分量主要是全局信息、细节不多,用全分辨率的 tensor 来存储和计算它其实是浪费。基于这个直觉,作者设计了一种叫做 OctaveConv 的卷积操作,在 channel 维度上把 feature map 分解成高频和低频两组,并对低频组做空间降采样,从而减少内存和计算量。
分解方式:超参数 α 控制比例
具体做法是:在 channel 维度上定义一个超参数 α,作为低频 channel 所占的比例。
- 高频部分(占比
1 - α):保留原有的 feature map 大小。
- 低频部分(占比
α):feature map 的长和宽都缩减为原来的一半。
“Octave”这个名字就来自这里——空间分辨率减半,对应音频领域频率降低一个八度。
OctaveConv 的更新方式
由于高频和低频两组 feature map 的空间尺寸不一样,普通卷积无法直接处理。OctaveConv 将每次特征更新定义为从一组不同尺寸的 feature map 到另一组不同尺寸的 feature map。
每次更新的输入输出形式如下:
具体的更新方式如下图:
图的右边标注了各路径对应的卷积核大小。整体上有四条路径:高频到高频、低频到低频、高频到低频(需要先做 pool 降采样再卷积)、低频到高频(需要先卷积再做 upsample)。需要注意的是,在 feature map 大小发生变化时,有 upsample 和 pool 的操作;另外,octave 内部的卷积使用的是 group conv。
参数量不变,计算量减少
改变了卷积操作之后,参数量并没有发生变化——卷积核的参数矩阵大小与 feature map 的空间尺寸无关。但内存和计算量相应减小了,具体减小的程度由 α 来决定:α 越大,分配到低频路径的 channel 越多,整体计算量下降越明显。
替换效果
将标准卷积替换为 OctaveConv 之后的性能对比如下图:
论文中一个比较有代表性的结果是:将 OctaveConv 应用到 ResNet-152,Top-1 精度达到 82.9%,计算量只有 22.2 GFLOPs。在合理的 α 取值下,这是一种几乎不损精度的加速方式,值得在实际项目中试一试。