【DL学习笔记】各种卷积操作总结(深度可分离、空洞、转置、可变形)

发布于:2025-08-04 ⋅ 阅读:(17) ⋅ 点赞:(0)

Vanilla Convolution 普通卷积

在这里插入图片描述
卷积通道数:

  • 卷积核的数量决定输出的张量的通道数 n n n,输入的张量和每一个核Kernel做卷积运算得到一个channel的输出。
  • 输入通道数 C i n C_{in} Cin决定每一个卷积核的通道数

卷积输出feature map的尺寸的计算公式:

  • W _ o u t = W i n + 2 P w − K w S w + 1 W\_out = \frac{W_{in} + 2P_w - K_w}{S_w} + 1 W_out=SwWin+2PwKw+1
  • H _ o u t = H i n + 2 P h − K h S h + 1 H\_out = \frac{H_{in} + 2P_h - K_h}{S_h} + 1 H_out=ShHin+2PhKh+1

其中,输入的尺寸为 ( W in , H in ) (W_{\text{in}}, H_{\text{in}}) (Win,Hin),卷积核的尺寸为 ( K w , K h ) (K_w, K_h) (Kw,Kh),步幅为 ( S w , S h ) (S_w, S_h) (Sw,Sh),填充为 ( P w , P h ) (P_w, P_h) (Pw,Ph),输出的尺寸为 ( W out , H out ) (W_{\text{out}}, H_{\text{out}}) (Wout,Hout)

Group Convolution 分组卷积

Group convolution(分组卷积)最早是在AlexNet(Alex Krizhevsky等人于2012年提出的深度神经网络模型)中引入的。在 AlexNet中,作者们使用了分组卷积来将计算分布到多个GPU上。

计算

在这里插入图片描述

Group Convolution :将输入的 feature map张量 在 channel 的维度上进行分组,然后再对每个分组 分别进行卷积操作,再将各个输出沿channel维度拼接在一起。

参数量

Group Convolution 优点为可减小参数量。

如下图,假设输入尺寸为 C i n × H × W C_{in} \times H \times W Cin×H×W,卷积核尺寸为 K × K K \times K K×K,输出的 Channel 数为 n n n,我们对于相同的输入和输出尺寸,分别使用 普通卷积 和 分组卷积来进行操作,并对比两种卷积方式的参数量。

在这里插入图片描述

  • 普通卷积:每个Kernel参数量为 K × K × C i n K \times K \times C_{in} K×K×Cin 一共有 n n n个Kernel,总共参数量为:
    K × K × C i n × n K \times K \times C_{in} \times n K×K×Cin×n
  • 分组卷积:将输入分为 g g g个组,每个组进入普通卷积的channel数为 C i n g \frac{C_{in}}{g} gCin,要保证最后沿channel维度拼接后为 n n n,所以每个普通卷积的数维度为 n g \frac{n}{g} gn,所以每个组用的卷积核参数量为 K × K × C i n g × n g K \times K \times \frac{C_{in}}{g} \times \frac{n}{g} K×K×gCin×gn,一共 g g g个组,所以总参数量为:
    ( K × K × C i n g × n g ) × g = K × K × C i n × n g (K \times K \times \frac{C_{in}}{g} \times \frac{n}{g} ) \times g = K \times K \times C_{in}\times \frac{n}{g} (K×K×gCin×gn)×g=K×K×Cin×gn

所以分组卷积是普通卷积参数量的 1 g \frac{1}{g} g1

代码实现

  • 使用普通卷积方法 torch.nn.conv2d(),通过参数 groups 指定组数
  • 注意:in_channelsout_channels 都必须可以被 groups 整除,否则会报错, 类似 :ValueError: in_channels must be divisible by groups
import torch
import torch.nn as nn

conv = nn.Conv2d(in_channels=10, out_channels=15, kernel_size=3, groups=5, stride=1, padding=1)
output = conv(torch.rand(1, 10, 20, 20))
print(output.shape)   # torch.Size([1, 15, 20, 20])

Depth-wise Convolution 逐深度卷积

是分组卷积的特例:当Group Convolution 的分组数量 g g g 最大,等于输入channel 数 C i n C_{in} Cin时,就变为了 Depth-wise Convolution逐深度卷积。

计算

将输入的每个通道(channel)独立地进行 普通卷积运算( C i n C_{in} Cin C o u t C_{out} Cout都为1),每个通道使用一个单独的卷积核进行处理,即为 DWConvolution

具体做法如下:

  • 将输入特征图按照 channel 进行分组,每个 channel 一个组,即 g = C i n g = C_{in} g=Cin
  • 每个 channel (即每个 group ) 使用一个独立的卷积核(大小为 1 × k × k 1 \times k \times k 1×k×k )对其对应通道做卷积运算,输入输出通道均为 1

在这里插入图片描述

和Group Convolution的优点一样,参数量和计算量小。

代码实现

nn.Conv2d 的参数 out_channelsgroups 都设置为等于 in_channels

import torch
import torch.nn as nn

conv = nn.Conv2d(in_channels=10, out_channels=10, kernel_size=3, groups=10, stride=1, padding=1)
output = conv(torch.rand(1, 10, 20, 20))
print(output.shape)   # torch.Size([1, 10, 20, 20])

Point-wise Convolution 逐点卷积

是特殊的普通卷积,kernel_size=1x1,也就是我们经常看到的一乘一卷积 conv 1x1
因为感受野是1x1,没有融合垂直于channl维度的平面上的信息,所以它通常用来组合每个像素各个通道之间的特征信息。
在这里插入图片描述

优点 :参数量和计算量小

代码实现:将 nn.Conv2d 的参数 kernel_size 设置为等于 1

import torch
import torch.nn as nn

conv = nn.Conv2d(in_channels=10, out_channels=10, kernel_size=1, stride=1)
output = conv(torch.rand(1, 10, 20, 20))
print(output.shape)   # torch.Size([1, 10, 20, 20])

Depth-wise Separable Convolution 深度可分离卷积

提出背景

Depth-wise Separable Convolution(深度可分离卷积)最早是由Google的研究团队在2014年提出的。该方法首次出现在论文《MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications》中。

计算

Depth-wise Separable Convolution 是

  • 先做一个 Depth-wise Convolution ,后面再做一个 Point-wise Convolution
  • 或者 先做一个 Depth-wise Convolution ,后面再做一个 Point-wise Convolution

计算量

Depth-wise Separable Convolution 的优势是 极大的减小了卷积的计算量。

这里还是对于相同的输入和输出尺寸,对比普通卷积核深度可分离卷积的计算量。
输入尺寸 D F × D F × M D_F\times D_F \times M DF×DF×M,输出通道数为 N N N

1、普通卷积计算量

在这里插入图片描述
对于普通卷积,计算量公式:
D k ⋅ D k ⋅ M ⋅ N ⋅ D F ⋅ D F (1) D_k \cdot D_k \cdot M \cdot N \cdot D_F \cdot D_F \tag{1} DkDkMNDFDF(1)

2、深度可分离卷积(Depth-wise Separable Convolution)计算量

在这里插入图片描述

计算量分为两部分:

  • Depth-wise 卷积:计算量为 D k ⋅ D k ⋅ M ⋅ D F ⋅ D F D_k \cdot D_k \cdot M \cdot D_F \cdot D_F DkDkMDFDF
  • Point-wise 卷积:计算量为 ( 1 ⋅ 1 ⋅ M ⋅ D F ⋅ D F ) ⋅ N (1\cdot 1\cdot M \cdot D_F \cdot D_F) \cdot N (11MDFDF)N

深度可分离卷积计算量公式:
D k ⋅ D k ⋅ M ⋅ D F ⋅ D F + M ⋅ N ⋅ D F ⋅ D F (2) D_k \cdot D_k \cdot M \cdot D_F \cdot D_F + M \cdot N \cdot D_F \cdot D_F \tag{2} DkDkMDFDF+MNDFDF(2)

3、计算量对比(公式(2) ÷ 公式(1))

为对比普通卷积与深度可分离卷积的计算量,用作商法比大小,将公式(2)除以公式(1),推导得:

D k ⋅ D k ⋅ M ⋅ D F ⋅ D F + M ⋅ N ⋅ D F ⋅ D F D k ⋅ D k ⋅ M ⋅ N ⋅ D F ⋅ D F = 1 N + 1 D k 2 (3) \frac{D_k \cdot D_k \cdot M \cdot D_F \cdot D_F + M \cdot N \cdot D_F \cdot D_F}{D_k \cdot D_k \cdot M \cdot N \cdot D_F \cdot D_F} = \frac{1}{N} + \frac{1}{D_k^2} \tag{3} DkDkMNDFDFDkDkMDFDF+MNDFDF=N1+Dk21(3)

4、典型场景( D k = 3 D_k = 3 Dk=3,即 3×3 卷积)

实际常用 3×3 卷积( D k = 3 D_k = 3 Dk=3 ),代入公式(3)得:

1 N + 1 D k 2 = 1 N + 1 9 \frac{1}{N} + \frac{1}{D_k^2} = \frac{1}{N} + \frac{1}{9} N1+Dk21=N1+91

5、结论

理论上,普通卷积计算量是深度可分离卷积的 8~9 倍(因 N N N为输出channel数往往很大,所以 1 N \frac{1}{N} N1 通常很小,主导项为 $ \frac{1}{9} $ ,故整体约为 9 倍 )。

Dilation/Atrous Convolution 膨胀卷积/空洞卷积

计算与代码实现

  • 普通卷积输出的每个像素是输入的连续的像素与卷积核运算得到的。
  • 膨胀卷积输出的每个像素是输入的有间隔的像素与Kernel运算得到的。

在这里插入图片描述

作用:增大卷积核的感受野。
感受野(Receptive Field)指CNN网络中,每个特征图的每个像素点对应输入图像的区域大小。

代码实现:指定nn.Conv2d()的膨胀率参数 dilation

  • 当 dilation=1 时,没有间隔,是普通卷积
  • 当 dilation=2 时,卷积核元素中间间隔一个像素
import torch
import torch.nn as nn

conv = nn.Conv2d(in_channels=10, out_channels=10, kernel_size=3, stride=1, padding=2, dilation=2)
output = conv(torch.rand(1, 10, 20, 20))
print(output.shape)   # torch.Size([1, 10, 20, 20])

padding参数设置

在这里插入图片描述
在这里插入图片描述
要保证输入输出的大小尺寸不变

  • 普通卷积:步长stride=1,填充padding=1,即原图多加一圈像素。
  • 膨胀卷积:步长stride=1,填充padding=2,加两圈像素。

缺点:网格效应Gridding Effect

由于膨胀卷积是一种稀疏的采样方式,当多个膨胀卷积叠加时,有些像素根本没有被利用到,会损失信息的连续性与相关性,进而影响分割、检测等要求较高的任务。

比如这里连续用了两次膨胀卷积得到的feature map中的一个绿色的像素,回溯回去是由紫色像素得到的。所以如果整个网络只有两层膨胀卷积的话,相当于只有原图的四分之一的像素用到了。
在这里插入图片描述

Transposed Convolution 转置卷积

转置卷积也是卷积,只不过转置卷积 是一种上采样操作
如下图的转置卷积所示,输入图像尺寸为 2x2, 输出图像的尺寸为 4x4。
在这里插入图片描述

参数设置

如何设置 转置卷积 的 stride 和 padding
在这里插入图片描述

已知 input 和 kernel 求 output

在这里插入图片描述

Deformable Convolution 可变形卷积

论文:《Deformable Convolutional Networks》

普通卷积公式:
y ( p 0 ) = ∑ p n ∈ R w ( p n ) ⋅ x ( p 0 + p n ) \mathbf{y}(\mathbf{p}_0) = \sum_{\mathbf{p}_n \in \mathcal{R}} \mathbf{w}(\mathbf{p}_n) \cdot \mathbf{x}(\mathbf{p}_0 + \mathbf{p}_n) y(p0)=pnRw(pn)x(p0+pn)

  • y ( p 0 ) \boldsymbol{y(p_0)} y(p0):输出特征图在位置 p 0 \boldsymbol{p_0} p0 处的值
  • w ( p n ) \boldsymbol{w(p_n)} w(pn):卷积核(权重)在位置 p n \boldsymbol{p_n} pn 处的参数
  • x ( p 0 + p n ) \boldsymbol{x(p_0 + p_n)} x(p0+pn):输入数据在位置 p 0 + p n \boldsymbol{p_0 + p_n} p0+pn 处的原始值
  • R \mathcal{R} R:卷积核的作用范围(即卷积核覆盖的所有位置集合,决定卷积的“视野”)

简单说,就是输出位置的值 = 卷积核权重与输入对应区域的加权求和

可变性卷积公式: y ( p 0 ) = ∑ p n ∈ R w ( p n ) ⋅ x ( p 0 + p n + Δ p n ) \mathbf{y}(\mathbf{p}_{0})=\sum_{\mathbf{p}_{n}\in\mathcal{R}}\mathbf{w}(\mathbf{p}_{n})\cdot\mathbf{x}(\mathbf{p}_{0}+\mathbf{p}_{n}+\Delta\mathbf{p}_{n}) y(p0)=pnRw(pn)x(p0+pn+Δpn)

  • y ( p 0 ) \mathbf{y}(\mathbf{p}_0) y(p0):输出特征图在位置 p 0 \mathbf{p}_0 p0 处的像素值
  • R \mathcal{R} R:卷积核的固定感受野范围(如 3×3 卷积的 9 个位置集合)
  • w ( p n ) \mathbf{w}(\mathbf{p}_n) w(pn):卷积核在固定位置 p n \mathbf{p}_n pn 处的权重参数
  • x ( ⋅ ) \mathbf{x}(\cdot) x():输入特征图
  • Δ p n \Delta\mathbf{p}_n Δpn:偏移量表示卷积核第 n n n 个采样点相对于固定位置 p n \mathbf{p}_n pn 的偏移。偏移量 Δ p n \Delta\mathbf{p}_n Δpn是学习到的值,是浮点型数据,由图像经过普通卷积计算得到。

网站公告

今日签到

点亮在社区的每一天
去签到