神经网络的卷积操作中不同的卷积核和不同的填充获得同样的输出

发布于:2024-06-28 ⋅ 阅读:(14) ⋅ 点赞:(0)

神经网络的卷积操作中不同的卷积核和不同的填充获得同样的输出

nn.Conv2d(in_channels,out_channels,kernel size, stride=l,
padding-0,dilation=l,groups=l,bias=True,padding_mode='zeros',device=None, dtype=None)

nn.Conv2d卷积输人数据的格式是(batch_size,C,H,W),其中 batch_size 是指在一次迭代中输人网络的数据量; C代表输入数据的通道数(channel); H和W分别代表输人数据的长(Height)和宽(Width)。根据不同的需求,需要给Con2d设定不同的参数,下面将对参数的设置方式进行介绍。首先定义卷积操作中各参数对应的符号如下。
H i n / H o u t H_{in}/H_{out} Hin/Hout:代表输入/输出特征图长度,$ W i n / W o u t W_{in}/W_{out} Win/Wout代表输入/输出特征图宽度
KH 代表卷积核的长度、KW 代表卷积核的宽度。
PH 代表长度方向补0的数目、PW 代表宽度方向补0的数目。
SH 代表长度方向卷积步长、SW 代表宽度方向卷积步长。
DH 代表长度方向空洞率、DW 代表宽度方向空洞率。
C i n C_{in} Cin代表输入特征图的通道数、 C o u t C_{out} Cout代表输出特征图的通道数。根据上面的符号设定,可以将特征图的输入和输出尺寸的关系表示如下,floor 向下取整:

H out  = f l o o r ( H in  + 2 × P H − D H × ( K H − 1 ) − 1 S H + 1 ) W out  = f l o o r ( W in  + 2 × P W − D W × ( K W − 1 ) − 1 S W + 1 ) \begin{gathered} H_{\text {out }}=floor(\frac{H_{\text {in }}+2 \times \mathrm{PH}-\mathrm{DH} \times(\mathrm{KH}-1)-1}{\mathrm{SH}}+1 )\\ W_{\text {out }}=floor(\frac{W_{\text {in }}+2 \times \mathrm{PW}-\mathrm{DW} \times(\mathrm{KW}-1)-1}{\mathrm{SW}}+1) \end{gathered} Hout =floor(SHHin +2×PHDH×(KH1)1+1)Wout =floor(SWWin +2×PWDW×(KW1)1+1)

上面的公式总结了 Conv2d 的输入和输出特征图的长宽尺寸计算关系,根据需求选择不同的参数搭配。此外,还需要指定 Conv2d 的输入和输出的通道数。

下面的示例实现了输入和输出特征图长宽相同的卷积计算。根据卷积的计算方式可知,为了保证输入和输出特征图的长宽一致,可以使用步长为1的卷积,所以SH和SW 均设置为1。对于不同的卷积核尺寸(KH,KW),需要计算出对应的补0数目(PH,PW),它们的对应关系如下:

P H = i n t ( K H 2 ) P W = i n t ( K W 2 ) \begin{gathered} \mathrm{PH}=int(\frac{\mathrm{KH}}{2})\\ \mathrm{PW}=int(\frac{\mathrm{KW}}{2}) \end{gathered} PH=int(2KH)PW=int(2KW)

下面将卷积核尺寸 k_size 分别设置为1、3、5和7,这几种卷积核尺寸是最为常用的。所有卷积过程的步长 stride 均设置为1,根据上式计算得到的补0数目分别为0,1,2,3。下面的代码对计算进行了验证,运行后将输出4行torch.Size([1,3,300,400]),证明卷积后输出特征图维度和输入相同。

import torch
import torch.nn as nn
data_in = torch.randn(size=(1, 3, 400, 400))
print(data_in.size())
# 输出结果
k_size = [1, 3, 5, 7]
stride = [1, 1, 1, 1]
pad = [0, 1, 2, 3]
# 输入和输出通道数均设为3
ch_in = 3
ch_out = 3

for i in range(len(k_size)):
    conv2d = nn.Conv2d(ch_in, ch_out, k_size[i], stride[i], pad[i])
    print(conv2d(data_in).size())

输出:

torch.Size([1, 3, 400, 400])
torch.Size([1, 3, 400, 400])
torch.Size([1, 3, 400, 400])
torch.Size([1, 3, 400, 400])