卷积层常用的方法与适用范围与深度可分离卷积详解

1. 标准卷积(Standard Convolution)

方法:

  • 使用固定的卷积核(滤波器)在输入特征图上滑动,提取局部特征。​

适用范围:

  • 图像分类:如在 AlexNet、VGGNet 中,标准卷积用于逐步提取图像的局部特征。
  • 通用特征提取:适用于大多数需要提取局部特征的任务。

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

方法:

  • 将标准卷积分解为两个独立的操作:
    1. 深度卷积(Depthwise Convolution):对每个输入通道单独进行卷积。
    2. 逐点卷积(Pointwise Convolution):使用 1×1 卷积核对深度卷积的输出进行组合。
  • 减少了计算量和参数数量。

适用范围:

  • 轻量级模型:如 MobileNet 和 EfficientNet,适用于移动设备和资源受限的环境。
  • 实时应用:如实时视频处理、移动设备上的图像识别。

3. 扩张卷积(Dilated Convolution)

方法:

  • 在卷积核中引入扩张率(Dilation Rate),扩大了卷积核的感受野,而不需要增加额外的参数。

适用范围:

  • 语义分割:如在 DeepLab 中,扩张卷积用于扩大感受野,捕捉更多上下文信息。
  • 图像生成:如在生成对抗网络(GAN)中,用于生成更高质量的图像。

4. 转置卷积(Transposed Convolution)

方法:

  • 用于上采样(Upsampling),通过卷积操作增加特征图的分辨率。
  • 常用于生成模型和语义分割任务中的上采样模块。

适用范围:

  • 语义分割:如在 U-Net 和 DeepLab 中,用于将特征图上采样到原始图像大小。
  • 生成模型:如在 GAN 的生成器中,用于生成高分辨率图像。

5. 分组卷积(Grouped Convolution)

方法:

  • 将输入通道分成多个组,每个组独立进行卷积操作。
  • 减少了计算量和参数数量,同时保持了特征的多样性。

适用范围:

  • 轻量级模型:如 ResNeXt,通过分组卷积提高模型的效率。
  • 多尺度特征提取:适用于需要处理多尺度特征的任务。

6. 混合精度卷积(Mixed Precision Convolution)

方法:

  • 使用不同的数据精度(如 FP16 和 FP32)进行卷积操作,减少计算量和内存占用,同时保持模型性能。

适用范围:

  • 大规模训练:在 GPU 和 TPU 上加速训练过程,同时减少内存占用。
  • 推理优化:在部署时使用混合精度,提高推理速度。

7. 3D 卷积(3D Convolution)

方法:

  • 在三维数据(如视频或体积数据)上进行卷积操作,捕捉时空特征。​

适用范围:

  • 视频分析:如在视频分类和目标检测中,捕捉时间维度的特征。
  • 医学图像分析:如在 CT 和 MRI 数据中,处理三维体积数据。

8. 可变形卷积(Deformable Convolution)

方法:

  • 在标准卷积的基础上引入可变形的采样点,能够捕捉不规则形状的特征。
  • 通过学习偏移量来调整卷积核的采样位置。

适用范围:

  • 目标检测:如在 Faster R-CNN 中,用于处理目标的不规则形状。
  • 语义分割:在复杂场景中,能够更好地捕捉物体的边界。

总结

卷积层的变体和方法多种多样,每种方法都有其独特的适用范围。选择合适的卷积方法取决于具体任务的需求,例如:
  • 效率优先:使用深度可分离卷积或分组卷积。
  • 扩大感受野:使用扩张卷积。
  • 上采样:使用转置卷积。
  • 处理视频或体积数据:使用 3D 卷积。

https://blog.csdn.net/zml194849/article/details/117021815

https://blog.csdn.net/m0_45267220/article/details/130291855

一些轻量级的网络,如mobilenet中,会有深度可分离卷积depthwise separable convolution,由depthwise(DW)和pointwise(PW)两个部分结合起来,用来提取特征feature map。相比常规的卷积操作,其参数数量和运算成本比较低。

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

逐通道卷积(Depthwise Convolution)
Depthwise Convolution的一个卷积核负责一个通道,一个通道只被一个卷积核卷积,这个过程产生的feature map通道数和输入的通道数完全一样。

一张5×5像素、三通道彩色输入图片(shape为5×5×3),Depthwise Convolution首先经过第一次卷积运算,DW完全是在二维平面内进行。卷积核的数量与上一层的通道数相同(通道和卷积核一一对应)。所以一个三通道的图像经过运算后生成了3个Feature map(如果有same padding则尺寸与输入层相同为5×5),如下图所示。(卷积核的shape即为:卷积核W x 卷积核H x 输入通道数)

 

 

其中一个Filter只包含一个大小为3×3的Kernel,卷积部分的参数个数计算如下(即为:卷积核Wx卷积核Hx输入通道数):

N_depthwise = 3 × 3 × 3 = 27

计算量为(即:卷积核W x 卷积核H x (图片W-卷积核W+1) x (图片H-卷积核H+1) x 输入通道数)

C_depthwise=3x3x(5-2)x(5-2)x3=243

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

逐点卷积(Pointwise Convolution)
Pointwise Convolution的运算与常规卷积运算非常相似,它的卷积核的尺寸为 1×1×M,M为上一层的通道数。所以这里的卷积运算会将上一步的map在深度方向上进行加权组合,生成新的Feature map。有几个卷积核就有几个输出Feature map。(卷积核的shape即为:1 x 1 x 输入通道数 x 输出通道数)

 

 

由于采用的是1×1卷积的方式,此步中卷积涉及到的参数个数可以计算为(即为:1 x 1 x 输入通道数 x 输出通道数):

N_pointwise = 1 × 1 × 3 × 4 = 12

计算量(即为:1 x 1 x 特征层W x 特征层H x 输入通道数 x 输出通道数):

C_pointwise = 1 × 1 × 3 × 3 × 3 × 4 = 108

经过Pointwise Convolution之后,同样输出了4张Feature map,与常规卷积的输出维度相同。

四、参数对比
回顾一下,常规卷积的参数个数为:

N_std = 4 × 3 × 3 × 3 = 108

Separable Convolution的参数由两部分相加得到:

N_depthwise = 3 × 3 × 3 = 27

N_pointwise = 1 × 1 × 3 × 4 = 12

N_separable = N_depthwise + N_pointwise = 39

相同的输入,同样是得到4张Feature map,Separable Convolution的参数个数是常规卷积的约1/3。因此,在参数量相同的前提下,采用Separable Convolution的神经网络层数可以做的更深。

五、计算量对比
回顾一下,常规卷积的计算量为:

C_std =3*3*(5-2)*(5-2)*3*4=972

Separable Convolution的计算量由两部分相加得到:

C_depthwise=3x3x(5-2)x(5-2)x3=243

C_pointwise = 1 × 1 × 3 × 3 × 3 × 4 = 108

C_separable = C_depthwise + C_pointwise = 351

相同的输入,同样是得到4张Feature map,Separable Convolution的计算量是常规卷积的约1/3。因此,在计算量相同的情况下,Depthwise Separable Convolution可以将神经网络层数可以做的更深。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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

  

posted @   yinghualeihenmei  阅读(382)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示