卷积神经网络中的Separable Convolution
卷积网络运算中非常消耗显存,除了从框架本身考虑节省显存外,也可以从计算方式来入手,这里分享一篇讲分离卷积计算的博客(https://yinguobing.com/separable-convolution/#fn2)
常规的卷积运算
假设输入为64643的这样一个彩色图片,经过一个包含有4个filter的卷积层,最终输出4个通道,设定每一个kernel的大小是3x3,那么卷积层的参数数量可以用如下公式计算
N
c
o
n
v
=
4
∗
3
∗
3
∗
3
=
108
Nconv = 4*3*3*3 = 108
Nconv=4∗3∗3∗3=108
前面两个3表示3*3的每一个kernel大小,后面一个3表示每个filter中的3个kernel
Separable Convolution
Separable Convolution 在Google的Xception以及MobileNet论文中有相应的论述,它的核心思想是讲一个完整的卷积原酸分解为两步计算,分别为Depthwise Convolution与Pointwise
Convolution。
Depthwise Convolution
同样是上述例子,一个大小为64643的图像,此次卷积全部放在二维平面中进行,并且Filter的数量与上一层的Depth相同,也就是说这里只有三个filtere,那么得到的结果应该是下图所述情况,假定此时的kernelsize依然为3*3
此时计算参数
N
=
3
∗
3
∗
3
N = 3*3*3
N=3∗3∗3
这样参数量少了很多,Depthwise Concolution 完成后的feature map数量与输入层的depth相同,但是这种运算对于输入层的每个channel独立进行卷积计算后结束,没有利用不同map在空间位置上形同的信息,因此需要增加新的操作来组合生成feature map,这就是Pointwise Convolution。
Pointwise Convolution
Pointwise Convolution的运算与常规卷积运算非常相似,不同之处在于卷积核的尺寸为1x1xM,M为上一层的Depth。所以这里的卷积预算会将上一步的map在深度方面进行加权组合,生成新的Feature map。有几个Filter就有几个Feature map,比如对应于上面的4个filter
此时的参数量
1
∗
1
∗
3
∗
4
=
12
1*1*3*4 = 12
1∗1∗3∗4=12
此时对比常规的卷积层参数和使用分离卷积操作的参数就可以获知 108 和12+27
由这里就可以看出使用separable Convolution就可以将同样深度的卷积神经网络的参数量降下来不少。
代码示例(Pytorch)
class SeparableConv2d(nn.Module):
def __init__(self,in_channels,out_channels,kernel_size=1,stride=1,padding=0,dilation=1,bias=False):
super(SeparableConv2d,self).__init__()
self.conv1 = nn.Conv2d(in_channels,in_channels,kernel_size,stride,padding,dilation,groups=in_channels,bias=bias)
self.pointwise = nn.Conv2d(in_channels,out_channels,1,1,0,1,1,bias=bias)
def forward(self,x):
x = self.conv1(x)
x = self.pointwise(x)
return x
此后把这个SeparableConv2d当成一个正常的pytorch里面的Conv2d 即可
参考文献
[1] https://yinguobing.com/separable-convolution/#fn2
[2] Xception: Deep Learning with Depthwise Separable Convolutions
[2] MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications