您现在的位置是:首页 >技术教程 >深度可分离卷积及其代码实现网站首页技术教程

深度可分离卷积及其代码实现

倒霉蛋小马 2026-06-29 12:01:04
简介深度可分离卷积及其代码实现

参考笔记:

卷积层的参数量和计算量_卷积层参数量计算公式-CSDN博客

 深度可分离卷积及其代码实现_深度可分离卷积代码-CSDN博客

深度可分离卷积(Depthwise seperable convolution)-CSDN博客


目录

1.普通卷积操作

2. 深度可分离卷积(Depthwise separable convolution)

2.1 原理

2.2 参数量、计算量对比

2.3 代码实现


1.普通卷积操作

普通卷积

假设输入为[Channel,H,W] = [3,3,3],下面所有的卷积例子设置padding=1,使得卷积后特征图尺寸不变

普通卷积:in_channel=3,out_channel=4

所以这里需要4个卷积核(输出几个通道就要几个卷积核,这里输出4个通道所以需要4个卷积核),每个卷积核的shape是3 x 3 x 3

普通卷积层的参数量为:卷积核W x 卷积核H x 输入通道数 x 输出通道数 = 3 x 3 x 3 x 4 = 108个参数

普通卷积层的计算量为:卷积核W x 卷积核H x 输出图片W x 输出图片H x 输入通道数 x 输出通道数 = 3 x 3 x 3 x 3 x 3 x 4  = 972 

2. 深度可分离卷积(Depthwise separable convolution)

 一些轻量级的网络,如MobileNet中,会有深度可分离卷积Depthwise separable convolution。由Depthwise(DW)和Pointwise(PW)两个部分结合起来,用来提取特征feature map。相比常规的卷积操作,可以显著减少参数量和计算量

2.1 原理

深度可分离卷积可分为两个过程,分别为逐通道卷积(Depthwise Convolution)和逐点卷积(Pointwise Convolution)

  • 逐通道卷积(Depthwise Convolution)

Depthwise Convolution的一个卷积核负责一个通道,一个通道只被一个卷积核卷积,这个过程产生的feature map通道数和输入的通道数完全一样,如下图所示

逐通道卷积

in_channel=3,out_channel=3,卷积核个数为3,每个卷积核的shape为1 x 3 x 3

逐通道卷积层的参数量为:卷积核W x 卷积核H x 输入通道数 = 3 x 3 x 3 = 27个参数

逐通道卷积层的计算量为:卷积核W x 卷积核H x 输出图片W x 输出图片H x 输入通道数  = 3 x 3 x 3 x 3 x 3  = 243

Depthwise Convolution完成后的feature map通道数与输入通道数相同,无法扩展feature map。而且这种运算对输入的每个通道独立进行卷积运算,没有有效的利用不同通道在相同空间位置上的特征信息。因此需要Pointwise Convolution来将这些Feature map进行组合生成新的Feature map

  • 逐点卷积(Pointwise Convolution)

Pointwise Convolution与普通卷积非常相似,它的卷积核的尺寸为 1×1×MM为逐通道卷积输出特征图的通道数。所以这里的卷积运算会将逐通道卷积层输出的feature map在深度方向上进行加权组合,生成新的feature map

逐点卷积

in_channel=3,out_channel=4,卷积核个数为4,每个卷积核的shape为3 x 1 x 1

逐点卷积层的参数量为:卷积核W x 卷积核H x 输入通道数 x 输出通道数 = 1 x 1 x 3 x 4  = 12个参数

逐点卷积层的计算量为:卷积核W x 卷积核H x 输出图片W x 输出图片H x 输入通道数 x 输出通道数 = 1 x 1 x 3 x 3 x 3 x 4  = 108

经过Pointwise Convolution之后,同样输出了通道数为4feature map,与常规卷积的输出维度相同

上面两步合起来就是如下图:

Depthwise separable convolution

2.2 参数量、计算量对比

  • 常规卷积
    • 参数量:108
    • 计算量:972
  • 深度可分离卷积
    • 参数量:39 = 27 + 12
    • 计算量:351 = 243 + 108

相同的输入,同样是得到输出通道数为4的feature map,深度可分离卷积的参数量和计算量是常规卷积的约1/3

2.3 代码实现

代码实现非常简单,关于nn.Conv2d的groups参数的作用在下面介绍

#深度可分离卷积
class DepthWiseConv(nn.Module):
    def __init__(self, in_channel, out_channel):
        super(DepthWiseConv, self).__init__()

        #逐通道卷积
        self.depth_conv = nn.Conv2d(in_channels=in_channel,
                                    out_channels=in_channel,
                                    kernel_size=3,
                                    stride=1,
                                    padding=1,
                                    groups=in_channel#逐通道做卷积
                                    )

        #逐点卷积,卷积核大小必须为1
        self.point_conv = nn.Conv2d(in_channels=in_channel,
                                    out_channels=out_channel,
                                    kernel_size=1,
                                    stride=1,
                                    padding=0,
                                    groups=1)

    #前向传播,逐通道卷积+逐点卷积
    def forward(self, x):
        return self.point_conv(self.depth_conv)

3. nn.Conv2d的groups参数

在 PyTorch 的 nn.Conv2d 中,groups 参数用于定义分组卷积(Grouped Convolution)。分组卷积允许我们将输入特征图的通道分成多个组并分别进行卷积计算

  • 基本定义:

        groups 代表将输入通道分成 groups 组进行卷积操作

        当 groups = 1 时,表示普通的卷积操作

        当 groups > 1 时,输入通道将被分成 groups 组,每组的输入通道进行独立的卷积计算

  • 计算方式:

        如果 in_channel 为输入通道数,out_channel 为输出通道数,且 groups = g ,那么会将输入通道分成 g 组,每组处理 in_channel 个通道

        每个组使用独立的卷积核进行卷积操作,这样可以减少参数量和计算复杂度

  • 示例:

        假设有一个输入 x in_channel = 8 ,希望输出 4 个通道,并且设置 groups = 4 ,这意味着输入的 8 个通道将被分成 4 组。每组包含 2 个输入通道,同时卷积得到 1 个输出通道

import torch
import torch.nn as nn

#创建分组卷积层
conv = nn.Conv2d(in_channels=8,
                 out_channels=4,
                 groups=4,
                 kernel_size=3,
                 stride=1,
                 padding=1)

#批次大小为1,通道数为8,大小为32x32
x = torch.randn(1, 8, 32, 32)

#分组卷积
out = conv(x)

#shape = (1, 4, 32, 32)
print(out.shape)

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。