我们发现在不使用padding操作时,经过卷积操作后,输出图像比输入图像小一点。
为保证输出图像的大小不变,我们可以使用padding操作:
conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1)
pool1 = nn.MaxPool2d(2)
conv2 = nn.Conv2d(16, 8, kernel_size=3, padding=1)
pool2 = nn.MaxPool2d(2)
output1 = conv1(img.unsqueeze(0))
print(img.unsqueeze(0).shape)
print(output1.shape)
output2 = pool1(output1)
print(output2.shape)
output3 = conv2(output2)
print(output3.shape)
output4 = pool1(output3)
print(output4.shape)
输出:
可见只有池化操作使图像减半。
先放计算公式:
对于尺寸为WxH大小的输入图像,卷积层使用的卷积核大小为fxf,步长为s,padding=p。
则输出的图像尺寸:
我们来验证一下:
(1,3,32,32)——>conv1(3,16,kernel_size=3,padding=1)
其中,f = 3, s = 1(默认值),p = 1
w' = (32 + 2*1 - 3)/1 + 1 = 32 输出尺寸不改变
其他可以同理进行验证。
但是,padding=1并不是会保证其他尺寸卷积核作用下的图像大小不变:
###5x5卷积核对图片尺寸的影响
conv1 = nn.Conv2d(3, 16, kernel_size=5, padding=1)
pool1 = nn.MaxPool2d(2)
conv2 = nn.Conv2d(16, 8, kernel_size=5, padding=1)
pool2 = nn.MaxPool2d(2)
output1 = conv1(img.unsqueeze(0))
print(img.unsqueeze(0).shape)
print(output1.shape)
output2 = pool1(output1)
print(output2.shape)
output3 = conv2(output2)
print(output3.shape)
output4 = pool1(output3)
print(output4.shape)
输出:
这是符合上边公式的。
值得一提的是,13x13的尺寸在经过最大池化层后尺寸变为6x6,可以验证池化层之后的尺寸是向下取整的:13/2 = 6。
如果我们想在使用5x5卷积核时保持输出图像的大小不变,怎么选择padding?
很简单,接着上边例子,解下边方程即可:
32 = (32 + 2p - 5)/ 1 + 1
解得p=2,验证一下:
###5x5卷积核对图片尺寸的影响
conv1 = nn.Conv2d(3, 16, kernel_size=5, padding=2)
pool1 = nn.MaxPool2d(2)
conv2 = nn.Conv2d(16, 8, kernel_size=5, padding=2)
pool2 = nn.MaxPool2d(2)
output1 = conv1(img.unsqueeze(0))
print(img.unsqueeze(0).shape)
print(output1.shape)
output2 = pool1(output1)
print(output2.shape)
output3 = conv2(output2)
print(output3.shape)
output4 = pool1(output3)
print(output4.shape)
确实~