雷锋网按:本文原作者Xf Mao ,本文原载于知乎 。雷锋网已获得作者授权。
推荐另一篇很好的总结:变形卷积核、可分离卷积?卷积神经网络中十大拍案叫绝的操作。
这篇总结很专业,并且很好的回答了评论中的疑问:
Depthwise Separable Convolution 就是卷积加 group 吧? 这篇文章里是这么说的:
要注意的是,Group conv 是一种 channel 分组的方式,Depthwise +Pointwise 是卷积的方式,只是 ShuffleNet 里面把两者应用起来了。因此 Group conv 和 Depthwise +Pointwise 并不能划等号。 我觉得 Depthwise +Pointwise 卷积是提供一种把 feature map 的空间信息(height&width)和通道信息(channel)拆分分别处理的方法,而 group 卷积只是单纯的通道分组处理,降低复杂度。
对于表述有误的地方欢迎更正!另外目前仅列举了一些比较著名且实用的卷积操作,对于没提到的,希望大家指出与补充
1. 原始版本 最早的卷积方式还没有任何骚套路,那就也没什么好说的了。
见下图,原始的 conv 操作可以看做一个 2D 版本的无隐层神经网络。
附上一个卷积详细流程:
【TensorFlow】tf.nn.conv2d 是怎样实现卷积的? - CSDN 博客
<img src="https://static.leiphone.com/uploads/new/article/pic/201709/fb01665eb9a74d64792d426dcb3a046e.jpg" data-rawwidth="933" data-rawheight="637" class="origin_image zh-lightbox-thumb" width="933" data-original="https://pic3.zhimg.com/v2-b3aed0d569a91f87da9f586217d76092_r.jpg" _src="https://static.leiphone.com/uploads/new/article/pic/201709/fb01665eb9a74d64792d426dcb3a046e.jpg"/>
代表模型:
LeNet:最早使用 stack 单卷积 + 单池化结构的方式,卷积层来做特征提取,池化来做空间下采样
AlexNet:后来发现单卷积提取到的特征不是很丰富,于是开始 stack 多卷积 + 单池化的结构
VGG([1409.1556] Very Deep Convolutional Networks for Large-Scale Image Recognition ):结构没怎么变,只是更深了
2. 多隐层非线性版本 这个版本是一个较大的改进,融合了 Network In Network 的增加隐层提升非线性表达的思想,于是有了这种先用 1*1 的卷积映射到隐空间,再在隐空间做卷积的结构。同时考虑了多尺度,在单层卷积层中用多个不同大小的卷积核来卷积,再把结果 concat 起来。
这一结构,被称之为 “Inception”
<img src="https://static.leiphone.com/uploads/new/article/pic/201709/2b7c53ec65e0163883ac14bcd54a40eb.jpg" data-rawwidth="844" data-rawheight="442" class="origin_image zh-lightbox-thumb" width="844" data-original="https://pic4.zhimg.com/v2-eddec9ea8e0868c570fb95c00032c8e3_r.jpg" _src="https://static.leiphone.com/uploads/new/article/pic/201709/2b7c53ec65e0163883ac14bcd54a40eb.jpg"/>
代表模型:
Inception-v1([1409.4842] Going Deeper with Convolutions ):stack 以上这种 Inception 结构
Inception-v2(Accelerating Deep Network Training by Reducing Internal Covariate Shift ):加了 BatchNormalization 正则,去除 5*5 卷积,用两个 3*3 代替
Inception-v3([1512.00567] Rethinking the Inception Architecture for Computer Vision ):7*7 卷积又拆成 7*1+1*7
Inception-v4([1602.07261] Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning ):加入了残差结构
3. 空洞卷积 Dilation 卷积,通常译作空洞卷积或者卷积核膨胀操作,它是解决 pixel-wise 输出模型的一种常用的卷积方式。一种普遍的认识是,pooling 下采样操作导致的信息丢失是不可逆的,通常的分类识别模型,只需要预测每一类的概率,所以我们不需要考虑 pooling 会导致损失图像细节信息的问题,但是做像素级的预测时(譬如语义分割),就要考虑到这个问题了。
所以就要有一种卷积代替 pooling 的作用(成倍的增加感受野),而空洞卷积就是为了做这个的。通过卷积核插 “0” 的方式,它可以比普通的卷积获得更大的感受野,这个 idea 的 motivation 就介绍到这里。具体实现方法和原理可以参考如下链接:
如何理解空洞卷积(dilated convolution)?
膨胀卷积 --Multi-scale context aggregation by dilated convolutions
我在博客里面又做了一个空洞卷积小 demo 方便大家理解
【Tensorflow】tf.nn.atrous_conv2d 如何实现空洞卷积? - CSDN 博客
代表模型:
FCN([1411.4038] Fully Convolutional Networks for Semantic Segmentation ):Fully convolutional networks,顾名思义,整个网络就只有卷积组成,在语义分割的任务中,因为卷积输出的 feature map 是有 spatial 信息的,所以最后的全连接层全部替换成了卷积层。
Wavenet(WaveNet: A Generative Model for Raw Audio ):用于语音合成。
4. 深度可分离卷积 Depthwise Separable Convolution,目前已被 CVPR2017 收录,这个工作可以说是 Inception 的延续,它是 Inception 结构的极限版本。
为了更好的解释,让我们重新回顾一下 Inception 结构(简化版本):
<img src="https://static.leiphone.com/uploads/new/article/pic/201709/fc1b0ae551ec7bb3c781a9402d0c0933.jpg" data-rawwidth="851" data-rawheight="535" class="origin_image zh-lightbox-thumb" width="851" data-original="https://pic2.zhimg.com/v2-e93699a4b575c2048a3f253260373a45_r.jpg" _src="https://static.leiphone.com/uploads/new/article/pic/201709/fc1b0ae551ec7bb3c781a9402d0c0933.jpg"/>
上面的简化版本,我们又可以看做,把一整个输入做 1*1 卷积,然后切成三段,分别 3*3 卷积后相连,如下图,这两个形式是等价的,即 Inception 的简化版本又可以用如下形式表达:
<img src="https://static.leiphone.com/uploads/new/article/pic/201709/c390cddb8d2bdea711f2ea2672849151.jpg" data-rawwidth="894" data-rawheight="501" class="origin_image zh-lightbox-thumb" width="894" data-original="https://pic3.zhimg.com/v2-522db5f1d17226e6179169e27b5feb42_r.jpg" _src="https://static.leiphone.com/uploads/new/article/pic/201709/c390cddb8d2bdea711f2ea2672849151.jpg"/>
OK,现在我们想,如果不是分成三段,而是分成 5 段或者更多,那模型的表达能力是不是更强呢?于是我们就切更多段,切到不能再切了,正好是 Output channels 的数量(极限版本):
<img src="https://static.leiphone.com/uploads/new/article/pic/201709/c2205f75ef021bf53dcf3e8680feb608.jpg" data-rawwidth="897" data-rawheight="491" class="origin_image zh-lightbox-thumb" width="897" data-original="https://pic4.zhimg.com/v2-c71010f8756639fc13b4287f02efbca3_r.jpg" _src="https://static.leiphone.com/uploads/new/article/pic/201709/c2205f75ef021bf53dcf3e8680feb608.jpg"/>
于是,就有了深度卷积(depthwise convolution),深度卷积是对输入的每一个 channel 独立的用对应 channel 的所有卷积核去卷积,假设卷积核的 shape 是 [filter_height, filter_width, in_channels, channel_multiplier],那么每个 in_channel 会输出 channel_multiplier 那么多个通道,最后的 feature map 就会有 in_channels * channel_multiplier 个通道了。反观普通的卷积,输出的 feature map 一般就只有 channel_multiplier 那么多个通道。
具体的过程可参见我的 demo:
【Tensorflow】tf.nn.depthwise_conv2d 如何实现深度卷积? - CSDN 博客
既然叫深度可分离卷积,光做 depthwise convolution 肯定是不够的,原文在深度卷积后面又加了 pointwise convolution,这个 pointwise convolution 就是 1*1 的卷积,可以看做是对那么多分离的通道做了个融合。
这两个过程合起来,就称为 Depthwise Separable Convolution 了:
【Tensorflow】tf.nn.separable_conv2d 如何实现深度可分卷积? - CSDN 博客
代表模型: Xception(Xception: Deep Learning with Depthwise Separable Convolutions )
5. 可变形卷积 可形变卷积的思想很巧妙:它认为规则形状的卷积核(比如一般用的正方形 3*3 卷积)可能会限制特征的提取,如果赋予卷积核形变的特性,让网络根据 label 反传下来的误差自动的调整卷积核的形状,适应网络重点关注的感兴趣的区域,就可以提取更好的特征。
如下图:网络会根据原位置(a),学习一个 offset 偏移量,得到新的卷积核(b)(c)(d),那么一些特殊情况就会成为这个更泛化的模型的特例,例如图(c)表示从不同尺度物体的识别,图(d)表示旋转物体的识别。
<img src="https://static.leiphone.com/uploads/new/article/pic/201709/64a862da2b7ce0ad0aa2add71e7a4499.jpg" data-rawwidth="1150" data-rawheight="383" class="origin_image zh-lightbox-thumb" width="1150" data-original="https://pic4.zhimg.com/v2-f267a0fa74c414dfc6ecf9e3124e0f4b_r.jpg" _src="https://static.leiphone.com/uploads/new/article/pic/201709/64a862da2b7ce0ad0aa2add71e7a4499.jpg"/>
这个 idea 的实现方法也很常规:
<img src="https://static.leiphone.com/uploads/new/article/pic/201709/802046efb1c5df9f0c02312151168e9a.jpg" data-rawwidth="968" data-rawheight="613" class="origin_image zh-lightbox-thumb" width="968" data-original="https://pic2.zhimg.com/v2-9eea6a49745ade45a6fd0cd9abaa1a4d_r.jpg" _src="https://static.leiphone.com/uploads/new/article/pic/201709/802046efb1c5df9f0c02312151168e9a.jpg"/>
上图中包含两处卷积,第一处是获取 offsets 的卷积,即我们对 input feature map 做卷积,得到一个输出(offset field),然后再在这个输出上取对应位置的一组值作为 offsets。假设 input feature map 的 shape 为 [batch,height,width,channels],我们指定输出通道变成两倍,卷积得到的 offset field 就是 [batch,height,width,2×channels],为什么指定通道变成两倍呢?因为我们需要在这个 offset field 里面取一组卷积核的 offsets,而一个 offset 肯定不能一个值就表示的,最少也要用两个值(x 方向上的偏移和 y 方向上的偏移)所以,如果我们的卷积核是 3*3,那意味着我们需要 3*3 个 offsets,一共需要 2*3*3 个值,取完了这些值,就可以顺利使卷积核形变了。第二处就是使用变形的卷积核来卷积,这个比较常规。(这里还有一个用双线性插值的方法获取某一卷积形变后位置的输入的过程)
这里有一个介绍性的 Slide:http://prlab.tudelft.nl/sites/default/files/Deformable_CNN.pdf
代表模型: Deformable Convolutional Networks(Deformable Convolutional Networks ):暂时还没有其他模型使用这种卷积,期待后续会有更多的工作把这个 idea 和其他视觉任务比如检测,跟踪相结合。
6. 特征重标定卷积 这是 ImageNet 2017 竞赛 Image Classification 任务的冠军模型 SENet 的核心模块,原文叫做”Squeeze-and-Excitation“,我结合我的理解暂且把这个卷积称作” 特征重标定卷积 “。
和前面不同的是,这个卷积是对特征维度作改进的。一个卷积层中往往有数以千计的卷积核,而且我们知道卷积核对应了特征,于是乎那么多特征要怎么区分?这个方法就是通过学习的方式来自动获取到每个特征通道的重要程度,然后依照计算出来的重要程度去提升有用的特征并抑制对当前任务用处不大的特征。
<img src="https://static.leiphone.com/uploads/new/article/pic/201709/78ea8ff79cde2195a2df19bfeed756a6.jpg" data-rawwidth="1262" data-rawheight="392" class="origin_image zh-lightbox-thumb" width="1262" data-original="https://pic3.zhimg.com/v2-4b785d7a5c77f68043740bdc088bb80e_r.jpg" _src="https://static.leiphone.com/uploads/new/article/pic/201709/78ea8ff79cde2195a2df19bfeed756a6.jpg"/>
这个想法的实现异常的简单,简单到你难以置信。
首先做普通的卷积,得到了一个的 output feature map,它的 shape 为 [C,H,W],根据 paper 的观点,这个 feature map 的特征很混乱。然后为了获得重要性的评价指标,直接对这个 feature map 做一个 Global Average Pooling,然后我们就得到了长度为 C 的向量。(这里还涉及到一个额外的东西,如果你了解卷积,你就会发现一旦某一特征经常被激活,那么 Global Average Pooling 计算出来的值会比较大,说明它对结果的影响也比较大,反之越小的值,对结果的影响就越小)
然后我们对这个向量加两个 FC 层,做非线性映射,这俩 FC 层的参数,也就是网络需要额外学习的参数。
最后输出的向量,我们可以看做特征的重要性程度,然后与 feature map 对应 channel 相乘就得到特征有序的 feature map 了。
虽然各大框架现在都还没有扩展这个卷积的 api,但是我们实现它也就几行代码的事,可谓是简单且实用了。
另外它还可以和几个主流网络结构结合起来一起用,比如 Inception 和 Res:
<img src="https://static.leiphone.com/uploads/new/article/pic/201709/e72feb3bad62faac2de6b3984aed9bd0.jpg" data-rawwidth="520" data-rawheight="495" class="origin_image zh-lightbox-thumb" width="520" data-original="https://pic4.zhimg.com/v2-32e1266a8f7f952d9fc4602dadf291ab_r.jpg" _src="https://static.leiphone.com/uploads/new/article/pic/201709/e72feb3bad62faac2de6b3984aed9bd0.jpg"/> <img src="https://static.leiphone.com/uploads/new/article/pic/201709/f300ec1e1f75404f123d2d0d015a5624.jpg" data-rawwidth="558" data-rawheight="469" class="origin_image zh-lightbox-thumb" width="558" data-original="https://pic4.zhimg.com/v2-58797fac3389570c8655d4b73351d30f_r.jpg" _src="https://static.leiphone.com/uploads/new/article/pic/201709/f300ec1e1f75404f123d2d0d015a5624.jpg"/>
代表模型:Squeeze-and-Excitation Networks(Squeeze-and-Excitation Networks )
7. 比较 我们把图像(height,width)作为空间维度,把 channels 做为特征维度。<img src="https://static.leiphone.com/uploads/new/article/pic/201709/46c2d76556606733ded2903f1b40b8f8.jpg" data-rawwidth="1004" data-rawheight="768" class="origin_image zh-lightbox-thumb" width="1004" data-original="https://pic3.zhimg.com/v2-710904e96b88df6f81a1b13aeef942a6_r.jpg" _src="https://static.leiphone.com/uploads/new/article/pic/201709/46c2d76556606733ded2903f1b40b8f8.jpg"/>