李沐20_卷积层里的填充和步幅——自学笔记

时间:2024-04-14 07:43:53

填充和步幅

给定32✖32的输入图像,应用5✖5大小的卷积核(第一层输出28✖28,第7层输出大小是4✖4,即每一层都-4)

更大的卷积核可以更快地减小输出大小:形状从nk✖nk减少到(nh-kn+1)✖(nw-kw+1)

1.填充

在输入的周围添加额外的行/列,考虑了角落里的特征

(1) 填充ph行和ph列,输出形状是(nh-kh+ph+1)✖(nw-kw+pw+1)
(2) 通常取ph=kh-1, pw=kw-1,核的高宽-1,即-kh+ph+1和-kw+pw+1都消除为0
(3) 当kh为奇数:在上下两侧填充ph/2
(4) 当kh为偶数:在上侧填充ph/2,在下侧填充ph/2

2.步幅

填充减小的输出大小与层数线性相关。

给定输入大小224✖224,在使用5✖5卷积核的情况下,需要55层将输出降低为4✖4,即需要大量计算才能得到较小的输出。

步幅是指行/列的滑动步长。

(1)给定高度sh,宽度sw,输出形状:[(nh-kh+ph+sh)/sh]✖[(nw-kw+pw+sw)/sw]

(2)如果ph=kh-1, pw=kw-1,则[(nh+sh-1)/sh]✖[(nw+sw-1)/sw]

(3)如果输入高度和宽度可以被步幅整除:(nh/sh)✖(nw/sw)

(另外:步幅通常取2)

总结

(1)填充和步幅是卷积层的超参数

(2)填充在输入周围添加额外的行/列,来控制输出形状的减少量

(3)步幅是每次滑动核窗口时的行/列的步长,可以成倍的减少输出形状

代码实现填充和步幅

在所有侧边填充1个像素。

import torch
from torch import nn

def comp_conv2d(conv2d, X):
  X = X.reshape((1,1) + X.shape)
  Y = conv2d(X)
  return Y.reshape(Y.shape[2:])

conv2d=nn.Conv2d(1,1,kernel_size=3,padding=1) # 核大小3✖3,上下左右各填充1行
X=torch.rand(size=(8,8)) # p是2✖2,k是3✖3,满足p=k-1,所有输出的形状不变
comp_conv2d(conv2d,X).shape
torch.Size([8, 8])

填充不同的高度和宽度。

conv2d=nn.Conv2d(1, 1, kernel_size=(5,3), padding=(2,1)) # 核5✖3,为保证输出形状不变,应该填充上下各2,左右各1
comp_conv2d(conv2d, X).shape
torch.Size([8, 8])

将高度和宽度的步幅设置为2

conv2d=nn.Conv2d(1,1,kernel_size=3,padding=1,stride=2) # 当步幅为2,一般输出的形状缩小为原来一半
comp_conv2d(conv2d,X).shape
torch.Size([4, 4])

一个稍微复杂的例子

conv2d=nn.Conv2d(1,1,kernel_size=(3,5),padding=(0,1), stride=(3,4))
comp_conv2d(conv2d,X).shape  # (8-3+0+3)/3=2; (8-5+1*2+4)/4=2
torch.Size([2, 2])