上一篇文章记录了 Pytorch 用于构建神经网络的容器,并且提到 一个神经网络模块是由其他子模块嵌套而成的结构,常用的就是卷积、池化等等,所以这篇简单介绍下 torch.nn
中的卷积类。
torch.nn.Conv1d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')
Conv1d
的作用就是对输入数据执行 一维卷积,所谓的一维卷积以数学形式可以这么表达:设输入为 ( N , C i n , L i n ) (N, C_{in}, L_{in}) (N,Cin,Lin),输出为 ( N , C o u t , L o u t ) (N, C_{out}, L_{out}) (N,Cout,Lout)。
那么 第 i i i 批第 j j j 个通道的输出 可以精确描述为:
o u t ( N i , C o u t j ) = b i a s ( C o u t j ) + ∑ k = 0 C i n − 1 w e i g h t ( C o u t j , k ) ⋆ i n p u t ( N i , k ) out(N_i, C_{out_{j}})=bias(C_{out_{j}})+\sum_{k=0}^{C_{in}-1}{weight(C_{out_{j}},k){\star}\ input(N_i,k)} out(Ni,Coutj)=bias(Coutj)+k=0∑Cin−1weight(Coutj,k)⋆ input(Ni,k)
注:前两天在朋友圈看到一个对卷积超好玩的理解:什么是卷积?你在过去不同时刻惹女朋友生气的叠加,对女朋友现在坏心情的贡献就是卷积。
参数:
in_channels
:类型为 int
,表示输入数据的通道数;out_channels
:类型为 int
,表示经过一维卷积操作后输出数据的通道数;kernel_size
:类型为 int、tuple
,表示卷积核的大小;stride
:可选参数,类型为 int、tuple
,控制进行卷积的步长,默认 stride=1
;padding
:可选参数,类型为 int、tuple
,可对输入的两侧进行零填充,即控制输入两侧的隐式填充量,默认 padding=0
;padding_mode
:可选参数,类型为 string
,控制填充模式 zeros-零填充, reflect-镜像填充, replicate-复制填充, circular
,默认为 padding_mode=zeros
;dilation
:可选参数,类型为 int、tuple
,控制卷积核元素的间距,默认 dilation=1
就是标准卷积,更改该参数的话标准卷积就变成了 膨胀卷积(空洞卷积),也被称为 à trous
算法,文字描述很困难,但是用图就很容易理解,参考 [1];groups
:可选参数,类型为 int
,控制从输入到输出之间的连接数,该参数必须满足能够整除input_channels & output_channels
,默认为 groups=1
,例如:
groups=1
时,所有的输入都会被卷积到输出;groups=2
时,相当于并排放置两个 conv1d
层,每个层会传入一半的 input_channels
并产生一半的 output_channels
,然后将两者连接起来;groups=input_channels
时,每个 input_channels
只会与该通道的大小为 o u t p u t _ c h a n n e l s i n p u t _ c h a n n e l s \frac{output{\_}channels}{input{\_}channels} input_channelsoutput_channels 的滤波器进行卷积;groups == in_channels
和 out_channels == K * in_channels
时(其中 K 是正整数),此操作也称为 深度卷积,换句话说,对于输入 ( N , C i n , L i n ) (N, C_{in}, L_{in}) (N,Cin,Lin),可以使用参数 ( C i n = C i n , C o u t = C i n ∗ K , ⋯ , g r o u p s = C i n ) (C_{in}=C_{in}, C_{out}=C_{in}*K, \cdots, groups=C_{in}) (Cin=Cin,Cout=Cin∗K,⋯,groups=Cin) 实现 depth=K
的深度卷积。下同。bias
:可选参数,类型为 bool
,若 bias=True
,则会添加可学习的偏差参数,默认值为 bias=True
。假设:
在卷积的过程中,可以学习的
Conv1d.weight
:类型为 Tensor
,代表模型中可学习的权重,shape 为 ( o u t _ c h a n n e l s , i n _ c h a n n e l s g r o u p s , k e r n e l _ s i z e ) (out{\_}channels, \frac{in{\_}channels}{groups}, kernel{\_}size) (out_channels,groupsin_channels,kernel_size),这些值是从 μ ( − k , k ) , k = g r o u p s C _ i n ∗ k e r n e l _ s i z e \mu(-\sqrt{k}, \sqrt{k}),{\ }k=\frac{groups}{C{\_}{in}*kernel{\_}size} μ(−k,k), k=C_in∗kernel_sizegroups 取样得到;Conv1d.bias
:类型为 Tensor
,代表模型中可学习的偏差,shape 为 ( o u t _ c h a n n e l s ) (out{\_}channels) (out_channels)。如果参数 bias=True
,那么这些值是从 μ ( − k , k ) , k = g r o u p s C _ i n ∗ k e r n e l _ s i z e \mu(-\sqrt{k}, \sqrt{k}),{\ }k=\frac{groups}{C{\_}{in}*kernel{\_}size} μ(−k,k), k=C_in∗kernel_sizegroups 取样得到。import torch
import torch.nn as nn
conv_layers = [nn.Conv1d(16, 33, 3, stride=2),
nn.Conv1d(16, 33, 5, stride=2),
nn.Conv1d(16, 33, 3, stride=3),
nn.Conv1d(16, 33, 3, stride=2, padding=2),
nn.Conv1d(16, 33, 3, stride=2, dilation=3),
nn.Conv1d(16, 33, 3, stride=2, bias=True),
nn.Conv1d(16, 24, 3, stride=2),
nn.Conv1d(16, 24, 3, stride=2, groups=2)]
input_data = torch.randn(20, 16, 50)
for i in range(len(conv_layers)):
output_data = conv_layers[i](input_data)
print(output_data.shape)
可以按照 1.3 中的公式验证下结果:
最后两个测试改变了输入通道数和分组,可以发现采用参数 groups
并不会改变结果:
torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')
Conv2d
的作用就是对输入数据执行 二维卷积,二维卷积以数学形式可以这么表达:设输入为 ( N , C i n , H i n , W i n ) (N, C_{in}, H_{in}, W_{in}) (N,Cin,Hin,Win),输出为 ( N , C o u t , H o u t , W o u t ) (N, C_{out}, H_{out}, W_{out}) (N,Cout,Hout,Wout)。
那么 第 i i i 批第 j j j 个通道的输出 可以精确描述为:
o u t ( N i , C o u t j ) = b i a s ( C o u t j ) + ∑ k = 0 C i n − 1 w e i g h t ( C o u t j , k ) ⋆ i n p u t ( N i , k ) out(N_i, C_{out_{j}})=bias(C_{out_{j}})+\sum_{k=0}^{C_{in}-1}{weight(C_{out_{j}},k){\star}\ input(N_i,k)} out(Ni,Coutj)=bias(Coutj)+k=0∑Cin−1weight(Coutj,k)⋆ input(Ni,k)
参数:
in_channels
:类型为 int
,表示输入数据的通道数;out_channels
:类型为 int
,表示经过二维卷积操作后输出数据的通道数;kernel_size
:类型为 int、tuple of two ints
,表示卷积核的大小:
int
时,宽高将使用同样的尺寸值;tuple of two ints
时,第一个 int
用于高度尺寸,第二个 int
用于宽度尺寸。下同。stride
:可选参数,类型为 int、tuple of two ints
,控制进行卷积的步长,默认 stride=1
;padding
:可选参数,类型为 int、tuple of two ints
,可对输入的两侧进行零填充,即控制输入两侧的隐式填充量,默认 padding=0
;padding_mode
:可选参数,类型为 string
,控制填充模式 zeros-零填充, reflect-镜像填充, replicate-复制填充, circular
,默认为 padding_mode=zeros
;dilation
:可选参数,类型为 int、tuple of two ints
,控制卷积核元素的间距,默认 dilation=1
是标准卷积,膨胀卷积(空洞卷积) 参考 [1];groups
:可选参数,类型为 int
,控制从输入到输出之间的连接数,该参数必须满足能够整除input_channels & output_channels
,默认为 groups=1
,例如:
groups=1
时,所有的输入都会被卷积到输出;groups=2
时,相当于并排放置两个 conv1d
层,每个层会传入一半的 input_channels
并产生一半的 output_channels
,然后将两者连接起来;groups=input_channels
时,每个 input_channels
只会与该通道的大小为 o u t p u t _ c h a n n e l s i n p u t _ c h a n n e l s \frac{output{\_}channels}{input{\_}channels} input_channelsoutput_channels 的滤波器进行卷积;bias
:可选参数,类型为 bool
,若 bias=True
,则会添加可学习的偏差参数,默认值为 bias=True
。假设:
在卷积的过程中,可以学习权重和偏差:
Conv2d.weight
:类型为 Tensor
,代表模型中可学习的权重,shape 为 ( o u t _ c h a n n e l s , i n _ c h a n n e l s g r o u p s , k e r n e l _ s i z e [ 0 ] , k e r n e l _ s i z e [ 1 ] ) (out{\_}channels, \frac{in{\_}channels}{groups}, kernel{\_}size[0], kernel{\_}size[1]) (out_channels,groupsin_channels,kernel_size[0],kernel_size[1]),这些值是从 μ ( − k , k ) , k = g r o u p s C _ i n ∗ k e r n e l _ s i z e [ 0 ] ∗ k e r n e l _ s i z e [ 1 ] \mu(-\sqrt{k}, \sqrt{k}),{\ }k=\frac{groups}{C{\_}{in}*kernel{\_}size[0]*kernel{\_}size[1]} μ(−k,k), k=C_in∗kernel_size[0]∗kernel_size[1]groups 取样得到;Conv2d.bias
:类型为 Tensor
,代表模型中可学习的偏差,shape 为 ( o u t _ c h a n n e l s ) (out{\_}channels) (out_channels)。如果参数 bias=True
,那么这些值是从 μ ( − k , k ) , k = g r o u p s C _ i n ∗ k e r n e l _ s i z e [ 0 ] ∗ k e r n e l _ s i z e [ 1 ] \mu(-\sqrt{k}, \sqrt{k}),{\ }k=\frac{groups}{C{\_}{in}*kernel{\_}size[0]*kernel{\_}size[1]} μ(−k,k), k=C_in∗kernel_size[0]∗kernel_size[1]groups 取样得到。import torch
import torch.nn as nn
conv_layers = [nn.Conv2d(16, 33, 3, stride=2), # square kernels and equal stride
# non-square kernels and unequal stride and padding
nn.Conv2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2)),
# non-square kernels and unequal stride and padding
nn.Conv2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2), dilation=(3, 1))
]
input_data = torch.randn(20, 16, 50, 100)
for i in range(len(conv_layers)):
output_data = conv_layers[i](input_data)
print(output_data.shape)
H o u t 1 = [ 50 + 2 × 0 − 1 × ( 3 − 1 ) − 1 2 + 1 ] = 24 H_{out1}=[\frac{50 + 2{\times}0-1{\times}(3-1)-1}{2}+1]=24 Hout1=[250+2×0−1×(3−1)−1+1]=24
W o u t 1 = [ 100 + 2 × 0 − 1 × ( 3 − 1 ) − 1 2 + 1 ] = 49 W_{out1}=[\frac{100 + 2{\times}0-1{\times}(3-1)-1}{2}+1]=49 Wout1=[2100+2×0−1×(3−1)−1+1]=49
H o u t 2 = [ 50 + 2 × 4 − 1 × ( 3 − 1 ) − 1 2 + 1 ] = 28 H_{out2}=[\frac{50 + 2{\times}4-1{\times}(3-1)-1}{2}+1]=28 Hout2=[250+2×4−1×(3−1)−1+1]=28
W o u t 2 = [ 100 + 2 × 2 − 1 × ( 5 − 1 ) − 1 1 + 1 ] = 100 W_{out2}=[\frac{100 + 2{\times}2-1{\times}(5-1)-1}{1}+1]=100 Wout2=[1100+2×2−1×(5−1)−1+1]=100
H o u t 3 = [ 50 + 2 × 4 − 3 × ( 3 − 1 ) − 1 2 + 1 ] = 26 H_{out3}=[\frac{50 + 2{\times}4-3{\times}(3-1)-1}{2}+1]=26 Hout3=[250+2×4−3×(3−1)−1+1]=26
W o u t 3 = [ 100 + 2 × 2 − 1 × ( 5 − 1 ) − 1 1 + 1 ] = 100 W_{out3}=[\frac{100 + 2{\times}2-1{\times}(5-1)-1}{1}+1]=100 Wout3=[1100+2×2−1×(5−1)−1+1]=100
torch.nn.Conv3d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')
Conv3d
的作用就是对输入数据执行 三维卷积,三维卷积以数学形式可以表达为:设输入为 ( N , C i n , D i n , H i n , W i n ) (N, C_{in}, D_{in}, H_{in}, W_{in}) (N,Cin,Din,Hin,Win),输出为 ( N , C o u t , D o u t , H o u t , W o u t ) (N, C_{out}, D_{out}, H_{out}, W_{out}) (N,Cout,Dout,Hout,Wout)。
那么 第 i i i 批第 j j j 个通道的输出 可以精确描述为:
o u t ( N i , C o u t j ) = b i a s ( C o u t j ) + ∑ k = 0 C i n − 1 w e i g h t ( C o u t j , k ) ⋆ i n p u t ( N i , k ) out(N_i, C_{out_{j}})=bias(C_{out_{j}})+\sum_{k=0}^{C_{in}-1}{weight(C_{out_{j}},k){\star}\ input(N_i,k)} out(Ni,Coutj)=bias(Coutj)+k=0∑Cin−1weight(Coutj,k)⋆ input(Ni,k)
参数:
in_channels
:类型为 int
,表示输入数据的通道数;out_channels
:类型为 int
,表示经过三维卷积操作后输出数据的通道数;kernel_size
:类型为 int、tuple of three ints
,表示卷积核的大小:
int
时,宽高将使用同样的尺寸值;tuple of three ints
时,第一个 int
用于深度尺寸,第二个 int
用于高度,第三个 int
用于宽度。下同。stride
:可选参数,类型为 int、tuple of three ints
,控制进行卷积的步长,默认 stride=1
;padding
:可选参数,类型为 int、tuple of three ints
,可对输入的三边均进行零填充,即控制输入两侧的隐式填充量,默认 padding=0
;padding_mode
:可选参数,类型为 string
,控制填充模式 zeros-零填充, reflect-镜像填充, replicate-复制填充, circular
,默认为 padding_mode=zeros
;dilation
:可选参数,类型为 int、tuple of three ints
,控制卷积核元素的间距,默认 dilation=1
是标准卷积,膨胀卷积(空洞卷积) 参考 [1];groups
:可选参数,类型为 int
,控制从输入到输出之间的连接数,该参数必须满足能够整除input_channels & output_channels
,默认为 groups=1
,例如:
groups=1
时,所有的输入都会被卷积到输出;groups=2
时,相当于并排放置两个 conv1d
层,每个层会传入一半的 input_channels
并产生一半的 output_channels
,然后将两者连接起来;groups=input_channels
时,每个 input_channels
只会与该通道的大小为 o u t p u t _ c h a n n e l s i n p u t _ c h a n n e l s \frac{output{\_}channels}{input{\_}channels} input_channelsoutput_channels 的滤波器进行卷积;bias
:可选参数,类型为 bool
,若 bias=True
,则会添加可学习的偏差参数,默认值为 bias=True
。假设:
在卷积的过程中,可以学习权重和偏差:
Conv3d.weight
:类型为 Tensor
,代表模型中可学习的权重,shape 为 ( o u t _ c h a n n e l s , i n _ c h a n n e l s g r o u p s , k e r n e l _ s i z e [ 0 ] , k e r n e l _ s i z e [ 1 ] , k e r n e l _ s i z e [ ] ) (out{\_}channels, \frac{in{\_}channels}{groups}, kernel{\_}size[0], kernel{\_}size[1], kernel{\_}size[]) (out_channels,groupsin_channels,kernel_size[0],kernel_size[1],kernel_size[]),这些值是从 μ ( − k , k ) , k = g r o u p s C _ i n ∗ k e r n e l _ s i z e [ 0 ] ∗ k e r n e l _ s i z e [ 1 ] ∗ k e r n e l _ s i z e [ 2 ] \mu(-\sqrt{k}, \sqrt{k}),{\ }k=\frac{groups}{C{\_}{in}*kernel{\_}size[0]*kernel{\_}size[1]*kernel{\_}size[2]} μ(−k,k), k=C_in∗kernel_size[0]∗kernel_size[1]∗kernel_size[2]groups 取样得到;Conv3d.bias
:类型为 Tensor
,代表模型中可学习的偏差,shape 为 ( o u t _ c h a n n e l s ) (out{\_}channels) (out_channels)。如果参数 bias=True
,那么这些值是从 μ ( − k , k ) , k = g r o u p s C _ i n ∗ k e r n e l _ s i z e [ 0 ] ∗ k e r n e l _ s i z e [ 1 ] ∗ k e r n e l _ s i z e [ 2 ] \mu(-\sqrt{k}, \sqrt{k}),{\ }k=\frac{groups}{C{\_}{in}*kernel{\_}size[0]*kernel{\_}size[1]*kernel{\_}size[2]} μ(−k,k), k=C_in∗kernel_size[0]∗kernel_size[1]∗kernel_size[2]groups 取样得到。import torch
import torch.nn as nn
conv_layers = [nn.Conv3d(16, 33, 3, stride=2), # square kernels and equal stride
# non-square kernels and unequal stride with padding
nn.Conv3d(16, 33, (3, 5, 2), stride=(2, 1, 1), padding=(4, 2, 0)),
]
input_data = torch.randn(20, 16, 10, 50, 100)
for i in range(len(conv_layers)):
output_data = conv_layers[i](input_data)
print(output_data.shape)
D o u t 1 = [ 10 + 2 × 0 − 1 × ( 3 − 1 ) − 1 2 + 1 ] = 4 D_{out1}=[\frac{10 + 2{\times}0-1{\times}(3-1)-1}{2}+1]=4 Dout1=[210+2×0−1×(3−1)−1+1]=4
H o u t 1 = [ 50 + 2 × 0 − 1 × ( 3 − 1 ) − 1 2 + 1 ] = 24 H_{out1}=[\frac{50 + 2{\times}0-1{\times}(3-1)-1}{2}+1]=24 Hout1=[250+2×0−1×(3−1)−1+1]=24
W o u t 1 = [ 100 + 2 × 0 − 1 × ( 3 − 1 ) − 1 2 + 1 ] = 49 W_{out1}=[\frac{100 + 2{\times}0-1{\times}(3-1)-1}{2}+1]=49 Wout1=[2100+2×0−1×(3−1)−1+1]=49
D o u t 2 = [ 10 + 2 × 4 − 1 × ( 3 − 1 ) − 1 2 + 1 ] = 8 D_{out2}=[\frac{10 + 2{\times}4-1{\times}(3-1)-1}{2}+1]=8 Dout2=[210+2×4−1×(3−1)−1+1]=8
H o u t 2 = [ 50 + 2 × 2 − 1 × ( 5 − 1 ) − 1 1 + 1 ] = 50 H_{out2}=[\frac{50 + 2{\times}2-1{\times}(5-1)-1}{1}+1]=50 Hout2=[150+2×2−1×(5−1)−1+1]=50
W o u t 2 = [ 100 + 2 × 0 − 1 × ( 2 − 1 ) − 1 1 + 1 ] = 99 W_{out2}=[\frac{100 + 2{\times}0-1{\times}(2-1)-1}{1}+1]=99 Wout2=[1100+2×0−1×(2−1)−1+1]=99
转置卷积(Transposed Convolution) 是卷积的逆过程,也被称为反卷积。在卷积神经网络中,属于 上采样(up-sampling) 的一种方式,常用于提升图像的分辨率,恢复图像的尺寸而不是像素值喔!图解分析可以参考 [1]。
和标准卷积类似,转置卷积也分为三种维度。
torch.nn.ConvTranspose1d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True, dilation=1, padding_mode='zeros')
ConvTranspose1d
的作用就是对输入数据执行 一维转置卷积,可以看作是 Conv1d
相对于其输入的梯度,它也称为 fractionally-strided convolution 或 deconvolution (尽管它不是实际的反卷积操作)。
参数:
in_channels
:类型为 int
,表示输入数据的通道数;out_channels
:类型为 int
,表示经过一维转置卷积操作后输出数据的通道数;kernel_size
:类型为 int、tuple of one int
,表示卷积核的大小;stride
:可选参数,类型为 int、tuple of one int
,控制进行卷积的步长,默认 stride=1
;padding
:可选参数,类型为 int、tuple of one int
,可对输入的两侧进行 dilation * (kernel_size-1) - padding
数量的零填充,默认 padding=0
。之所以进行固定熟练的填充点数,是为了遵循当 Conv1d
和 ConvTranspose1d
使用相同的参数初始化时,它们在输入和输出形状方面互为倒数 。output_padding
:可选参数,类型为 int、tuple of one int
,控制添加到输出形状一侧的附加尺寸,默认为 output_padding=0
。该参数的作用是处理当 stride>1
时的情况:Conv1d
将多个输入形状映射到相同的输出形状,output_padding
通过有效增加一侧计算后的输出形状来解决这种歧义。注:output_padding
仅用于查找输出形状,但实际上并未向输出执行零填充。padding_mode
:可选参数,类型为 string
,控制填充模式 zeros-零填充, reflect-镜像填充, replicate-复制填充, circular
,默认为 padding_mode=zeros
;dilation
:可选参数,类型为 int、tuple
,控制卷积核元素的间距,默认 dilation=1
就是标准卷积,更改该参数的话标准卷积就变成了 膨胀卷积(空洞卷积),参考 [1];groups
:可选参数,类型为 int
,控制从输入到输出之间的连接数,该参数必须满足能够整除input_channels & output_channels
,默认为 groups=1
,例如:
groups=1
时,所有的输入都会被卷积到输出;groups=2
时,相当于并排放置两个 conv1d
层,每个层会传入一半的 input_channels
并产生一半的 output_channels
,然后将两者连接起来;groups=input_channels
时,每个 input_channels
只会与该通道的大小为 o u t p u t _ c h a n n e l s i n p u t _ c h a n n e l s \frac{output{\_}channels}{input{\_}channels} input_channelsoutput_channels 的滤波器进行卷积;bias
:可选参数,类型为 bool
,若 bias=True
,则会添加可学习的偏差参数,默认值为 bias=True
。input shape
: ( N , C i n , L i n ) (N, C_{in}, L_{in}) (N,Cin,Lin)output shape
: ( N , C o u t , L o u t ) (N, C_{out}, L_{out}) (N,Cout,Lout)在卷积的过程中,可以学习的
ConvTranspose1d.weight
:类型为 Tensor
,代表模型中可学习的权重,shape 为 ( o u t _ c h a n n e l s , i n _ c h a n n e l s g r o u p s , k e r n e l _ s i z e ) (out{\_}channels, \frac{in{\_}channels}{groups}, kernel{\_}size) (out_channels,groupsin_channels,kernel_size),这些值是从 μ ( − k , k ) , k = g r o u p s C _ o u t ∗ k e r n e l _ s i z e \mu(-\sqrt{k}, \sqrt{k}),{\ }k=\frac{groups}{C{\_}{out}*kernel{\_}size} μ(−k,k), k=C_out∗kernel_sizegroups 取样得到;ConvTranspose1d.bias
:类型为 Tensor
,代表模型中可学习的偏差,shape 为 ( o u t _ c h a n n e l s ) (out{\_}channels) (out_channels)。如果参数 bias=True
,那么这些值是从 μ ( − k , k ) , k = g r o u p s C _ o u t ∗ k e r n e l _ s i z e \mu(-\sqrt{k}, \sqrt{k}),{\ }k=\frac{groups}{C{\_}{out}*kernel{\_}size} μ(−k,k), k=C_out∗kernel_sizegroups 取样得到。import torch
import torch.nn as nn
conv_layers = [nn.ConvTranspose1d(16, 33, 3, stride=2),
nn.ConvTranspose1d(16, 33, 3, stride=2, padding=2),
nn.ConvTranspose1d(16, 33, 3, stride=2, padding=2, output_padding=1),
nn.ConvTranspose1d(16, 33, 3, stride=2, padding=2, output_padding=1, dilation=3)
]
input_data = torch.randn(20, 16, 30)
for i in range(len(conv_layers)):
output_data = conv_layers[i](input_data)
print(output_data.shape)
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')
ConvTranspose2d
的作用就是对输入数据执行 二维转置卷积,可以看作是 Conv2d
相对于其输入的梯度。
参数:
in_channels
:类型为 int
,表示输入数据的通道数;out_channels
:类型为 int
,表示经过二维转置卷积操作后输出数据的通道数;kernel_size
:类型为 int、tuple of two ints
,表示卷积核的大小;
int
时,宽高将使用同样的尺寸值;tuple of two ints
时,第一个 int
用于高度尺寸,第二个 int
用于宽度尺寸。下同。stride
:可选参数,类型为 int、tuple of two ints
,控制进行卷积的步长,默认 stride=1
;padding
:可选参数,类型为 int、tuple of two ints
,可对输入进行 dilation * (kernel_size-1) - padding
数量的零填充,默认 padding=0
。之所以进行固定熟练的填充点数,是为了遵循当 Conv2d
和 ConvTranspose2d
使用相同的参数初始化时,它们在输入和输出形状方面互为倒数 。output_padding
:可选参数,类型为 int、tuple of two ints
,控制添加到输出形状一侧的附加尺寸,默认为 output_padding=0
。该参数的作用是处理当 stride>1
时的情况:Conv2d
将多个输入形状映射到相同的输出形状,output_padding
通过有效增加一侧计算后的输出形状来解决这种歧义。注:output_padding
仅用于查找输出形状,但实际上并未向输出执行零填充。padding_mode
:可选参数,类型为 string
,控制填充模式 zeros-零填充, reflect-镜像填充, replicate-复制填充, circular
,默认为 padding_mode=zeros
;dilation
:可选参数,类型为 int、tuple of two ints
,控制卷积核元素的间距,默认 dilation=1
就是标准卷积,更改该参数的话标准卷积就变成了 膨胀卷积(空洞卷积),参考 [1];groups
:可选参数,类型为 int
,控制从输入到输出之间的连接数,该参数必须满足能够整除input_channels & output_channels
,默认为 groups=1
,例如:
groups=1
时,所有的输入都会被卷积到输出;groups=2
时,相当于并排放置两个 conv1d
层,每个层会传入一半的 input_channels
并产生一半的 output_channels
,然后将两者连接起来;groups=input_channels
时,每个 input_channels
只会与该通道的大小为 o u t p u t _ c h a n n e l s i n p u t _ c h a n n e l s \frac{output{\_}channels}{input{\_}channels} input_channelsoutput_channels 的滤波器进行卷积;bias
:可选参数,类型为 bool
,若 bias=True
,则会添加可学习的偏差参数,默认值为 bias=True
。input shape
: ( N , C i n , H i n , W i n ) (N, C_{in}, H_{in}, W_{in}) (N,Cin,Hin,Win)output shape
: ( N , C o u t , H o u t , W o u t ) (N, C_{out}, H_{out}, W_{out}) (N,Cout,Hout,Wout)ConvTranspose2d.weight
:类型为 Tensor
,代表模型中可学习的权重,shape 为 ( o u t _ c h a n n e l s , i n _ c h a n n e l s g r o u p s , k e r n e l _ s i z e [ 0 ] , k e r n e l _ s i z e [ 1 ] ) (out{\_}channels, \frac{in{\_}channels}{groups}, kernel{\_}size[0], kernel{\_}size[1]) (out_channels,groupsin_channels,kernel_size[0],kernel_size[1]),这些值是从 μ ( − k , k ) , k = g r o u p s C _ o u t ∗ k e r n e l _ s i z e [ 0 ] ∗ k e r n e l _ s i z e [ 1 ] \mu(-\sqrt{k}, \sqrt{k}),{\ }k=\frac{groups}{C{\_}{out}*kernel{\_}size[0]*kernel{\_}size[1]} μ(−k,k), k=C_out∗kernel_size[0]∗kernel_size[1]groups 取样得到;ConvTranspose2d.bias
:类型为 Tensor
,代表模型中可学习的偏差,shape 为 ( o u t _ c h a n n e l s ) (out{\_}channels) (out_channels)。如果参数 bias=True
,那么这些值是从 μ ( − k , k ) , k = g r o u p s C _ o u t ∗ k e r n e l _ s i z e [ 0 ] ∗ k e r n e l _ s i z e [ 1 ] \mu(-\sqrt{k}, \sqrt{k}),{\ }k=\frac{groups}{C{\_}{out}*kernel{\_}size[0]*kernel{\_}size[1]} μ(−k,k), k=C_out∗kernel_size[0]∗kernel_size[1]groups 取样得到。import torch
import torch.nn as nn
conv_layers = [nn.ConvTranspose2d(16, 33, 3, stride=2), # With square kernels and equal stride
# non-square kernels and unequal stride and with padding
nn.ConvTranspose2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2)),
# non-square kernels and unequal stride and with padding & output_padding
nn.ConvTranspose2d(16, 33, 3, stride=(2, 1), padding=(4, 2), output_padding=(1, 0)),
]
input_data = torch.randn(20, 16, 50, 100)
for i in range(len(conv_layers)):
output_data = conv_layers[i](input_data)
print(output_data.shape)
官网还给了另外一种应用形式,即用给定的数据进行转置卷积。通过下面的例子可以发现转置卷积和卷积是互为逆过程的。需要注意的地方是,转置卷积只可以恢复尺寸并不能保证数据也是和原始值是一样的。
import torch
import torch.nn as nn
input_data = torch.randn(1, 16, 12, 12)
down_sample = nn.Conv2d(16, 16, 3, stride=2, padding=1)
up_sample = nn.ConvTranspose2d(16, 16, 3, stride=2, padding=1)
# 计算正向卷积的输出
pe_output = down_sample(input_data)
print(pe_output.size())
# 将上述输出作为转置卷积的输入
# 可以发现最终的输出和原始输入的尺寸是一致的
output = up_sample(pe_output, output_size=input_data.size())
print(output.size())
# 检验输入和输出的值是否相同,显然是不同的
print(input_data.equal(output))
原型:torch.nn.ConvTranspose3d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True, dilation=1, padding_mode='zeros')
ConvTranspose3d
的作用就是对输入数据执行 三维转置卷积,可描述为:在由多个输入平面组成的输入图像上应用 ConvTranspose3d
,会将每个输入值逐个乘以一个可学习的内核,并对所有输入特征平面的输出求和。该模块可以看作是 Conv3d
相对于其输入的梯度。
参数:
in_channels
:类型为 int
,表示输入数据的通道数;out_channels
:类型为 int
,表示经过三维转置卷积操作后输出数据的通道数;kernel_size
:类型为 int、tuple of three ints
,表示卷积核的大小;
int
时,宽高将使用同样的尺寸值;tuple of three ints
时,第一个 int
用于深度尺寸,第二个 int
用于高度尺寸,第二个 int
用于宽度尺寸。下同。stride
:可选参数,类型为 int、tuple of three ints
,控制进行卷积的步长,默认 stride=1
;padding
:可选参数,类型为 int、tuple of three ints
,可对输入进行 dilation * (kernel_size-1) - padding
数量的零填充,默认 padding=0
。output_padding
:可选参数,类型为 int、tuple of two ints
,控制添加到输出形状一侧的附加尺寸,默认为 output_padding=0
。该参数的作用是处理当 stride>1
时的情况:Conv3d
将多个输入形状映射到相同的输出形状,output_padding
通过有效增加一侧计算后的输出形状来解决这种歧义。注:output_padding
仅用于查找输出形状,但实际上并未向输出执行零填充。padding_mode
:可选参数,类型为 string
,控制填充模式 zeros-零填充, reflect-镜像填充, replicate-复制填充, circular
,默认为 padding_mode=zeros
;dilation
:可选参数,类型为 int、tuple of two ints
,控制卷积核元素的间距,默认 dilation=1
就是标准卷积,更改该参数的话标准卷积就变成了 膨胀卷积(空洞卷积),参考 [1];groups
:可选参数,类型为 int
,控制从输入到输出之间的连接数,该参数必须满足能够整除input_channels & output_channels
,默认为 groups=1
,例如:
groups=1
时,所有的输入都会被卷积到输出;groups=2
时,相当于并排放置两个 conv1d
层,每个层会传入一半的 input_channels
并产生一半的 output_channels
,然后将两者连接起来;groups=input_channels
时,每个 input_channels
只会与该通道的大小为 o u t p u t _ c h a n n e l s i n p u t _ c h a n n e l s \frac{output{\_}channels}{input{\_}channels} input_channelsoutput_channels 的滤波器进行卷积;bias
:可选参数,类型为 bool
,若 bias=True
,则会添加可学习的偏差参数,默认值为 bias=True
。input shape
: ( N , C i n , D i n , H i n , W i n ) (N, C_{in}, D_{in}, H_{in}, W_{in}) (N,Cin,Din,Hin,Win)output shape
: ( N , C o u t , D o u t , H o u t , W o u t ) (N, C_{out}, D_{out}, H_{out}, W_{out}) (N,Cout,Dout,Hout,Wout)在转置卷积的过程中,可以学习权重和偏差:
ConvTranspose3d.weight
:类型为 Tensor
,代表模型中可学习的权重,shape 为 ( o u t _ c h a n n e l s , i n _ c h a n n e l s g r o u p s , k e r n e l _ s i z e [ 0 ] , k e r n e l _ s i z e [ 1 ] , k e r n e l _ s i z e [ 2 ] ) (out{\_}channels, \frac{in{\_}channels}{groups}, kernel{\_}size[0], kernel{\_}size[1], kernel{\_}size[2]) (out_channels,groupsin_channels,kernel_size[0],kernel_size[1],kernel_size[2]),这些值是从 μ ( − k , k ) , k = g r o u p s C _ o u t ∗ k e r n e l _ s i z e [ 0 ] ∗ k e r n e l _ s i z e [ 1 ] ∗ k e r n e l _ s i z e [ 2 ] \mu(-\sqrt{k}, \sqrt{k}),{\ }k=\frac{groups}{C{\_}{out}*kernel{\_}size[0]*kernel{\_}size[1]*kernel{\_}size[2]} μ(−k,k), k=C_out∗kernel_size[0]∗kernel_size[1]∗kernel_size[2]groups 取样得到;ConvTranspose3d.bias
:类型为 Tensor
,代表模型中可学习的偏差,shape 为 ( o u t _ c h a n n e l s ) (out{\_}channels) (out_channels)。如果参数 bias=True
,那么这些值是从 μ ( − k , k ) , k = g r o u p s C _ o u t ∗ k e r n e l _ s i z e [ 0 ] ∗ k e r n e l _ s i z e [ 1 ] ∗ k e r n e l _ s i z e [ 2 ] \mu(-\sqrt{k}, \sqrt{k}),{\ }k=\frac{groups}{C{\_}{out}*kernel{\_}size[0]*kernel{\_}size[1]*kernel{\_}size[2]} μ(−k,k), k=C_out∗kernel_size[0]∗kernel_size[1]∗kernel_size[2]groups 取样得到。import torch
import torch.nn as nn
conv_layers = [nn.ConvTranspose3d(16, 33, 3, stride=2), # With square kernels and equal stride
# non-square kernels and unequal stride and with padding
nn.ConvTranspose3d(16, 33, (3, 5, 2), stride=(2, 1, 1), padding=(0, 4, 2)),
# non-square kernels and unequal stride and with padding & output_padding
nn.ConvTranspose3d(16, 33, (3, 5, 2), stride=(2, 1, 1), padding=(0, 4, 2), output_padding=(1, 0, 0)),
]
input_data = torch.randn(20, 16, 10, 50, 100)
for i in range(len(conv_layers)):
output_data = conv_layers[i](input_data)
print(output_data.shape)
torch.nn.LazyConv1d(out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')
LazyConv1d
本质上就是 Conv1d
,只不过是使用了延迟初始化的卷积,也就是利用 input.size(1) = Conv1d的参数in_channels
进行延迟初始化。
参数:
out_channels
:类型为 int
,表示经过延迟卷积后的输出通道数;kernel_size
:类型为 int、tuple of one int
,控制卷积核的大小;stride
:可选参数,类型为 int、tuple of one int
,控制卷积的步长,默认为 stride=1
;padding
:可选参数,类型为 int、tuple of one int
,控制对输入两侧进行填充点的数量,默认为 stride=0
表示不进行填充;padding_mode
:可选参数,类型为 string
,控制填充模式 zeros-零填充, reflect-镜像填充, replicate-复制填充, circular
,默认为 padding_mode=zeros
;dilation
:可选参数,类型为 int、tuple of one int
,控制卷积核元素的间距,默认 dilation=1
就是标准卷积;groups
:可选参数,类型为 int
,控制从输入到输出之间的连接数,该参数必须满足能够整除input_channels & output_channels
,默认为 groups=1
;bias
:可选参数,类型为 bool
,若 bias=True
,则会添加可学习的偏差参数,默认值为 bias=True
。torch.nn.LazyConv2d(out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')
LazyConv2d
是使用了延迟初始化的 Conv2d
,也就是利用 input.size(1) = Conv2d 的参数 in_channels
进行延迟初始化。
参数:
out_channels
:类型为 int
,表示经过延迟卷积后的输出通道数;kernel_size
:类型为 int、tuple of two ints
,控制卷积核的大小;stride
:可选参数,类型为 int、tuple of two ints
,控制卷积的步长,默认为 stride=1
;padding
:可选参数,类型为 int、tuple of two ints
,控制对输入两侧进行填充点的数量,默认为 stride=0
表示不进行填充;padding_mode
:可选参数,类型为 string
,控制填充模式 zeros-零填充, reflect-镜像填充, replicate-复制填充, circular
,默认为 padding_mode=zeros
;dilation
:可选参数,类型为 int、tuple of two ints
,控制卷积核元素的间距,默认 dilation=1
就是标准卷积;groups
:可选参数,类型为 int
,控制从输入到输出之间的连接数,该参数必须满足能够整除input_channels & output_channels
,默认为 groups=1
;bias
:可选参数,类型为 bool
,若 bias=True
,则会添加可学习的偏差参数,默认值为 bias=True
。torch.nn.LazyConv3d(out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')
LazyConv3d
是使用了延迟初始化的 Conv3d
,即利用 input.size(1) = Conv3d 的参数 in_channels
进行延迟初始化。
参数:
out_channels
:类型为 int
,表示经过延迟卷积后的输出通道数;kernel_size
:类型为 int、tuple of three ints
,控制卷积核的大小;stride
:可选参数,类型为 int、tuple of three ints
,控制卷积的步长,默认为 stride=1
;padding
:可选参数,类型为 int、tuple of three ints
,控制对输入两侧进行填充点的数量,默认为 stride=0
表示不进行填充;padding_mode
:可选参数,类型为 string
,控制填充模式 zeros-零填充, reflect-镜像填充, replicate-复制填充, circular
,默认为 padding_mode=zeros
;dilation
:可选参数,类型为 int、tuple of three ints
,控制卷积核元素的间距,默认 dilation=1
就是标准卷积;groups
:可选参数,类型为 int
,控制从输入到输出之间的连接数,该参数必须满足能够整除input_channels & output_channels
,默认为 groups=1
;bias
:可选参数,类型为 bool
,若 bias=True
,则会添加可学习的偏差参数,默认值为 bias=True
。torch.nn.LazyConvTranspose1d(out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True, dilation=1, padding_mode='zeros')
torch.nn.LazyConvTranspose1d
本质上是使用了延迟初始化 ConvTranspose1d
,利用 input.size(1) = ConvTranspose1d 的参数 in_channels
进行延迟初始化。
参数:
out_channels
:类型为 int
,表示输出通道数;kernel_size
:类型为 int、tuple of one int
,表示卷积核的大小;stride
:可选参数,类型为 int、tuple of one int
,控制进行卷积的步长,默认 stride=1
;padding
:可选参数,类型为 int、tuple of one int
,可对输入的两侧进行 dilation * (kernel_size-1) - padding
数量的零填充,默认 padding=0
。之所以进行固定熟练的填充点数,是为了遵循当 Conv1d
和 ConvTranspose1d
使用相同的参数初始化时,它们在输入和输出形状方面互为倒数 。output_padding
:可选参数,类型为 int、tuple of one int
,控制添加到输出形状一侧的附加尺寸,默认为 output_padding=0
。padding_mode
:可选参数,类型为 string
,控制填充模式 zeros-零填充, reflect-镜像填充, replicate-复制填充, circular
,默认为 padding_mode=zeros
;dilation
:可选参数,类型为 int、tuple
,控制卷积核元素的间距,默认 dilation=1
就是标准卷积,更改该参数的话标准卷积就变成了 膨胀卷积(空洞卷积),参考 [1];groups
:可选参数,类型为 int
,控制从输入到输出之间的连接数,该参数必须满足能够整除input_channels & output_channels
,默认为 groups=1
;bias
:可选参数,类型为 bool
,若 bias=True
,则会添加可学习的偏差参数,默认值为 bias=True
。torch.nn.LazyConvTranspose2d(out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True, dilation=1, padding_mode='zeros')')
LazyConvTransposed2d
是使用了延迟初始化的 ConvTransposed2d
,也就是利用 input.size(1) = ConvTransposed2d 的参数 in_channels
进行延迟初始化。
参数:
out_channels
:类型为 int
,表示输出通道数;kernel_size
:类型为 int、tuple of two ints
,表示卷积核的大小;stride
:可选参数,类型为 int、tuple of two ints
,控制进行卷积的步长,默认 stride=1
;padding
:可选参数,类型为 int、tuple of two ints
,可对输入的两侧进行 dilation * (kernel_size-1) - padding
数量的零填充,默认 padding=0
。之所以进行固定熟练的填充点数,是为了遵循当 Conv1d
和 ConvTranspose1d
使用相同的参数初始化时,它们在输入和输出形状方面互为倒数 。output_padding
:可选参数,类型为 int、tuple of two ints
,控制添加到输出形状一侧的附加尺寸,默认为 output_padding=0
。padding_mode
:可选参数,类型为 string
,控制填充模式 zeros-零填充, reflect-镜像填充, replicate-复制填充, circular
,默认为 padding_mode=zeros
;dilation
:可选参数,类型为 int、tuple of two ints
,控制卷积核元素的间距,默认 dilation=1
就是标准卷积,更改该参数的话标准卷积就变成了 膨胀卷积(空洞卷积),参考 [1];groups
:可选参数,类型为 int、tuple of two ints
,控制从输入到输出之间的连接数,该参数必须满足能够整除input_channels & output_channels
,默认为 groups=1
;bias
:可选参数,类型为 bool
,若 bias=True
,则会添加可学习的偏差参数,默认值为 bias=True
。torch.nn.LazyConvTranspose3d(out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True, dilation=1, padding_mode='zeros')
LazyConvTransposed3d
是使用了延迟初始化的 ConvTransposed3d
,也就是利用 input.size(1) = ConvTransposed3d 的参数 in_channels
进行延迟初始化。
参数:
out_channels
:类型为 int
,表示输出通道数;kernel_size
:类型为 int、tuple of three ints
,表示卷积核的大小;stride
:可选参数,类型为 int、tuple of three ints
,控制进行卷积的步长,默认 stride=1
;padding
:可选参数,类型为 int、tuple of three ints
,可对输入的两侧进行 dilation * (kernel_size-1) - padding
数量的零填充,默认 padding=0
。之所以进行固定熟练的填充点数,是为了遵循当 Conv1d
和 ConvTranspose1d
使用相同的参数初始化时,它们在输入和输出形状方面互为倒数 。output_padding
:可选参数,类型为 int、tuple of three ints
,控制添加到输出形状一侧的附加尺寸,默认为 output_padding=0
。padding_mode
:可选参数,类型为 string
,控制填充模式 zeros-零填充, reflect-镜像填充, replicate-复制填充, circular
,默认为 padding_mode=zeros
;dilation
:可选参数,类型为 int、tuple of two ints
,控制卷积核元素的间距,默认 dilation=1
就是标准卷积,更改该参数的话标准卷积就变成了 膨胀卷积(空洞卷积),参考 [1];groups
:可选参数,类型为 int、tuple of three ints
,控制从输入到输出之间的连接数,该参数必须满足能够整除input_channels & output_channels
,默认为 groups=1
;bias
:可选参数,类型为 bool
,若 bias=True
,则会添加可学习的偏差参数,默认值为 bias=True
。该方法 torch.nn.Unfold(kernel_size, dilation=1, padding=0, stride=1)
可以从批量输入张量中提取滑动局部块。目前没有怎么用到这块所以就先不记录了。
与上面的方法相反的是 torch.nn.Fold(output_size, kernel_size, dilation=1, padding=0, stride=1)
可以将一组滑动局部块组合成一个大的组合张量。
[1]. 膨胀卷积