2.2.填充和步幅

我们已经知道,卷积的输出形式取决于输入形式和卷积核的形式。

​ 此外还有其他因素会影响输出的大小。假设以下情景: 有时,在应用了连续的卷积之后,我们最终得到的输出远小于输入大小。这是由于卷积核的宽度和高度通常大于1所导致的。比如,一个240×240像素的图像,经过10层5×5的卷积后,将减少到200×200像素。如此一来,原始图像的边界丢失了许多有用信息。而填充是解决此问题最有效的方法; 有时,我们可能希望大幅降低图像的宽度和高度。例如,如果我们发现原始的输入分辨率十分冗余。步幅则可以在这类情况下提供帮助。

1.填充

​ 容易知道,更大的卷积核可以更快地减小输出大小,但有时我们不想输出变得很小,那么我们可以在输入的周围添加了额外的行/列,这样也可以考虑了角落里数据的特征

在这里插入图片描述

​ 填充后,输出甚至比输入还大了。

​ 填充 p h p_h ph行和 p w p_w pw列,输出形状为 ( n h − k h + p h + 1 ) × ( n w − k w + p w + 1 ) (n_h-k_h+p_h+1)\times(n_w-k_w+p_w+1) (nhkh+ph+1)×(nwkw+pw+1)

​ 通常取 p h = k h − 1 , p w = k w − 1 p_h = k_h -1,p_w = k_w -1 ph=kh1,pw=kw1,当 k h k_h kh为奇数时,在上下两侧填充 p h / 2 p_h/2 ph/2;当 k h k_h kh为偶数时:在上侧填充 ⌈ p h / 2 ⌉ \lceil p_h/2\rceil ph/2,在下侧填充 ⌊ p h / 2 ⌋ \lfloor p_h/2\rfloor ph/2

2.步幅

​ 填充减小的输出大小与层数线性相关:给定输入大小为224×224,在使用5×5卷积核的情况下,需要44层将输出降低到4×4,需要大量计算才能得到较小输出

​ 步幅是指行/列的滑动步长,有时候为了高效计算或是缩减采样次数,卷积窗口可以跳过中间位置,每次滑动多个元素。

​ 例如一个高度为3,宽度为2的步幅:

在这里插入图片描述

​ 给定高度 s h s_h sh和宽度 s w s_w sw的步幅,输出形状是
⌊ ( n h − k h + p h + s h ) / s h ⌋ × ⌊ ( n w − k w + p w + s w ) / s w ⌋ \lfloor (n_h-k_h+p_h+s_h)/s_h\rfloor \times \lfloor (n_w-k_w+p_w+s_w)/s_w\rfloor ⌊(nhkh+ph+sh)/sh×⌊(nwkw+pw+sw)/sw
​ 如果 p h = k h − 1 , p w = k w − 1 p_h = k_h -1,p_w=k_w-1 ph=kh1,pw=kw1则为
⌊ ( n h + s h − 1 ) / s h ⌋ × ⌊ ( n w + s w − 1 ) / s w ⌋ \lfloor (n_h+s_h-1)/s_h\rfloor \times \lfloor (n_w+s_w-1)/s_w\rfloor ⌊(nh+sh1)/sh×⌊(nw+sw1)/sw
​ 如果输入高度和宽度可以被步幅整除:
( n h / s h ) × ( n w / s w ) (n_h/s_h)\times(n_w/s_w) (nh/sh)×(nw/sw)

总结

  1. 填充和步幅是卷积层的超参数
  2. 填充在输入周围添加额外的行/列,来控制输出形状的减少量
  3. 步幅是每次滑动核窗口时的行/列的步长,可以成倍的减少输出形状

代码实现

import torch
from torch import nn


# 为了方便起见,我们定义了一个计算卷积层的函数。
# 此函数初始化卷积层权重,并对输入和输出提高和缩减相应的维数
def comp_conv2d(conv2d, X):
    # 这里的(1,1)表示批量大小和通道数都是1
    X = X.reshape((1, 1) + X.shape)  # +是元组的连接
    Y = conv2d(X)
    # 省略前两个维度:批量大小和通道
    return Y.reshape(Y.shape[2:])


# 请注意,这里每边都填充了1行或1列,因此总共添加了2行或2列
#两个1,1分别为输出通道和输入通道个数
conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1)  # padding=1是上下左右各添加一行
X = torch.rand(size=(8, 8))
# 输入8,填充2,则为8+2+1-3 =8 ,输出还是8行8列
print(comp_conv2d(conv2d, X).shape)

'''填充不同的高度和宽度'''
conv2d = nn.Conv2d(1, 1, kernel_size=(5, 3), padding=(2, 1))  # 上下填充2,左右填充1
# 输入8行8列,对于行,填充了4,则为8+4+1-5=8 ,对于列,填充了2,则为8+2+1-3=8,输出还是8行8列
print(comp_conv2d(conv2d, X).shape)

'''步幅'''
conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1, stride=2)
print(comp_conv2d(conv2d, X).shape)

conv2d = nn.Conv2d(1, 1, kernel_size=(3, 5), padding=(0, 1), stride=(3, 4))
print(comp_conv2d(conv2d, X).shape)

相关推荐

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

    2024-07-21 22:36:03       27 阅读
  2. 【OpenCV 基础知识 22】扩展边界并填充

    2024-07-21 22:36:03       25 阅读
  3. STM32学习实践笔记(26):USART配置步骤

    2024-07-21 22:36:03       31 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 22:36:03       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 22:36:03       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 22:36:03       45 阅读
  4. Python语言-面向对象

    2024-07-21 22:36:03       55 阅读

热门阅读

  1. 数学建模--灰色关联分析法

    2024-07-21 22:36:03       19 阅读
  2. 什么是 MLPerf?

    2024-07-21 22:36:03       20 阅读
  3. Docker

    2024-07-21 22:36:03       16 阅读
  4. 代码改进,模型优化,强化深度学习

    2024-07-21 22:36:03       19 阅读
  5. python 基础知识点(一)

    2024-07-21 22:36:03       17 阅读
  6. Python利用psutil库进行监控进程和资源

    2024-07-21 22:36:03       17 阅读
  7. SpringBoot RestHighLevelClient 按版本更新

    2024-07-21 22:36:03       20 阅读
  8. 跨域问题几种解决方法

    2024-07-21 22:36:03       20 阅读
  9. Python面试整理-文件处理

    2024-07-21 22:36:03       15 阅读