深入浅出理解转置卷积Conv2DTranspose

news2024/11/25 18:57:45

温故而知新,可以为师矣!

一、参考资料

论文:A guide to convolution arithmetic for deep learning
github源码:Convolution arithmetic
bilibili视频:转置卷积(transposed convolution)
转置卷积(Transposed Convolution)
【keras/Tensorflow/pytorch】Conv2D和Conv2DTranspose详解
怎样通俗易懂地解释反卷积?
抽丝剥茧,带你理解转置卷积(反卷积)

二、标准卷积(Conv2D)

在这里插入图片描述

1. Conv2D 计算公式

标准卷积计算公式有:
o = i + 2 p − k s + 1 i = size   of   input o = size   of   output p = p a d d i n g k = size   of   kernel s = s t r i d e s o=\frac{i+2p-k}s+1 \quad \begin{array}{l} \\i=\textit{size of input}\\o=\textit{size of output}\\p=padding\\k=\textit{size of kernel}\\s=strides\end{array} o=si+2pk+1i=size of inputo=size of outputp=paddingk=size of kernels=strides

以特征图的高度Height为例,经过卷积操作之后,输出特征图计算公式为:
H o u t = H i n + 2 p − k s + 1 ( 1 ) H_{out}=\frac{H_{in}+2p-k}s+1\quad(1) Hout=sHin+2pk+1(1)

2. Conv2D中的步长stride

2.1 当步长stride=1,p=0,k=3

在这里插入图片描述

输入特征图(蓝色): ( H i n , W i n ) = ( 4 , 4 ) (H_{in},W_{in})=(4,4) (Hin,Win)=(4,4)
标准卷积核: k e r n e l _ s i z e ( k ) = 3 , s t r i d e ( s ) = 1 , p a d d i n g = 0 kernel\_size(k)=3,stride(s)=1,padding=0 kernel_size(k)=3,stride(s)=1padding=0
输出特征图(绿色): ( H o u t , W o u t ) = ( 2 , 2 ) (H_{out},W_{out})=(2,2) (Hout,Wout)=(2,2)

代入 公式 ( 1 ) 公式(1) 公式(1)中,可得:
H o u t = H i n + 2 p − K S + 1 H o u t = 4 + 2 ∗ 0 − 3 1 + 1 = 2 H_{out}=\frac{H_{in}+2p-K}S+1\\ H_{out}=\frac{4+2*0-3}1+1=2 Hout=SHin+2pK+1Hout=14+203+1=2

2.2 当步长stride=2,p=1,k=3

在这里插入图片描述

输入特征图(蓝色): ( H i n , W i n ) = ( 5 , 5 ) (H_{in},W_{in})=(5,5) (Hin,Win)=(5,5)
标准卷积核: k e r n e l _ s i z e ( k ) = 3 , s t r i d e ( s ) = 2 , p a d d i n g = 1 kernel\_size(k)=3,stride(s)=2,padding=1 kernel_size(k)=3,stride(s)=2padding=1
输出特征图(绿色): ( H o u t , W o u t ) = ( 3 , 3 ) (H_{out},W_{out})=(3,3) (Hout,Wout)=(3,3)

代入 公式 ( 1 ) 公式(1) 公式(1)中,可得:
H o u t = H i n + 2 p − k s + 1 H o u t = 5 + 2 ∗ 1 − 3 2 + 1 = 3 H_{out}=\frac{H_{in}+2p-k}s+1\\ H_{out}=\frac{5+2*1-3}2+1=3 Hout=sHin+2pk+1Hout=25+213+1=3

三、转置卷积(Conv2DTranspose)

1. 引言

对于很多生成模型(如语义分割、自动编码器(Autoencoder)、GAN中的生成器等模型),我们通常希望进行与标准卷积相反的转换,即执行上采样。对于语义分割,首先用编码器提取特征图,然后用解码器恢复原始图像大小,这样来分类原始图像的每个像素。

实现上采样的传统方法是应用插值方案或人工创建规则。而神经网络等现代架构则倾向于让网络自动学习合适的变换,无需人类干预。为了做到这一点,我们可以使用转置卷积。

2. 对转置卷积名称的误解

This operation is sometimes called “deconvolution” after (Zeiler et al., 2010), but is really the transpose (gradient) of atrous_conv2d rather than an actual deconvolution.
Deconvolutional Networks: Zeiler et al., 2010 (pdf)

转置卷积又叫反卷积(deconv or deconvolution)、逆卷积。然而,转置卷积是目前最为正规和主流的名称,因为这个名称更加贴切的描述了Conv2DTranspose 的计算过程,而其他的名字容易造成误导。在主流的深度学习框架中,如TensorFlow,Pytorch,Keras中的函数名都是 conv_transpose。所以,学习转置卷积之前,我们一定要弄清楚标准名称,遇到他人说反卷积、逆卷积也要帮其纠正,让不正确的命名尽早的淹没在历史的长河中。

我们先说一下为什么人们很喜欢将转置卷积称为反卷积或逆卷积。首先举一个例子,将一个4x4的输入通过3x3的卷积核在进行普通卷积(无padding, stride=1),将得到一个2x2的输出。而转置卷积将一个2x2的输入通过同样3x3大小的卷积核将得到一个4x4的输出,看起来似乎是普通卷积的逆过程。就好像是加法的逆过程是减法,乘法的逆过程是除法一样,人们自然而然的认为这两个操作似乎是一个可逆的过程。转置卷积不是卷积的逆运算(一般卷积操作是不可逆的),转置卷积也是卷积。转置卷积并不是正向卷积的完全逆过程(逆运算),它不能完全恢复输入矩阵的数据,只能恢复输入矩阵的大小(shape)。所以,转置卷积的名字就由此而来,而并不是“反卷积”或者是“逆卷积”,不好的名称容易给人以误解。

有些地方,转置卷积又被称作 fractionally-strided convolution或者deconvolution,但 deconvolution 具有误导性,不建议使用。因此,本文将会使用 Conv2DTransposefractionally-strided convolutions 两个名字,分别对应代码版学术论文版

I think transpose_conv2d or conv2d_transpose are the cleanest names.

3. Conv2DTranspose的概念

转置卷积(Transposed Convolution)语义分割或者==对抗神经网络(GAN)==中比较常见,其主要作用是做上采样(UpSampling)。
在这里插入图片描述

4. Conv2DConv2DTranspose对比

转置卷积和标准卷积有很大的区别,直接卷积是用一个“小窗户”去看一个“大世界”,而转置卷积是用一个“大窗户”的一部分去看“小世界”。

标准卷积(大图变小图)中,输入(5,5),步长(2,2),输出(3,3)。

在这里插入图片描述

转置卷积操作中(小图变大图),输入(3,3)输出(5,5)。
在这里插入图片描述

5. Conv2DTranspose计算过程

转置卷积核大小为k,步长s,填充p,则转置卷积的计算步骤可以总结为三步:

  1. 第一步:计算新的输入特征图;
  2. 第二步:计算转置卷积核;
  3. 第三步:执行标准卷积操作。

5.1 第一步:计算新的输入特征图

对输入特征图 M M M 进行 插值(interpolation) 零元素,得到新的输入特征图 M ′ M^{\prime} M

以特征图的高度Height为例,输入特征图的Height高为 H i n H_{in} Hin ,中间有 ( H i n − 1 ) (H_{in}-1) (Hin1) 个空隙。
两个相邻位置中间的插值零元素的个数: s − 1 s-1 s1 s s s 表示步长。
Height方向上总共插值零元素的个数: ( H i n − 1 ) ∗ ( s − 1 ) (H_{in}-1) * (s-1) (Hin1)(s1)
新的输入特征图大小 H i n ′ = H i n + ( H i n − 1 ) ∗ ( s − 1 ) H_{in}^{\prime} = H_{in} + (H_{in}-1)*(s-1) Hin=Hin+(Hin1)(s1)

5.2 第二步:计算转置卷积核

对标准卷积核 K K K进行上下、左右翻转,得到转置卷积核 K ′ K^{\prime} K

已知:
标准卷积核大小: k k k,
标准卷积核stride: s s s,
标准卷积核padding: p p p

  1. 转置卷积核大小: k ′ = k k^{\prime}=k k=k
  2. 转置卷积核stride: s ′ = 1 s^{\prime}=1 s=1该值永远为1
  3. 转置卷积核padding: p ′ = k − p − 1 p^{\prime} = k-p-1 p=kp1该公式是如何产生的,下文有解释。
    在这里插入图片描述

5.3 第三步:执行标准卷积操作

转置卷积核新的输入特征图进行标准卷积操作,得到的结果就是转置卷积的结果。

根据标准卷积的计算公式可知:
H o u t = ( H i n ′ + 2 p ′ − k ′ ) s ′ + 1 ( 2 ) \mathrm{H_{out}}=\frac{(\mathrm{H_{in}^{\prime}}+2\mathrm{p^{\prime}}-k^{\prime})}{\mathrm{s^{\prime}}}+1\quad(2) Hout=s(Hin+2pk)+1(2)

H ′ = H i n + ( H i n − 1 ) ∗ ( s − 1 ) H^{\prime} = H_{in} + (H_{in}-1)*(s-1) H=Hin+(Hin1)(s1)
k ′ = k k^{\prime}=k k=k,
s ′ = 1 s^{\prime}=1 s=1,
p ′ = k − p − 1 p^{\prime} = k-p-1 p=kp1

将第一、二步中变换的结果代入上式,可得:
H o u t = ( H i n + H i n ∗ s − H − s + 1 ) + 2 ∗ ( k − p − 1 ) − k s ′ + 1 ( 3 ) \text{H}_{out}=\frac{(\text{H}_{in}+\text{H}_{in}*s-\text{H}-\text{s}+1)+2*(\text{k}-\text{p}-1)-\text{k}}{\text{s}'}+1\quad(3) Hout=s(Hin+HinsHs+1)+2(kp1)k+1(3)
化简,可得:
H o u t = ( H i n − 1 )*s + k − 2 p − 1 s ′ + 1 ( 4 ) \text{H}_{out}=\frac{(\text{H}_{in}-1\text{)*s}+\text{k}-2\text{p}-1}{\text{s}'}+1\quad(4) Hout=s(Hin1)*s+k2p1+1(4)
上式中,分母步长 s ′ = 1 s^{\prime}=1 s=1,则最终结果为:
H o u t = ( H i n − 1 ) ∗ s − 2 p + k ( 5.1 ) \mathrm{H}_{out}=(\mathrm{H}_{in}-1)*\text{s}-2\text{p}+\mathrm{k}\quad(5.1) Hout=(Hin1)s2p+k(5.1)

综上所述,可以求得特征图Height和Width两个方向上进行转置卷积计算的结果:
H o u t = ( H i n − 1 ) × s t r i d e [ 0 ] − 2 × p a d d i n g [ 0 ] + k e r n e l _ s i z e [ 0 ] W o u t = ( W i n − 1 ) × s t r i d e [ 1 ] − 2 × p a d d i n g [ 1 ] + k e r n e l _ s i z e [ 1 ] H_{out}=(H_{in}−1)×stride[0]−2×padding[0]+kernel\_size[0]\\ W_{out}=(W_{in}−1)×stride[1]−2×padding[1]+kernel\_size[1] Hout=(Hin1)×stride[0]2×padding[0]+kernel_size[0]Wout=(Win1)×stride[1]2×padding[1]+kernel_size[1]

5.4 Conv2DTranspose示例

在这里插入图片描述

输入特征图 M M M H i n = 3 H_{in}=3 Hin=3
标准卷积核 K K K k = 3 , s = 2 , p = 1 k=3,s=2, p=1 k=3,s=2,p=1
新的输入特征图 M ′ M^{\prime} M H i n ′ = 3 + ( 3 − 1 ) ∗ ( 2 − 1 ) = 3 + 2 = 5 H_{in}^{\prime}=3+(3−1)∗(2−1)=3+2=5 Hin=3+(31)(21)=3+2=5。注意加上padding之后才是7。
转置卷积核 K ′ K^{\prime} K k ′ = k , s ′ = 1 , p ′ = 3 − 1 − 1 = 1 k^{\prime}=k,s^{\prime}=1,p^{\prime}=3−1−1=1 k=k,s=1,p=311=1
转置卷积计算的最终结果: H o u t = ( 3 − 1 ) ∗ 2 − 2 ∗ 1 + 3 = 5 \mathrm{H_{out}}=(3-1)*2-2*1+3=5 Hout=(31)221+3=5

在这里插入图片描述

6. 证明 p ′ = k − p − 1 p^{\prime}=k-p-1 p=kp1

变换 公式 ( 5.1 ) 公式(5.1) 公式(5.1) 可得:
H i n = H o u t + 2 p − k s + 1 ( 5.2 ) H_{in}=\frac{H_{out}+2p-k}s+1\quad(5.2) Hin=sHout+2pk+1(5.2)

公式 ( 5.2 ) 公式(5.2) 公式(5.2) 公式 ( 1 ) 公式(1) 公式(1)可以看出, Conv2DConv2DTranspose 在输入和输出大小互为逆(inverses)

Note: torch.nn.ConvTranspose2d
The padding argument effectively adds dilation * (kernel_size - 1) - padding amount of zero padding to both sizes of the input. This is set so that when a Conv2d and a ConvTranspose2d are initialized with same parameters, they are inverses of each other in regard to the input and output shapes.

参数padding有效地将 d i l a t i o n ∗ ( k e r n e l _ s i z e − 1 ) − p a d d i n g dilation * (kernel\_size - 1) - padding dilation(kernel_size1)padding 零填充的填充量添加到两种大小的输入中。这样设置是为了当Conv2d和ConvTranspose2d用相同的参数初始化时,它们输入和输出的形状大小互为逆
简单理解,参数padding的作用是,使得 Conv2dConvTranspose2d 输入输出的形状大小互为逆

第二步中 p ′ = k − p − 1 p^{\prime} = k-p-1 p=kp1 计算公式是如何产生的呢?其实就是根据“ Conv2dConvTranspose2d 输入输出的形状大小互为逆” 的条件推导(反推)得来的。可以简单证明:

已知条件
H ′ = H i n + ( H i n − 1 ) ∗ ( s − 1 ) H^{\prime} = H_{in} + (H_{in}-1)*(s-1) H=Hin+(Hin1)(s1)
k ′ = k k^{\prime}=k k=k,
s ′ = 1 s^{\prime}=1 s=1,
p ′ p^{\prime} p未知待求。

将已知条件代入 公式 ( 2 ) 公式(2) 公式(2) 中,可得:
H o u t = ( H i n + H i n ∗ s − H − s + 1 ) + 2 ∗ p ′ − k s ′ + 1 \text{H}_{out}=\frac{(\text{H}_{in}+\text{H}_{in}*s-\text{H}-\text{s}+1)+2*p^{\prime}-\text{k}}{\text{s}'}+1 Hout=s(Hin+HinsHs+1)+2pk+1
化简,可得:
H o u t = ( H i n − 1 ) ∗ s + 2 ∗ p ′ − k + 2 ( 6 ) \mathrm{H}_{out}=(\mathrm{H}_{in}-1)*\text{s}+2*p^{\prime}-\mathrm{k}+2\quad(6) Hout=(Hin1)s+2pk+2(6)
根据“ Conv2dConvTranspose2d 输入输出的形状大小互为逆”,可得:
H i n = ( H o u t − 1 ) ∗ s + 2 ∗ p ′ − k + 2 ( 7 ) \mathrm{H}_{in}=(\mathrm{H}_{out}-1)*\text{s}+2*p^{\prime}-\mathrm{k}+2\quad(7) Hin=(Hout1)s+2pk+2(7)
变换公式可得:
H o u t = ( H i n − 2 ∗ p ′ + k − 2 ) s + 1 ( 8 ) \mathrm{H_{out}}=\frac{(\mathrm{H_{in}}-2*\mathrm{p^{\prime}}+\mathrm{k}-2)}{\mathrm{s}}+1\quad(8) Hout=s(Hin2p+k2)+1(8)
公式 ( 8 ) 公式(8) 公式(8) 公式 ( 1 ) 公式(1) 公式(1) 可得:
2 p − k = − 2 ∗ p ′ + k − 2 2p-k=-2*p^{\prime}+k-2 2pk=2p+k2
解得:
p ′ = k − p − 1 ( 9 ) p^{\prime}=k-p-1\quad(9) p=kp1(9)

证闭。

7. Conv2DTranspose中的步长stride

下图展示了转置卷积中不同s和p的情况:

在这里插入图片描述在这里插入图片描述在这里插入图片描述
s=1, p=0, k=3s=2, p=0, k=3s=2, p=1, k=3

7.1 当步长stride=1,p=0,k=3

在这里插入图片描述

输入特征图(蓝色): ( H i n , W i n ) = ( 2 , 2 ) (H_{in},W_{in})=(2,2) (Hin,Win)=(2,2)
标准卷积核: k e r n e l _ s i z e ( k ) = 3 , s t r i d e ( s ) = 1 , p a d d i n g ( p ) = 0 kernel\_size(k)=3,stride(s)=1, padding(p)=0 kernel_size(k)=3,stride(s)=1,padding(p)=0
新的输入特征图: H i n ′ = 2 + ( 2 − 1 ) ∗ ( 1 − 1 ) = 2 H_{in}^{\prime} =2+(2-1)*(1-1)=2 Hin=2+(21)(11)=2。如图上图所示,插值变换后得到的新的输入特征图为(2,2)。
转置卷积核: k e r n e l _ s i z e ( k ′ ) = 3 , s t r i d e ( s ′ ) = 1 , p a d d i n g ( p ′ ) = 3 − 0 − 1 = 2 kernel\_size(k^{\prime})=3,stride(s^{\prime})=1, padding(p^{\prime})=3-0-1=2 kernel_size(k)=3,stride(s)=1,padding(p)=301=2。如图上图所示,填充padding为2。
输出特征图(绿色): ( H o u t , W o u t ) = ( 4 , 4 ) (H_{out},W_{out})=(4,4) (Hout,Wout)=(4,4)

代入 公式 ( 5 ) 公式(5) 公式(5)中,可得:
H o u t = ( H i n − 1 ) ∗ s − 2 p + k H o u t = ( 2 − 1 ) ∗ 1 − 2 ∗ 0 + 3 = 4 \mathrm{H}_{out}=(\mathrm{H}_{in}-1)*\text{s}-2\text{p}+\mathrm{k}\\ \mathrm{H}_{out}=(2-1)*1-2*0+3=4 Hout=(Hin1)s2p+kHout=(21)120+3=4

7.2 当步长stride=2,p=0,k=3

在这里插入图片描述

输入特征图(蓝色): ( H i n , W i n ) = ( 2 , 2 ) (H_{in},W_{in})=(2,2) (Hin,Win)=(2,2)
卷积核: k = 3 , s t r i d e ( s ) = 2 , p a d d i n g = 0 k=3,stride(s)=2, padding=0 k=3,stride(s)=2,padding=0
新的输入特征图: H i n ′ = 2 + ( 2 − 1 ) ∗ ( 2 − 1 ) = 3 H_{in}^{\prime} =2+(2-1)*(2-1)=3 Hin=2+(21)(21)=3。如图上图所示,插值变换后得到的新的输入特征图为(3,3)。
转置卷积核: k e r n e l _ s i z e ( k ′ ) = 3 , s t r i d e ( s ′ ) = 1 , p a d d i n g ( p ′ ) = 3 − 0 − 1 = 2 kernel\_size(k^{\prime})=3,stride(s^{\prime})=1, padding(p^{\prime})=3-0-1=2 kernel_size(k)=3,stride(s)=1,padding(p)=301=2。如图上图所示,填充padding为2。
输出特征图(绿色): ( H o u t , W o u t ) = ( 5 , 5 ) (H_{out},W_{out})=(5,5) (Hout,Wout)=(5,5)

代入 公式 ( 5 ) 公式(5) 公式(5)中,可得:
H o u t = ( H i n − 1 ) ∗ s − 2 ∗ p + k H o u t = ( 2 − 1 ) ∗ 2 − 2 ∗ 0 + 3 = 5 \mathrm{H}_{out}=(\mathrm{H}_{in}-1)*\text{s}-2*\text{p}+\mathrm{k}\\ \mathrm{H}_{out}=(2-1)*2-2*0+3=5 Hout=(Hin1)s2p+kHout=(21)220+3=5

7.3 当步长stride=2,p=1,k=3

在这里插入图片描述

输入特征图(蓝色): ( H i n , W i n ) = ( 3 , 3 ) (H_{in},W_{in})=(3,3) (Hin,Win)=(3,3)
卷积核: k = 3 , s t r i d e ( s ) = 2 , p a d d i n g = 1 k=3,stride(s)=2, padding=1 k=3,stride(s)=2,padding=1
新的输入特征图: H i n ′ = 3 + ( 3 − 1 ) ∗ ( 2 − 1 ) = 5 H_{in}^{\prime} =3+(3-1)*(2-1)=5 Hin=3+(31)(21)=5。如图上图所示,插值变换后得到的新的输入特征图为(5,5)。
转置卷积核: k e r n e l _ s i z e ( k ′ ) = 3 , s t r i d e ( s ′ ) = 1 , p a d d i n g ( p ′ ) = 3 − 1 − 1 = 1 kernel\_size(k^{\prime})=3,stride(s^{\prime})=1, padding(p^{\prime})=3-1-1=1 kernel_size(k)=3,stride(s)=1,padding(p)=311=1。如图上图所示,填充padding为1。
输出特征图(绿色): ( H o u t , W o u t ) = ( 5 , 5 ) (H_{out},W_{out})=(5,5) (Hout,Wout)=(5,5)

代入 公式 ( 5 ) 公式(5) 公式(5)中,可得:
H o u t = ( H i n − 1 ) ∗ s − 2 ∗ p + k H o u t = ( 3 − 1 ) ∗ 2 − 2 ∗ 1 + 3 = 5 \mathrm{H}_{out}=(\mathrm{H}_{in}-1)*\text{s}-2*\text{p}+\mathrm{k}\\ \mathrm{H}_{out}=(3-1)*2-2*1+3=5 Hout=(Hin1)s2p+kHout=(31)221+3=5

8. 棋盘效应(Checkerboard Artifacts)

棋盘效应(Checkerboard Artifacts)
卷积操作总结(三)—— 转置卷积棋盘效应产生原因及解决
Deconvolution and Checkerboard Artifacts

棋盘效应是由于转置卷积的“不均匀重叠”(Uneven overlap)的结果,使图像中某个部位的颜色比其他部位更深。
在这里插入图片描述

9. 总结

  1. Conv2D,特征图变换:

H o u t = H i n + 2 p − k s + 1 H_{out}=\frac{H_{in}+2p-k}s+1 Hout=sHin+2pk+1

  1. Conv2DTranspose,特征图变换:

H o u t = ( H i n − 1 ) ∗ s − 2 p + k \mathrm{H}_{out}=(\mathrm{H}_{in}-1)*\text{s}-2\text{p}+\mathrm{k} Hout=(Hin1)s2p+k

  1. 标准卷积核: s , p , k e r n e l _ s i z e ( k ) s,p,kernel\_size(k) s,p,kernel_size(k),转置卷积核: s = 1 , p ′ = k − p − 1 , k e r n e l _ s i z e ( k ′ ) = k e r n e l _ s i z e ( k ) s=1,p^{\prime}=k-p-1,kernel\_size(k^{\prime})=kernel\_size(k) s=1,p=kp1,kernel_size(k)=kernel_size(k)
  2. Conv2DConv2DTranspose 输入输出的形状大小互为逆
  3. 标准卷积(大图变小图,(5,5)到(3,3)),转置卷积(小图变大图,(3,3)到(5,5))。

四、相关经验

tf.layers.Conv2DTranspose

TensorFlow函数:tf.layers.Conv2DTranspose

以 tensorflow2 框架的Conv2DTranspose为例,介绍转置卷积函数。

layers.Conv2DTranspose(
    filters,
    kernel_size,
    strides=(1, 1),
    padding='valid',
    output_padding=None,
    data_format=None,
    dilation_rate=(1, 1),
    activation=None,
    use_bias=True,
    kernel_initializer='glorot_uniform',
    bias_initializer='zeros',
    kernel_regularizer=None,
    bias_regularizer=None,
    activity_regularizer=None,
    kernel_constraint=None,
    bias_constraint=None,
    **kwargs,
)
Docstring:     
Transposed convolution layer (sometimes called Deconvolution).

参数解释

  • filters:整数,输出空间的维数(即卷积中的滤波器数)。
  • kernel_size:一个元组或2个正整数的列表,指定过滤器的空间维度;可以是单个整数,以指定所有空间维度的相同值。
  • strides:一个元组或2个正整数的列表,指定卷积的步长;可以是单个整数,以指定所有空间维度的相同值。
  • padding:可以是一个"valid"或"same"(不区分大小写)。
  • data_format:一个字符串,可以是一个 channels_last(默认)、channels_first,表示输入中维度的顺序。channels_last 对应于具有形状(batch, height, width, channels)的输入,而 channels_first 对应于具有形状(batch, channels, height, width)的输入。
  • dilation_rate:。
  • activation:激活功能,将其设置为“None”以保持线性激活。
  • use_bias:Boolean,表示该层是否使用偏置。
  • kernel_initializer:卷积内核的初始化程序。
  • bias_initializer:偏置向量的初始化器,如果为None,将使用默认初始值设定项。
  • kernel_regularizer:卷积内核的可选正则化器。
  • bias_regularizer:偏置矢量的可选正则化器。
  • activity_regularizer:输出的可选正则化函数。
  • kernel_constraint:由Optimizer更新后应用于内核的可选投影函数(例如,用于实现层权重的范数约束或值约束);该函数必须将未投影的变量作为输入,并且必须返回投影变量(必须具有相同的形状);在进行异步分布式培训时,使用约束是不安全的。
  • bias_constraint:由Optimizer更新后应用于偏置的可选投影函数。
  • trainable:Boolean,如果为True,还将变量添加到图集合GraphKeys。TRAINABLE_VARIABLES中(请参阅参考资料 tf.Variable)。
  • name:字符串,图层的名称。

torch.nn.ConvTranspose2d

torch.nn.ConvTranspose2d

# 函数原型
CLASS torch.nn.ConvTranspose2d(in_channels, 
                               out_channels, 
                               kernel_size, 
                               stride=1, 
                               padding=0, 
                               output_padding=0, 
                               groups=1, 
                               bias=True, 
                               dilation=1, 
                               padding_mode='zeros', 
                               device=None, 
                               dtype=None)

参数解释

  • in_channels (int) – Number of channels in the input image
  • out_channels (int) – Number of channels produced by the convolution
  • kernel_size (int or tuple) – Size of the convolving kernel
  • stride (int or tuple, optional) – Stride of the convolution. Default: 1
  • padding (int or tuple, optional) – dilation * (kernel_size - 1) - padding zero-padding will be added to both sides of each dimension in the input. Default: 0
  • output_padding (int or tuple, optional) – Additional size added to one side of each dimension in the output shape. Default: 0. Note that output_padding is only used to find output shape, but does not actually add zero-padding to output. 在计算得到的输出特征图的高、宽方向各填充几行或列0(注意,这里只是在上下以及左右的一侧one side填充,并不是两侧都填充)
  • groups (int, optional) – Number of blocked connections from input channels to output channels. Default: 1. 当使用到组卷积时才会用到的参数,默认为1即普通卷积。
  • bias (bool, optional) – If True, adds a learnable bias to the output. Default: True
  • dilation (int or tuple, optional) – Spacing between kernel elements. Default: 1. 当使用到空洞卷积(膨胀卷积)时才会使用该参数,默认为1即普通卷积。

代码示例(TensorFlow)

#创建生成器
def make_generator_model():
    model = tf.keras.Sequential()#创建模型实例
    #第一层须指定维度 #batch无限制
    model.add(layers.Dense(7*7*BATCH_SIZE, use_bias=False, input_shape=(100,)))#Desne第一层可以理解为全连接层输入,它的秩必须小于2
    model.add(layers.BatchNormalization())
    model.add(layers.LeakyReLU())
    
    model.add(layers.Reshape((7,7,256)))
    assert model.output_shape == (None,7,7,256)
    
    #转化为7*7*128
    model.add(layers.Conv2DTranspose(128,(5,5),strides=(1,1),padding='same',use_bias=False))
    assert model.output_shape == (None,7,7,128)
    model.add(layers.BatchNormalization())
    model.add(layers.LeakyReLU())
    
    #转化为14*14*64
    model.add(layers.Conv2DTranspose(64,(5,5),strides=(2,2),padding='same',use_bias=False))
    assert model.output_shape == (None,14,14,64)
    model.add(layers.BatchNormalization())
    model.add(layers.LeakyReLU())
 
    #转化为28*28*1
    model.add(layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', use_bias=False,activation='tanh'))
    assert model.output_shape == (None, 28, 28, 1)          
 
    return model

代码示例(PyTorch)

下面使用Pytorch框架来模拟s=1, p=0, k=3的转置卷积操作:

在这里插入图片描述
在代码中transposed_conv_official函数是使用官方的转置卷积进行计算,transposed_conv_self函数是按照上面讲的步骤自己对输入特征图进行填充并通过卷积得到的结果。

import torch
import torch.nn as nn


def transposed_conv_official():
    feature_map = torch.as_tensor([[1, 0],
                                   [2, 1]], dtype=torch.float32).reshape([1, 1, 2, 2])
    print(feature_map)
    trans_conv = nn.ConvTranspose2d(in_channels=1, out_channels=1,
                                    kernel_size=3, stride=1, bias=False)
    trans_conv.load_state_dict({"weight": torch.as_tensor([[1, 0, 1],
                                                           [0, 1, 1],
                                                           [1, 0, 0]], dtype=torch.float32).reshape([1, 1, 3, 3])})
    print(trans_conv.weight)
    output = trans_conv(feature_map)
    print(output)


def transposed_conv_self():
    feature_map = torch.as_tensor([[0, 0, 0, 0, 0, 0],
                                   [0, 0, 0, 0, 0, 0],
                                   [0, 0, 1, 0, 0, 0],
                                   [0, 0, 2, 1, 0, 0],
                                   [0, 0, 0, 0, 0, 0],
                                   [0, 0, 0, 0, 0, 0]], dtype=torch.float32).reshape([1, 1, 6, 6])
    print(feature_map)
    conv = nn.Conv2d(in_channels=1, out_channels=1,
                     kernel_size=3, stride=1, bias=False)
    conv.load_state_dict({"weight": torch.as_tensor([[0, 0, 1],
                                                     [1, 1, 0],
                                                     [1, 0, 1]], dtype=torch.float32).reshape([1, 1, 3, 3])})
    print(conv.weight)
    output = conv(feature_map)
    print(output)


def main():
    transposed_conv_official()
    print("---------------")
    transposed_conv_self()


if __name__ == '__main__':
    main()

输出结果

tensor([[[[1., 0.],
          [2., 1.]]]])
Parameter containing:
tensor([[[[1., 0., 1.],
          [0., 1., 1.],
          [1., 0., 0.]]]], requires_grad=True)
tensor([[[[1., 0., 1., 0.],
          [2., 2., 3., 1.],
          [1., 2., 3., 1.],
          [2., 1., 0., 0.]]]], grad_fn=<SlowConvTranspose2DBackward>)
---------------
tensor([[[[0., 0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0., 0.],
          [0., 0., 1., 0., 0., 0.],
          [0., 0., 2., 1., 0., 0.],
          [0., 0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0., 0.]]]])
Parameter containing:
tensor([[[[0., 0., 1.],
          [1., 1., 0.],
          [1., 0., 1.]]]], requires_grad=True)
tensor([[[[1., 0., 1., 0.],
          [2., 2., 3., 1.],
          [1., 2., 3., 1.],
          [2., 1., 0., 0.]]]], grad_fn=<ThnnConv2DBackward>)

Process finished with exit code 0

DCGAN

论文:Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1343080.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】深度解剖环境变量

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟悉并掌握Linux的环境变量。 > 毒鸡汤&#x…

【2023 CCF 大数据与计算智能大赛】基于TPU平台实现超分辨率重建模型部署 基于FSRCNN的TPU平台超分辨率模型部署方案

2023 CCF 大数据与计算智能大赛 基于TPU平台实现超分辨率重建模型部署 基于FSRCNN的TPU平台超分辨率模型部署方案 WELL 刘渝 人工智能 研一 西安交通大学 中国-西安 1461003622qq.com 史政立 网络空间安全 研一 西安交通大学 中国-西安 1170774291qq.com 崔琳、张…

vue项目hdr格式文件放在assets下rgbeloader.load获取不到问题解决

如下图 我再App.vue组件中这样写 艾特符号定位 告诉系统 要src下的assets下的xhdr下的xidis.hdr 但是运行项目 他会告诉你找不到这个资源 我们改一下 我们组件时 App.vue 与assets同在 src目录下 用 ./去找 这样也是找不到的 我们需要将它放在静态资源包public下 public路…

Vite+Vue3学习笔记(2)——语法、渲染、事件、数据传递、生命周期、第三方库、前端部署

官网链接&#xff1a;https://cn.vuejs.org/ 如果出现普通用户无法新建项目&#xff0c;必须要管理员身份新建&#xff0c;那么可以在nodejs的安装路径设置安全选项&#xff0c;提高普通用户的权限。 具体方法参考&#xff1a; https://blog.csdn.net/weixin_43174650/article/…

毫米波雷达:从 3D 走向 4D

1 毫米波雷达已广泛应用于汽车 ADAS 系统 汽车智能驾驶需要感知层、决策层、执行层三大核心系统的高效配合&#xff0c;其中感知层通过传感器探知周围的环境。汽车智能驾驶感知层将真实世界的视觉、物理、事件等信息转变成数字信号&#xff0c;为车辆了解周边环境、制定驾驶操…

2023 年有什么流行的开源项目?

背景介绍 作为一个资深开源参与者&#xff0c;我盘点下2023年有意思的开源项目&#xff0c;从GitHub热榜角度盘点下。 作为工程师我对技术理解顺势而为&#xff0c;当风口袭来拥抱研究使用&#xff0c;理解其中精髓为风口添砖加瓦。 2023年很特殊&#xff0c;AI生成开始火热…

挑战Python100题(7)

100+ Python challenging programming exercises 7 Question 61 Print a unicode string "hello world". Hints: Use ustrings format to define unicode string. 打印一个unicode字符串“helloworld”。 提示:使用u“字符串”格式定义unicode字符串。 Solution…

【全网最细】爆肝3天,2023年年度音乐+图片+热词终于出来了,来看看你知道几个?

目录 前言 2023年度音乐 1.《阳光开朗大男孩》 2.《早安隆回》 3.《一路生花》 4.《爱如火》 5.《向云端》 6.《孤勇者》 7.《起风了》 8.《只因你太美》 2023年度图片 1.R星 2.小飞棍来喽 3.一键三连 4.只因你太美 5.原神&#xff0c;启动&#xff01; 2023年…

毅速:3D打印技术传统模具行业影响深远

随着3D打印技术的不断发展和完善&#xff0c;一系列的优势使其在模具制造领域的应用越来越广泛&#xff0c;这一技术在模具行业的应用将为整个行业带来变革。 首先&#xff0c;3D打印技术将大幅提高模具制造的精度和效率。传统的模具制造过程中&#xff0c;由于加工设备的限制和…

SOAP请求发送(基于Hutool)

拿到SOAP请求的时候&#xff0c;先使用SOAPUI工具解析WSDL文件&#xff0c;得到请求方法列表&#xff0c;新建一个请求&#xff0c;SOAPUI查看协议版本和Action如下&#xff1a; 如下为解析出的XML入参示例。 <soapenv:Envelope xmlns:soapenv"http://schemas.xmlsoap…

ffmpeg 解码文件时的时间戳问题

实时流和普通文件 1 实时流 实时流编码时&#xff0c;我们一般不进行b帧编码&#xff0c;但是文件存储时为了减小大小&#xff0c;会增加b帧&#xff0c;实时流只带了I&#xff0c;P帧&#xff0c;那就会好很多 2 普通文件 很多文件带了b帧&#xff0c;所以要使用解码时间去同…

软件测试/测试开发丨Selenium环境安装配置

一、selenium 环境配置 1、下载浏览器 目前比较常用的浏览器是 Google Chrome 浏览器&#xff0c;所以本教程以 chrome 为主&#xff0c;后面简介一下其他浏览器的环境配置。 chrome 下载: www.google.cn/chrome/ 2、chromedriver 环境配置 chromedriver 是chromedriver提…

搜索算法和推荐算法、广告算法的区别

广告和推荐算法的技术框架比较相似&#xff0c;在线计算时都分为召回&#xff08;candidates generating&#xff09;和排序&#xff08;candidates ranking&#xff09;两个阶段&#xff08;这似乎是计算资源有限条件下&#xff0c;所有检索问题的通用架构&#xff09;。 在某…

从a类到b类理解原型链

一.一个Student类 class Student {constructor(name, age) {this.name name;this.age age;}learn() {console.log("学习");}}let a1new Student(王德发,20)console.log(a1); 打印出来的结果: 二.extends继承 // 老师类class Teacher {constructor(name, age) {thi…

什么是uniapp?用uniapp开发好不好用?

随着移动应用市场的持续发展&#xff0c;开发者们面临着不断增长的需求和多样化的平台选择。在这个背景下&#xff0c;UniApp 应运而生&#xff0c;成为一种跨平台开发框架&#xff0c;为开发者提供了一种高效、简便的方式来开发移动应用程序。利用 UniApp 开发应用程序可以节省…

飞企互联-FE企业运营管理平台 登录绕过漏洞复现

0x01 产品简介 飞企互联-FE企业运营管理平台是一个基于云计算、智能化、大数据、物联网、移动互联网等技术支撑的云工作台。这个平台可以连接人、链接端、联通内外&#xff0c;支持企业B2B、C2B与O2O等核心需求&#xff0c;为不同行业客户的互联网转型提供支持。 0x02 漏洞概…

Android画布Canvas drawPath绘制跟随手指移动的圆,Kotlin

Android画布Canvas drawPath绘制跟随手指移动的圆&#xff0c;Kotlin import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.Path import android.os.Bundle import android.…

快速实现图片重命名(统一命名或按数字顺序命名)

快速实现图片重命名&#xff08;统一命名或按数字顺序命名&#xff09; 有时候跑数据集需要图像的命名有规律&#xff0c;但储存时的命名可能是没有规律的。这时候手动一个个右键重命名&#xff0c;再进行修改过于耗时&#xff0c;这里给出简便的统一重命名方法。 按数字排序…

Linux驱动开发学习笔记6《蜂鸣器实验》

目录 一、蜂鸣器驱动原理 二、硬件原理分析 三、实验程序编写 1、 修改设备树文件 &#xff08;1&#xff09;添加pinctrl节点 &#xff08;2&#xff09;添加BEEP设备节点 &#xff08;3&#xff09;检查PIN 是否被其他外设使用 2、蜂鸣器驱动程序编写 3、编写测试AP…

LVM与磁盘配额

文章目录 LVM与磁盘配额一、LVM概述1、LVM概述2、LVM机制的基本概念2.1 PV&#xff08;Physical Volume&#xff0c;物理卷&#xff09;2.2 VG&#xff08;Logical Volume&#xff0c;逻辑卷&#xff09;2.3 LV&#xff08;Logical Volume&#xff0c;逻辑卷&#xff09; 二、L…