常规卷积
相信接触过卷积神经网络的都知道常规卷积的操作
我们通过个大小的卷积核
卷积出来的结果为
现在我们来计算一下常规卷积的计算开销(以最简单的stride
(步长)为的情况进行讨论)
卷积层每一步操作的开销
一个卷积核做一次卷积操作需要的开销为,这里是卷积核大小,则为通道数。
一个卷积核完整地卷积完一次所需开销为,这里指的是卷积完成后的特征图长宽。
我们一共使用个这样的卷积核进行卷积计算,因此最后总的计算开销为:
下面我们来看以下Depthwise卷积的步骤
在常规的卷积中,我们的卷积核都对每个通道进行了一次计算
而Depthwise卷积只对一个通道进行卷积计算,因此Depthwise卷积是不会改变原始特征图的通道数目
深度可分离卷积的Depthwise卷积步骤
原始特征图大小为
我们需要用相同通道数目个卷积核进行卷积
换句话说就是用个的卷积核分别对一个通道进行卷积计算
M个Dk*DK*1的卷积核分别对一个通道进行卷积计算
上面的Depthwise卷积有一个问题是,它只让卷积核单独对一个通道进行计算,但是各个通道之间的信息并没有达到交换,从而在网络后续信息流动中会损失通道之间的信息 因此我们加入一个Pointwise操作,来进一步融合通道之间的信息这个操作也十分简单,就是常规的卷积核,形如下图:
1x1卷积核
通过这样一个卷积核,我们能在尽可能减少计算量的情况下,加强通道之间信息的交互
接下来我们继续推导下Pointwise卷积核这部分的计算量
假设一共有个的卷积核
Pointwise卷积示意图
原始特征图为
一个卷积核计算开销为:
一个卷积核卷积完原始特征图的计算开销为:
我们一共使用个卷积核,所以总开销为:
最后我们来看一下Depthwise和Pointwise这两部分的计算量:
Depthwise和Pointwise这两部分的计算量
和传统卷积相比,深度可分离卷积的计算量减少了N倍
可以看到Depthwise + Pointwise卷积的计算量相较于传统卷积减少了倍!
在达到相同目的(即对相邻元素以及通道之间信息进行计算)下,Dpethwise + Pointwise能极大减少卷积计算量,这也导致了大量移动端网络上都采用了这种卷积结构,再加上模型蒸馏,剪枝,能让移动端更高效的计算,推理。
另外华为最近出了一篇GhostNet文章,对移动端网络感兴趣的可以去看看,该文章同时结合了常规卷积和Depthwise卷积,通过普通卷积得出一系列特征图,再通过Depthwise方式在这一系列特征图得出另外一部分特征图,最后「concate」到一起:
GhostNet的模块
部分框架有提供Depthwise卷积API,这里就不再赘述了。
其他框架可以参考下面我的PaddlePaddle框架代码来实现:
import paddle.fluid as fluid
from paddle.fluid.dygraph.nn import Conv2D, BatchNorm
class DepthwiseConv(fluid.dygraph.Layer):
"""
通过分组卷积实现Depthwise卷积
卷积前后通道数不变
"""
def __init__(self, size, stride):
"""
:param inputs: 输入张量
:param size: 卷积核大小
"""
super(DepthwiseConv, self).__init__()
self.size = size
self.stride = stride
self.padding = (int(self.size - self.stride) + 1) // 2
def forward(self, inputs):
channels = inputs.shape[1] # 获取输入通道数
# print(channels)
depthwise = Conv2D(num_channels=channels, filter_size=self.size, stride=self.stride,
padding=(self.padding, self.padding), num_filters=channels)
out = depthwise(inputs)
return out
本文分享自 GiantPandaCV 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!