动手学深度学习 5.2 填充和步幅

前言

从零开始学习ai文章系列计划是个人在《动手学深度学习》和《磨菇书》两本书的学习中的个人笔记,文章也会以课本中的章节分开,即每个章节一片笔记。我会尽量的把主要内容以及遇到的难点进行记录与解决,如果哪里有错误的欢迎指正。或者不清晰的可以直接查看原文部分。

《动手学深度学习》原文(课本):https://tangshusen.me/Dive-into-DL-PyTorch/#/

《动手学深度学习》代码:https://github.com/ShusenTang/Dive-into-DL-PyTorch

(由于有时候公式太多,可能会直接贴图片)

在上一节的例子里,我们使用高和宽为3的输入与高和宽为2的卷积核得到高和宽为2的输出。

一般来说,假设输入形状是 \(n_h*n_w\) ,卷积核窗口形状是 \(k_h*k_w\) ,那么输出形状将会是
\[ (n_h-k_h+1)*(n_w-k_w+1) \] 所以卷积层的输出形状由输入形状和卷积核窗口形状决定。本节我们将介绍卷积层的两个超参数,即填充和步幅。它们可以对给定形状的输入和卷积核改变输出形状。

1. 填充

填充(padding)是指在输入高和宽的两侧填充元素(通常是0元素)

图5.2里我们在原输入高和宽的两侧分别添加了值为0的元素,使得输入高和宽从3变成了5,并导致输出高和宽由2增加到4

一般来说,如果在高的两侧一共填充 \(p_h\) 行,在宽的两侧一共填充 \(p_w\) 列,那么输出形状将会是 \[ (n_h-k_h+p_h+1)*(n_w-k_w+p_w+1) \] 也就是说,输出的高和宽会分别增加 \(p_h\)\(p_w\)

在很多情况下,我们会设置 \(p_h = k_h-1\)\(p_w = k_w-1\) 来使输入和输出具有相同的高和宽。这样会方便在构造网络时推测每个层的输出形状。

假设 \(k_h\) 是奇数,(那么 \(k_h-1\) 就是偶数),我们会在高的两侧分别填充 \(\frac{p_h}{2}\) 行 。

假设 \(k_h\) 是偶数,(那么 \(k_h-1\) 就是奇数),我们会在高或底的某一侧填充 \(\frac{p_h}{2}\) 行 。

对于宽 \(k_w\) 同理。

卷积神经网络经常使用奇数高宽的卷积核,如1、3、57,所以两端上的填充个数相等。

下面的例子里我们创建一个高和宽为3的二维卷积层,然后设输入高和宽两侧的填充数分别为1。给定一个高和宽为8的输入,我们发现输出的高和宽也是8

当卷积核的高和宽不同时,我们也可以通过设置高和宽上不同的填充数使输出和输入具有相同的高和宽。

在行的部分添加4行,即两侧分别添加2行,列的部分同理两侧添加1列(注意这里卷积核是5x3

2. 步幅

我们将每次滑动的行数和列数称为步幅(stride)。目前我们看到的例子里,在高和宽两个方向上步幅均为1。我们也可以使用更大步幅。

一般来说,当高上步幅为 \(s_h\) ,宽上步幅为 \(s_w\) 时,输出形状为(注意这里不是中括号,而是向下取整符号) \[ \lfloor (n_h-k_h+p_h+s_h)/s_h\rfloor * \lfloor (n_w-k_w+p_w+s_w)/s_w\rfloor \] 如果我们设置 \(p_h = k_h-1\)\(p_w = k_w-1\) ,么输出形状将简化为 \[ \lfloor (n_h+s_h-1)/s_h\rfloor * \lfloor (n_w+s_w-1)/s_w\rfloor \] 更进一步,如果输入的高和宽能分别被高和宽上的步幅整除,那么输出形状将是 \[ \lfloor n_h/s_h\rfloor * \lfloor n_w/s_w\rfloor \]

\(\lfloor (s_h-1)/s_h\rfloor\)0

下面我们令高和宽上的步幅均为2,从而使输入的高和宽减半。

同理可以分别设置高和宽上的步幅