暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

走向轻量化网络:分组卷积与深度可分离卷积

南极Python 2021-05-25
1323

分组卷积(Group Convolution)

分组卷积将输入特征图进行分组,分别对每组的特征图进行卷积操作,得到输出的特征图,最后再将每组卷积后得到的特征图拼接在一起,就完成了整个卷积操作。

在PyTorch中,输入特征图个数与输出特征图个数需要能够被分组数整除,因为输出特征图个数需要均摊给每一组。比如输入特征图个数为X,输出特征图个数为Y,分组数为g,且g可整除X和Y,那么每一组的输入特征图个数为X/g,输出特征图个数为Y/g,总的输出特征图个数为(Y/g)*g=Y

假设输入特征图个数为6,卷积核尺寸为3*3,输出特征图个数为10,不考虑偏置项。以下操作基于本例.

普通卷积:

当分组数为1时,就是普通的卷积

import torch
import torch.nn as  nn
from torchsummary import summary
class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv=nn.Conv2d(in_channels=6,out_channels=10,kernel_size=3,groups=1,bias=False)
    def forward(self,x):
        return self.conv(x)
model=Model()

查看参数量:

参数量计算方法:

1*((3*3*(6/1))*(10/1))=540
1是分组数
3*3是卷积核尺寸
6是输入特征图个数
10是输出特征图个数

分组卷积:

当分组数不为1时,就是分组卷积

import torch
import torch.nn as  nn
from torchsummary import summary
class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv=nn.Conv2d(in_channels=6,out_channels=10,kernel_size=3,groups=2,bias=False)
    def forward(self,x):
        return self.conv(x)
model=Model()

查看参数量:

参数量计算方法:

2 * ((3*3*(6/2))*(10/2))=270
2是分组数
3*3是卷积核尺寸
6是输入特征图个数
10是输出特征图个数

可以看到,我们分了两组,参数量也减半。

深度可分离卷积(Depthwise Separable Convolution)

深度可分离卷积包含两个步骤:逐通道卷积逐点卷积

假设输入特征图个数为6,卷积核尺寸为3*3,输出特征图个数为12,不考虑偏置项。以下操作基于本例.

逐通道卷积(Depthwise Convolution)

当分组卷积的分组数=输入特征图个数=输出特征图个数时,就得到了逐通道卷积:

import torch
import torch.nn as  nn
from torchsummary import summary
class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv=nn.Conv2d(in_channels=6,out_channels=6,kernel_size=3,groups=6,bias=False)
    def forward(self,x):
        return self.conv(x)
model=Model()

查看参数量:

参数量计算方法:

6 * ((3*3*(6/6))*(6/6))=54
6是分组数,等于输入特征图个数
3*3是卷积核尺寸
6是输入特征图个数,也是输出特征图个数

逐点卷积(Pointwise Convolution)

逐点卷积就是普通的1*1卷积(分组数为1)

import torch
import torch.nn as  nn
from torchsummary import summary
class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv=nn.Conv2d(in_channels=6,out_channels=12,kernel_size=1,groups=1,bias=False)
    def forward(self,x):
        return self.conv(x)
model=Model()

查看参数量:

参数量计算方法:

1 * ((1*1*(6/1))*(12/1))=72
1是分组数,等于输入特征图个数
1*1是卷积核尺寸
6是输入特征图个数
12是输出特征图个数

至此,逐通道卷积与逐点卷积的参数量之和为:54+72=126

深度可分离卷积可以描述为:

import torch
import torch.nn as  nn
from torchsummary import summary
class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.depthwise_conv=nn.Conv2d(in_channels=6,out_channels=6,kernel_size=3,groups=6,bias=False)#groups=in_channels=out_channels
        self.pointwise_conv=nn.Conv2d(in_channels=6,out_channels=12,kernel_size=1,groups=1,bias=False)
    def forward(self,x):
        return self.pointwise_conv(self.depthwise_conv(x))
model=Model()

查看参数量:

参数量也是54+72=126

由此可见,深度可分离卷积正是逐通道卷积与逐点卷积的叠加。

普通卷积

import torch
import torch.nn as  nn
from torchsummary import summary
class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv=nn.Conv2d(in_channels=6,out_channels=12,kernel_size=3,groups=1,bias=False)
    def forward(self,x):
        return self.conv(x)
model=Model()

查看参数量:

参数量计算方法:

1 * ((3*3*(6/1))*(12/1))=648
1是分组数
3*3是卷积核尺寸
6是输入特征图个数
12是输出特征图个数

看,输出特征图个数一样的前提下,普通卷积的参数量远多于深度可分离卷积。

正因为深度可分离卷积的参数量较少,使得它在轻量化网络中得到了广泛应用,有时间可以盘点下这些轻量化网络。

参考:

  • [1] https://zhuanlan.zhihu.com/p/92134485
  • [2] https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html




南极Python交流群已成立,长按下方二维码添加我的微信,备注加群即可,欢迎进群学习交流(划水


              原创不易,感谢点赞,分享和在看的你!

文章转载自南极Python,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论