TransposeConv
1、简介
首先回顾一下普通卷积, 下图是以stride=1, padding=0, kernel_size=3为例, 假设输入特征图大小为4×4(假设输入输出都是单通道), 通过卷积后的特征图大小为2×2, 一般使用卷积的情况中, 要是特征图变小(stride>1), 要么保持不变(stride=1), 当然也可以通过四周padding让特征图变大但是没有意义。
2、转置卷积
转置卷积主要起到上采样的作用, 但转置卷积不是卷积的逆运算(一般卷积操作是不可逆的), 它只能恢复到原来的大小, 数值与原来的不一样。转置卷积的运算步骤可以归纳为以下几点:
在输入特征图元素间填充s-1行, 列0(其中s是转置卷积的步距)
在输入特征图四周填充p-1行, 列0(其中k表示转置卷积的kernel_size大小, p为转置卷积的padding, 注意这里的padding和卷积操作有些不同)
将卷积核参数上下、左右翻转
做正常卷积运算(填充0, 步距1)
下面假设输入的特征图为2×2(假设输入输出为单通道), 通过转置卷积后的的得到4×4大小的特征图。 这里使用的转置卷积核大小k=3, stride=1, padding=0的情况(忽略偏置bias)
首先在元素间填充s-1=0行,列0
然后再特征图四周填充k-p-1=2行, 列0
接着对卷积核参数进行上下, 左右翻转
最后做正常卷积(填充0, 步距1) transpose_conv.jpg
下面展示了不同转置卷积中不同s和p的情况 transpose_conv_s2_p0_k3.gif transpose_conv_s1_p0_k3.gif transpose_conv_s2_p1_k3.gif
![]() s=1, p=0, k=3
间隙填充s-1=0,四周填充k-p-1=2
|
![]() s=2, p=0, k=3
间隙填充s-1=1,四周填充k-p-1=2
|
![]() s=2, p=1, k=3
间隙填充s-1=1,四周填充k-p-1=1
|
转置卷积操作后特征图的大小可以通过如下公式进行计算:
其中stride[0]表示高度方向的stride, padding[0]表示高度方向的padding, kernel_size[0]表示高度方向的kernel_size, 同理[1]表示宽度方向上的。 通过上面的公式可以看出, padding越大,输出特征矩阵的高宽越小。 你可以理解为正向传播过程中进行了padding然后得到了特征图, 现在使用转置卷积还原到原来的高宽后要把原来的padding减掉。
3、pytorch中转置卷积参数
pytorch官方关于转置卷积的ConvTranspose2d的文档。
Applied a 2D transposed convolution operator over an input image composed of several input planes. This module can be seen as the gradient of Conv2d with respect to its input. It is also known as a fractionally-strided convolution or a deconvolution (althought it is not an actual deconvolution operation). image-20231107093032555.png
官方的介绍中还有如下几个参数:
output_padding: 在计算得到的输出特征图的高、宽各方向各填充几行或列0(注意:这里只是在上下以及左右的一侧one side填充,并不是两侧头填充)
groups: 当使用到组卷积时才会用到的参数, 默认为1即为普通卷积
bias: 是否使用偏置, 默认为True使用
dilation: 当使用空洞卷积(膨胀卷积)时才会使用到的参数, 默认为1即为普通卷积。
输出特征图高、宽计算
4、pytorch转置卷积实验
下面使用pytorch模拟s=1, p=0, k=3的转置卷积操作
在代码中transpose_conv_official函数是通过官方的转置卷积进行计算, transpose_conv_self是按照上面的介绍对输入特征图进行填充并通过卷积得到的结果。
1 | # !/usr/bin/env python |
终端输出:
1 | feature_map |