一、基本介绍
深度可分离卷积是对传统卷积的改进,通过拆分空间维度和通道维度的相关性,减少了卷积计算所需要的参数个数。深度可分离卷积计算主要包含两个部分,第一部分是Depthwise Convolution ,将通道拆分,每个通道用一个单独的卷积核卷积。即卷积核的个数等于输入特征的通道数,并且每个卷积核只有一个通道。第二部分是Pointwise Convolution,是为1×1卷积,卷积核通道数和输入的通道数相同。
二、传统卷积计算过程
在传统的卷积过程中,卷积核的通道数需和输入的通道数相同,
每个卷积核
的运算包含两部分,第一部分是卷积核相应通道与输入的相应通道进行卷积运算(对应位置相乘再相加),第二部分是将不同通道卷积结果相加得到通道数为1的特征图。n个卷积核最终得到通道数为n的输出。
二、深度可分离卷积计算过程
深度可分离卷积分为两个模块,第一个部分是depthwise convolution,与传统卷积过程不同,depthwise卷积将通道分离,并且卷积核个数和输入特征的通道数相同,每个卷积核的通道数都为1,一个卷积核只对一个通道做运算。最终生成的特征通道数和输入的通道数相同。
第二部分是pointwise convolution,该部分主要有两个功能:
1、自由设置输出的通道数大小,输出通道数等于pointwise convolution中一维卷积核个数。
2、融合通道间信息,depthwise卷积忽略了通道间信息,通过一维卷积可以融合通道间的信息。
三、深度可分离卷积实现
实现深度可分离卷积:
import torch
from torch import nn
from torchsummary import summary
class depth_separable(nn.Module):
def __init__(self, in_channels:int, out_channels:int) -> None:
super(depth_separable,self).__init__()
self.depth_conv = nn.Conv2d( #和常规卷积不同就是设置了groups参数
in_channels,
in_channels,
kernel_size=3,
stride=1,
groups=in_channels, #groups设置为输入通道数,可以使逐通道卷积
)
self.point_conv = nn.Conv2d( #实现点卷积
in_channels,
out_channels,
kernel_size=1,
)
def forward(self, x):
return self.point_conv(self.depth_conv(x))
class mydepth_separable(nn.Module):
def __init__(self) -> None:
super(mydepth_separable,self).__init__()
self.conv2d = depth_separable(3,8)
self.relu = nn.ReLU()
def forward(self, x):
return self.relu(self.conv2d(x))
device = torch.device("cuda" )
model=mydepth_separable().to(device)
summary(model, (3, 5, 5)) #查看参数量(3,5,5)表示输入的尺寸是5×5×3
参数结果:
可以看到depthwise卷积后的输出是3×3×3,参数量是30,点卷积的输出是3×3×8,参数量是32,这里的参数量包含了偏置。
普通卷积:
import torch
from torch import nn
from torchsummary import summary
class conv(nn.Module):
def __init__(self, in_channels:int, out_channels:int) -> None:
super(conv,self).__init__()
self.conv = nn.Conv2d(
in_channels,
out_channels,
kernel_size=3,
stride=1,
)
def forward(self,x):
return self.conv(x)
class myconv(nn.Module):
def __init__(self) -> None:
super(myconv,self).__init__()
self.conv2d=conv(3,8)
self.relu=nn.ReLU()
def forward(self,x):
return self.relu(self.conv2d(x))
device = torch.device("cuda" )
model1=myconv().to(device)
summary(model1, (3, 5, 5))
对比普通卷积和深度可分离卷积,深度可分离卷积一共仅需62个参数,而普通卷积需要224个参数,这就是深度可分离模块的作用,大大地减少了参数量。但是,参数量减少的同时也可能出现模型性能下降的可能,因此如何在降低网络规模的同时保证网络的性能也是轻量型网络的研究热点。