动手学深度学习(pytorch)学习记录24-填充和步幅[学习记录]
目录
- 填充
- 步幅
填充
不填充:
假设输入图像高度为n1,宽度为n2,卷积核高宽为k1、k2,则输出形状为(n1-k1+1)×(n2-k2+1),经过卷积后的图像越来越小,边缘信息不断丢失
填充:
假设添加p1行填充(一半在顶部,一半在底部),添加p2列填充(一半在左侧一半在右侧),输出形状为(n1-k1+p1+1)×(n2-k2+p2+1)
当设置p1=k1-1,p2=k2-1的时候,输入形状和输出形状一致。
如下例,给定宽高为8的输入,则输出的宽高也为8
import torch
from torch import nn# 为了方便起见,我们定义了一个计算卷积层的函数。
# 此函数初始化卷积层权重,并对输入和输出提高和缩减相应的维数
def comp_conv2d(conv2d, X):# 这里的(1,1)表示批量大小和通道数都是1X = X.reshape((1, 1) + X.shape)# size变化 [8,8]-->[1,1,8,8]Y = conv2d(X)# 省略前两个维度:批量大小和通道return Y.reshape(Y.shape[2:])# 请注意,这里每边都填充了1行或1列,因此总共添加了2行或2列
conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1) # 输入通道1,输出通道1,卷积核3×3,每边填充1行/列
X = torch.rand(size=(8, 8))
comp_conv2d(conv2d, X).shape
torch.Size([8, 8])
当卷积核宽高不一样的时候,也可以设置不同的填充宽高,使输出输出形状保持一致。
conv2d = nn.Conv2d(1, 1, kernel_size=(5, 3), padding=(2, 1))
comp_conv2d(conv2d, X).shape
torch.Size([8, 8])
步幅
卷积窗口是从左上角向下向右滑动的,在前面的代码中,滑动的距离是默认的1个元素,即步幅为1
垂直步幅为s1、水平步幅为h2时,输出形状为[(n1-k1+p1+s1)/s1]×[(n2-k2+p2+s2)/s2]
如果设置了p1=k1-1,p2=k2-1,输出形状简化为[(n1+s1-1)/s1]×[(n2+s2-1)/s2]
下面将高度和宽度的步幅设置为2,从而将输入的高度和宽度减半。
conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1, stride=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))
# 原尺寸8×8,填充后8×10,高度方向123一次,456一次,剩下的不够一次,输出高度2;宽度方向,1234一次,5678一次,剩下的不够一次
comp_conv2d(conv2d, X).shape
torch.Size([2, 2])
封面图片来源
欢迎点击我的主页查看更多文章。
本人学习地址https://zh-v2.d2l.ai/
恳请大佬批评指正。