深度可分离卷积(DepthwiseSeparableConvolution):Depthwise卷积与Pointwise卷积

0、前言

深度可分离卷积不用多说,在轻量级网络架构方面是一个绕不开的话题,只要接触深度学习多多少少会接触。

深度可分离卷积即Depthwise Separable Convolution,该卷积将一个常规卷积过程划分成两个完成:Depthwise卷积和Pointwise卷积,在保证输出一样时,计算量大大降低。

首先来看,一个常规卷积是怎么实现的。当我在pytorch定义一个卷积,该卷积接受一个3通道tensor,输出一个4通道tensor:

nn.Conv2d(in_channels=3,
          out_channels=4,
          kernel_size=3)

其示意图:在这里插入图片描述
我们计算一下参数量:parameters=3*3*3*4=108
推广来看,参数量为:parameters=kernel_size*kernel_size*in_channels*out_channels

如果我们从通道数变换的角度来看,卷积就是将3通道的tensor变为了4通道的tensor,我们来看看深度可分离卷积是怎么实现通道的变化的。

1、深度可分离卷积

深度可分离卷积实际上就是两步:depthwise卷积+pointwise卷积

我们知道点卷积(pointwise)的一大作用就是扩展通道和压缩通道,实际上我们可以直接在3通道的tensor上,直接使用点卷积来升维,将3通道变成4通道,但是这样做违背了卷积的本质。

卷积本质上就是通过卷积匀速提取特征,不同特征对应不同通道,所以改变了通道数。所以我们想要深度可分离卷积替代普通卷积,也需要进行卷积运算,然后改变通道数。

所以第一个阶段depthwise卷积就是进行卷积运算,第二个阶段pointwise卷积就是改变通道数,使符合预先定义的输出通道数。

下面两幅图分别就是depthwise卷积和pointwise卷积的示意图。

在这里插入图片描述

1.1 depthwise卷积

深度可分离卷积最难理解的应该就是depthwise卷积了,可能第一眼一看觉得挺简单的,但是如果用pytorch实现就麻烦了,因为又涉及到组卷积的概念。

关于组卷积的概念可以看分组卷积(Group Converlution),实际上depthwise卷积就是分组数=输入通道数=输出通道数的特殊分组卷积,那么可以看到depthwise卷积只是单独对每个通道进行卷积运算,但是没有设计跨通道的计算,这样无法进行完善的特征提取,而且depthwise卷积也没有改变通道数的能力

1.2 pointwise卷积

针对1.1中的问题,使用pointwise卷积即可实现。pointwise本质上就是一个普通卷积,只不过kernel_size=1而已。说实话没什么好说的。

2、代码实现

import torch
from torch import nn



class DSC(nn.Module):
    """
    深度可分离卷积:https://zhuanlan.zhihu.com/p/80041030 https://zhuanlan.zhihu.com/p/490685194
    先是depthwiseConv,本质上就是分组卷积,在深度可分离卷积中,分组卷积的组数=输入通道数=输出通道数,该部分通道数不变
    再是pointwisejConv,就是点卷积,该部分负责扩展通道数,所以其kernel_size=1,不用padding
    """
    def __init__(self, in_channel, out_channel, ksize=3,padding=1,bais=True):
        super(DSC, self).__init__()

        self.depthwiseConv = nn.Conv2d(in_channels=in_channel,
                                       out_channels=in_channel,
                                       groups=in_channel,
                                       kernel_size=ksize,
                                       padding=padding,
                                       bias=bais)
        self.pointwiseConv = nn.Conv2d(in_channels=in_channel,
                                       out_channels=out_channel,
                                       kernel_size=1,
                                       padding=0,
                                       bias=bais)

    def forward(self, x):
        out = self.depthwiseConv(x)
        out = self.pointwiseConv(out)
        return out

if __name__=="__main__":
    from torchsummary import summary
    dsc=DSC(in_channel=3,out_channel=8,ksize=3,padding=1,bais=False).cuda()
    summary(dsc,input_size=(3,48,48))

参数量为51,如果是普通卷积Conv2d(3,8,3),参数量为216(不加bias),可见参数量下降幅度很大。
在这里插入图片描述

参考

Depthwise卷积与Pointwise卷积

  • 3
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是一个对称矩阵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值