5.2 填充和步幅
所以卷積層的輸出形狀由輸入形狀和卷積核窗口形狀決定糜值。本節(jié)我們將介紹卷積層的兩個(gè)超參數(shù),即填充和步幅赊抖。它們可以對(duì)給定形狀的輸入和卷積核改變輸出形狀页衙。
5.2.1 填充
填充(padding)是指在輸入高和寬的兩側(cè)填充元素(通常是0元素)爹凹。圖5.2里我們?cè)谠斎敫吆蛯挼膬蓚?cè)分別添加了值為0的元素竖般,使得輸入高和寬從3變成了5零酪,并導(dǎo)致輸出高和寬由2增加到4。圖5.2中的陰影部分為第一個(gè)輸出元素及其計(jì)算所使用的輸入和核數(shù)組元素:
0×0+0×1+0×2+0×3=0驮肉。
卷積神經(jīng)網(wǎng)絡(luò)經(jīng)常使用奇數(shù)高寬的卷積核熏矿,如1、3离钝、5和7票编,所以兩端上的填充個(gè)數(shù)相等。對(duì)任意的二維數(shù)組
X
卵渴,設(shè)它的第i
行第j
列的元素為X[i,j]
慧域。當(dāng)兩端上的填充個(gè)數(shù)相等,并使輸入和輸出具有相同的高和寬時(shí)浪读,我們就知道輸出Y[i,j]
是由輸入以X[i,j]
為中心的窗口同卷積核進(jìn)行互相關(guān)計(jì)算得到的昔榴。
下面的例子里我們創(chuàng)建一個(gè)高和寬為3的二維卷積層,然后設(shè)輸入高和寬兩側(cè)的填充數(shù)分別為1瑟啃。給定一個(gè)高和寬為8的輸入论泛,我們發(fā)現(xiàn)輸出的高和寬也是8揩尸。
import torch
from torch import nn
# 定義一個(gè)函數(shù)來(lái)計(jì)算卷積層蛹屿。它對(duì)輸入和輸出做相應(yīng)的升維和降維
def comp_conv2d(conv2d, X):
# (1, 1)代表批量大小和通道數(shù)(“多輸入通道和多輸出通道”一節(jié)將介紹)均為1
X = X.view((1, 1) + X.shape)
Y = conv2d(X)
return Y.view(Y.shape[2:]) # 排除不關(guān)心的前兩維:批量和通道
# 注意這里是兩側(cè)分別填充1行或列,所以在兩側(cè)一共填充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])
當(dāng)卷積核的高和寬不同時(shí)岩榆,我們也可以通過(guò)設(shè)置高和寬上不同的填充數(shù)使輸出和輸入具有相同的高和寬错负。
# 使用高為5、寬為3的卷積核勇边。在高和寬兩側(cè)的填充數(shù)分別為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 步幅
在上一節(jié)里我們介紹了二維互相關(guān)運(yùn)算犹撒。卷積窗口從輸入數(shù)組的最左上方開(kāi)始,按從左往右粒褒、從上往下的順序识颊,依次在輸入數(shù)組上滑動(dòng)。我們將每次滑動(dòng)的行數(shù)和列數(shù)稱為步幅(stride)奕坟。
目前我們看到的例子里祥款,在高和寬兩個(gè)方向上步幅均為1。我們也可以使用更大步幅月杉。圖5.3展示了在高上步幅為3刃跛、在寬上步幅為2的二維互相關(guān)運(yùn)算】廖可以看到桨昙,輸出第一列第二個(gè)元素時(shí)检号,卷積窗口向下滑動(dòng)了3行,而在輸出第一行第二個(gè)元素時(shí)卷積窗口向右滑動(dòng)了2列蛙酪。當(dāng)卷積窗口在輸入上再向右滑動(dòng)2列時(shí)齐苛,由于輸入元素?zé)o法填滿窗口,無(wú)結(jié)果輸出滤否。圖5.3中的陰影部分為輸出元素及其計(jì)算所使用的輸入和核數(shù)組元素:
0×0+0×1+1×2+2×3=8
0×0+6×1+0×2+0×3=6
0×0+6×1+0×2+0×3=6
下面我們令高和寬上的步幅均為2脸狸,從而使輸入的高和寬減半。
conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1, stride=2)
comp_conv2d(conv2d, X).shape
輸出:
torch.Size([4, 4])
接下來(lái)是一個(gè)稍微復(fù)雜點(diǎn)兒的例子藐俺。
conv2d = nn.Conv2d(1, 1, kernel_size=(3, 5), padding=(0, 1), stride=(3, 4))
comp_conv2d(conv2d, X).shape
輸出:
torch.Size([2, 2])
小結(jié)
- 填充可以增加輸出的高和寬炊甲。這常用來(lái)使輸出與輸入具有相同的高和寬。
- 步幅可以減小輸出的高和寬欲芹,例如輸出的高和寬僅為輸入的高和寬的1/n(n為大于1的整數(shù))
注:除代碼外本節(jié)與原書(shū)此節(jié)基本相同卿啡,原書(shū)傳送門(mén)