# 5.2 填充和步幅
在上一節的例子里,我們使用高和寬為3的輸入與高和寬為2的卷積核得到高和寬為2的輸出。一般來說,假設輸入形狀是`$ n_h\times n_w $`,卷積核窗口形狀是`$ k_h\times k_w $`,那么輸出形狀將會是
```[tex]
(n_h-k_h+1) \times (n_w-k_w+1).
```
所以卷積層的輸出形狀由輸入形狀和卷積核窗口形狀決定。本節我們將介紹卷積層的兩個超參數,即填充和步幅。它們可以對給定形狀的輸入和卷積核改變輸出形狀。
## 5.2.1 填充
填充(padding)是指在輸入高和寬的兩側填充元素(通常是0元素)。圖5.2里我們在原輸入高和寬的兩側分別添加了值為0的元素,使得輸入高和寬從3變成了5,并導致輸出高和寬由2增加到4。圖5.2中的陰影部分為第一個輸出元素及其計算所使用的輸入和核數組元素:`$ 0\times0+0\times1+0\times2+0\times3=0 $`。
:-: 
<div align=center>圖5.2 在輸入的高和寬兩側分別填充了0元素的二維互相關計算</div>
一般來說,如果在高的兩側一共填充`$ p_h $`行,在寬的兩側一共填充`$ p_w $`列,那么輸出形狀將會是
```[tex]
(n_h-k_h+p_h+1)\times(n_w-k_w+p_w+1),
```
也就是說,輸出的高和寬會分別增加`$ p_h $`和`$ p_w $`。
在很多情況下,我們會設置`$ p_h=k_h-1 $`和`$ p_w=k_w-1 $`來使輸入和輸出具有相同的高和寬。這樣會方便在構造網絡時推測每個層的輸出形狀。假設這里`$ k_h $`是奇數,我們會在高的兩側分別填充`$ p_h /2 $`行。如果`$ k_h $`是偶數,一種可能是在輸入的頂端一側填充`$ \lceil p_h/2\rceil $`行,而在底端一側填充`$ \lfloor p_h/2\rfloor $`行。在寬的兩側填充同理。
卷積神經網絡經常使用奇數高寬的卷積核,如1、3、5和7,所以兩端上的填充個數相等。對任意的二維數組`X`,設它的第`i`行第`j`列的元素為`X[i,j]`。當兩端上的填充個數相等,并使輸入和輸出具有相同的高和寬時,我們就知道輸出`Y[i,j]`是由輸入以`X[i,j]`為中心的窗口同卷積核進行互相關計算得到的。
下面的例子里我們創建一個高和寬為3的二維卷積層,然后設輸入高和寬兩側的填充數分別為1。給定一個高和寬為8的輸入,我們發現輸出的高和寬也是8。
``` python
import torch
from torch import nn
# 定義一個函數來計算卷積層。它對輸入和輸出做相應的升維和降維
def comp_conv2d(conv2d, X):
# (1, 1)代表批量大小和通道數(“多輸入通道和多輸出通道”一節將介紹)均為1
X = X.view((1, 1) + X.shape)
Y = conv2d(X)
return Y.view(Y.shape[2:]) # 排除不關心的前兩維:批量和通道
# 注意這里是兩側分別填充1行或列,所以在兩側一共填充2行或列
conv2d = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, padding=1)
X = torch.rand(8, 8)
comp_conv2d(conv2d, X).shape
```
輸出:
```
torch.Size([8, 8])
```
當卷積核的高和寬不同時,我們也可以通過設置高和寬上不同的填充數使輸出和輸入具有相同的高和寬。
``` python
# 使用高為5、寬為3的卷積核。在高和寬兩側的填充數分別為2和1
conv2d = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=(5, 3), padding=(2, 1))
comp_conv2d(conv2d, X).shape
```
輸出:
```
torch.Size([8, 8])
```
## 5.2.2 步幅
在上一節里我們介紹了二維互相關運算。卷積窗口從輸入數組的最左上方開始,按從左往右、從上往下的順序,依次在輸入數組上滑動。我們將每次滑動的行數和列數稱為步幅(stride)。
目前我們看到的例子里,在高和寬兩個方向上步幅均為1。我們也可以使用更大步幅。圖5.3展示了在高上步幅為3、在寬上步幅為2的二維互相關運算。可以看到,輸出第一列第二個元素時,卷積窗口向下滑動了3行,而在輸出第一行第二個元素時卷積窗口向右滑動了2列。當卷積窗口在輸入上再向右滑動2列時,由于輸入元素無法填滿窗口,無結果輸出。圖5.3中的陰影部分為輸出元素及其計算所使用的輸入和核數組元素:
`$ 0\times0+0\times1+1\times2+2\times3=8 $`、
`$ 0\times0+6\times1+0\times2+0\times3=6 $`。
:-: 
<div align=center>圖5.3 高和寬上步幅分別為3和2的二維互相關運算</div>
一般來說,當高上步幅為`$ s_h $`,寬上步幅為`$ s_w $`時,輸出形狀為
```[tex]
\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.
```
如果設置`$ p_h=k_h-1 $`和`$ p_w=k_w-1 $`,那么輸出形狀將簡化為`$ \lfloor(n_h+s_h-1)/s_h\rfloor \times \lfloor(n_w+s_w-1)/s_w\rfloor $`。更進一步,如果輸入的高和寬能分別被高和寬上的步幅整除,那么輸出形狀將是`$ (n_h/s_h) \times (n_w/s_w) $`。
下面我們令高和寬上的步幅均為2,從而使輸入的高和寬減半。
``` python
conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1, stride=2)
comp_conv2d(conv2d, X).shape
```
輸出:
```
torch.Size([4, 4])
```
接下來是一個稍微復雜點兒的例子。
``` python
conv2d = nn.Conv2d(1, 1, kernel_size=(3, 5), padding=(0, 1), stride=(3, 4))
comp_conv2d(conv2d, X).shape
```
輸出:
```
torch.Size([2, 2])
```
為了表述簡潔,當輸入的高和寬兩側的填充數分別為`$ p_h $`和`$ p_w $`時,我們稱填充為`$ (p_h, p_w) $`。特別地,當`$ p_h = p_w = p $`時,填充為`$ p $`。當在高和寬上的步幅分別為`$ s_h $`和`$ s_w $`時,我們稱步幅為`$ (s_h, s_w) $`。特別地,當`$ s_h = s_w = s $`時,步幅為`$ s $`。在默認情況下,填充為0,步幅為1。
## 小結
* 填充可以增加輸出的高和寬。這常用來使輸出與輸入具有相同的高和寬。
* 步幅可以減小輸出的高和寬,例如輸出的高和寬僅為輸入的高和寬的`$ 1/n $`(`$ n $`為大于1的整數)。
-----------
> 注:除代碼外本節與原書此節基本相同,[原書傳送門](https://zh.d2l.ai/chapter_convolutional-neural-networks/padding-and-strides.html)
- Home
- Introduce
- 1.深度學習簡介
- 深度學習簡介
- 2.預備知識
- 2.1環境配置
- 2.2數據操作
- 2.3自動求梯度
- 3.深度學習基礎
- 3.1 線性回歸
- 3.2 線性回歸的從零開始實現
- 3.3 線性回歸的簡潔實現
- 3.4 softmax回歸
- 3.5 圖像分類數據集(Fashion-MINST)
- 3.6 softmax回歸的從零開始實現
- 3.7 softmax回歸的簡潔實現
- 3.8 多層感知機
- 3.9 多層感知機的從零開始實現
- 3.10 多層感知機的簡潔實現
- 3.11 模型選擇、反向傳播和計算圖
- 3.12 權重衰減
- 3.13 丟棄法
- 3.14 正向傳播、反向傳播和計算圖
- 3.15 數值穩定性和模型初始化
- 3.16 實戰kaggle比賽:房價預測
- 4 深度學習計算
- 4.1 模型構造
- 4.2 模型參數的訪問、初始化和共享
- 4.3 模型參數的延后初始化
- 4.4 自定義層
- 4.5 讀取和存儲
- 4.6 GPU計算
- 5 卷積神經網絡
- 5.1 二維卷積層
- 5.2 填充和步幅
- 5.3 多輸入通道和多輸出通道
- 5.4 池化層
- 5.5 卷積神經網絡(LeNet)
- 5.6 深度卷積神經網絡(AlexNet)
- 5.7 使用重復元素的網絡(VGG)
- 5.8 網絡中的網絡(NiN)
- 5.9 含并行連結的網絡(GoogLeNet)
- 5.10 批量歸一化
- 5.11 殘差網絡(ResNet)
- 5.12 稠密連接網絡(DenseNet)
- 6 循環神經網絡
- 6.1 語言模型
- 6.2 循環神經網絡
- 6.3 語言模型數據集(周杰倫專輯歌詞)
- 6.4 循環神經網絡的從零開始實現
- 6.5 循環神經網絡的簡單實現
- 6.6 通過時間反向傳播
- 6.7 門控循環單元(GRU)
- 6.8 長短期記憶(LSTM)
- 6.9 深度循環神經網絡
- 6.10 雙向循環神經網絡
- 7 優化算法
- 7.1 優化與深度學習
- 7.2 梯度下降和隨機梯度下降
- 7.3 小批量隨機梯度下降
- 7.4 動量法
- 7.5 AdaGrad算法
- 7.6 RMSProp算法
- 7.7 AdaDelta
- 7.8 Adam算法
- 8 計算性能
- 8.1 命令式和符號式混合編程
- 8.2 異步計算
- 8.3 自動并行計算
- 8.4 多GPU計算
- 9 計算機視覺
- 9.1 圖像增廣
- 9.2 微調
- 9.3 目標檢測和邊界框
- 9.4 錨框
- 10 自然語言處理
- 10.1 詞嵌入(word2vec)
- 10.2 近似訓練
- 10.3 word2vec實現
- 10.4 子詞嵌入(fastText)
- 10.5 全局向量的詞嵌入(Glove)
- 10.6 求近義詞和類比詞
- 10.7 文本情感分類:使用循環神經網絡
- 10.8 文本情感分類:使用卷積網絡
- 10.9 編碼器--解碼器(seq2seq)
- 10.10 束搜索
- 10.11 注意力機制
- 10.12 機器翻譯