深度可分离卷积(Depthwise Separable Convolution)和分组卷积(Group Convolution)的理解,相互关系及PyTorch实现

1. 分组卷积(Group Convolution)

分组卷积最早出现在AlexNet中,如下图所示。在CNN发展初期,GPU资源不足以满足训练任务的要求,因此,Hinton采用了多GPU训练的策略,每个GPU完成一部分卷积,最后把多个GPU的卷积结果进行融合。AlexNet结构图
接下来回顾一下常规卷积是怎样进行的,假设输入的特征图(Tensor)的shape为 C i n × H × W C_{in} \times H \times W Cin×H×W,输出通道数为 C o u t C_{out} Cout,那么,卷积过程中就会有 C o u t C_{out} Cout个卷积核(Convolution Kernel),每个卷积核的尺寸为 C i n × K × K C_{in} \times K \times K Cin×K×K,其中, K K K为卷积核的大小,换句话说,就是每个卷积核会和输入特征图的每个通道都进行卷积计算,每个卷积核的计算结果是各通道卷积结果的和。文字可能枯燥,下图是是常规卷积的示意图。
常规卷积示意图
可以很明显看出,常规卷积的计算结果中,特征图的每个通道和输入特征图的所有通道都有关。下图是分组卷积的示意图,差别就非常明显了。分组卷积的输出特征图的每个通道,只和输入特征图的一部分通道有关,而这部分通道,就是一个分组(Group)。依旧假设输入特征图的尺寸为 C i n × H × W C_{in} \times H \times W Cin×H×W,分为3组进行分组卷积,那么,对于每一组,输出特征图的通道数都是 C o u t / 3 C_{out}/3 Cout/3,卷积核大小变为 C i n × K × K C_{in} \times K \times K Cin×K×K,最后只需要将各个分组的计算结果按照通道进行连接(Cat)即可。

分组卷积可以很大程度上减少卷积所需的参数量,上述例子中,常规卷积所需的参数量(仅考虑卷积权重,不考虑偏置)为:
C i n × K × K × C o u t C_{in} \times K \times K \times C_{out} Cin×K×K×Cout
相同的输入输出特征图,分组卷积所需的参数量为:
C i n × K × K × C o u t 3 \frac{C_{in} \times K \times K \times C_{out}}{3} 3Cin×K×K×Cout
即,分组卷积可将参数量减少为原来的 1 / G 1/G 1/G G G G为分组数量。
分组卷积示意图

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

大部分博客在介绍可分离卷积和分组卷积时,都是先介绍深度可分离卷积再介绍分组卷积。博主之所以将两者顺序做出了调换,是因为,按照我的理解,深度可分离卷积是可以基于分组卷积进行理解和分析的。

单从名称进行分析,Depthwise可理解为逐深度,如此理解,深度可分离卷积就是逐个深度分开卷积,也就是逐个通道分开卷积。这样子,深度可分离卷积就变得非常容易理解了,以分组卷积为基础,深度可分离卷积是分组为 C i n C_{in} Cin的分组卷积。但是,其中也是有区别的,逐深度卷子只是深度可分离卷子的第一个过程,这个过程中,输入特征图和输出特征图的通道数保持一致,也就是,对于输入特征图的每个通道,通过一个尺寸为 K × K K \times K K×K的卷积核,计算结果作为输出特征图的一个通道,不进行通道数的增加和减少。深度可分离卷积是通过**逐点卷积(Pointwise Convolution)**实现通道数改变的,这个过程使用大小为 C i n × 1 × 1 C_{in} \times 1 \times 1 Cin×1×1的卷积核实现,数量为 C o u t C_{out} Cout个,深度可分离卷积所需参数量为:
C i n × K × K + C o u t × 1 × 1. C_{in} \times K \times K + C_{out} \times 1 \times1. Cin×K×K+Cout×1×1.

3. PyTorch实现

Pytorch是2017年推出的深度学习框架,不同于Tensorflow基于静态图的模型搭建方式,PyTorch是完全动态的框架,推出以来很快成为AI研究人员的热门选择并受到推崇。(介绍到此结束)

在PyTorch中,实现二维卷积是通过nn.Conv2d实现的,这个函数是非常强大的,其功能不仅仅是实现常规卷积,通过合理的参数选择就可以实现分组卷积、空洞卷积。API的官方介绍如下:

CLASS torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)

 - stride: controls the stride for the cross-correlation, a single number or a tuple.
 - padding: controls the amount of implicit zero-paddings on both sides for padding number of points for each dimension.
 - dilation: controls the spacing between the kernel points; also known as the à trous algorithm. It is harder to describe, but this link has a nice visualization of what dilation does.
 - groups: controls the connections between inputs and outputs. in_channels and out_channels must both be divisible by groups. For example,
		At groups=1, all inputs are convolved to all outputs.
		At groups=2, the operation becomes equivalent to having two conv layers side by side, each seeing half the input channels, and producing half the output channels, and both subsequently concatenated.
		At groups= in_channels, each input channel is convolved with its own set of filters.
3.1 分组卷积

分组卷积只需要对nn.Conv2d中的groups参数进行设置即可,表示需要分的组数,groups的默认值为1,即进行常规卷积。以下是实现分组卷积的代码:

class CSDN_Tem(nn.Module):
    def __init__(self, in_ch, out_ch, groups):
        super(CSDN_Tem, self).__init__()
        self.conv = nn.Conv2d(
            in_channels=in_ch,
            out_channels=out_ch,
            kernel_size=3,
            stride=1,
            padding=1,
            groups=groups
        )

    def forward(self, input):
        out = self.conv(input)
        return out

通过以下代码对该模型进行测试,设定输入特征图通道数为16,输出特征图通道数为32,分组数目为4:

conv = CSDN_Tem(16, 32, 4)
print(summary(conv, (16, 64, 64), batch_size=1))

控制台输出为:

----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1            [1, 32, 64, 64]           1,184
================================================================
Total params: 1,184
Trainable params: 1,184
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.25
Forward/backward pass size (MB): 1.00
Params size (MB): 0.00
Estimated Total Size (MB): 1.25
----------------------------------------------------------------

这一分组卷积过程所需参数为1184个,其中包含了偏置(Bias).

3.2 深度可分离卷积

深度可分离卷积的PyTorch代码如下:

class CSDN_Tem(nn.Module):
    def __init__(self, in_ch, out_ch):
        super(CSDN_Tem, self).__init__()
        self.depth_conv = nn.Conv2d(
            in_channels=in_ch,
            out_channels=in_ch,
            kernel_size=3,
            stride=1,
            padding=1,
            groups=in_ch
        )
        self.point_conv = nn.Conv2d(
            in_channels=in_ch,
            out_channels=out_ch,
            kernel_size=1,
            stride=1,
            padding=0,
            groups=1
        )

    def forward(self, input):
        out = self.depth_conv(input)
        out = self.point_conv(out)
        return out

采用和分组卷积相同的输入和输出通道数,测试代码如下:

conv = CSDN_Tem(16, 32)
print(summary(conv, (16, 64, 64), batch_size=1))

控制台输出结果为:

----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1            [1, 16, 64, 64]             160
            Conv2d-2            [1, 32, 64, 64]             544
================================================================
Total params: 704
Trainable params: 704
Non-trainable params: 0
----------------------------------------------------------------

深度可分离卷积实现相同的操作仅需704个参数。

如有疑问,欢迎留言!

参考

  1. https://www.cnblogs.com/shine-lee/p/10243114.html
  2. https://blog.csdn.net/luoluonuoyasuolong/article/details/81750190
  3. https://blog.csdn.net/luoluonuoyasuolong/article/details/81750190
  4. https://pytorch.org/docs/stable/nn.html?highlight=conv2#torch.nn.Conv2d
  • 39
    点赞
  • 214
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值