關於torch.nn.Conv2d的筆記


先看一下CLASS有哪些參數:

torch.nn.Conv2d(
    in_channels,
    out_channels,
    kernel_size,
    stride=1,
    padding=0,
    dilation=1,
    groups=1,
    bias=True,
    padding_mode='zeros'
)

可以對輸入的張量進行 2D 卷積。

 

in_channels: 輸入圖片的 channel 數。

out_channels: 輸出圖片的 channel 數。

kernel_size: 卷積核的大小。

stride: 滑動的步長。

bias: 若設為 True,則對輸出圖像每個元素加上一個可以學習的 bias。 

dilation: 核間點距。

padding: 控制補 $0$ 的數目。padding 是在卷積之前補 $0$,如果願意的話,可以通過使用 torch.nn.Functional.pad 來補非 $0$ 的內容。padding 補 $0$ 的策略是四周都補,如果 padding 輸入是一個二元組的話,則第一個參數表示高度上面的 padding,第2個參數表示寬度上面的 padding。

 

關於 padding 策略的例子:

x = torch.tensor([[[[-1.0, 2.0], [3.5, -4.0]]]])
print(x, x.shape)  # N = 1, C = 1, (H,W) = (2,2)
layer1 = torch.nn.Conv2d(1, 1, kernel_size=(1, 1), padding=0)
layer2 = torch.nn.Conv2d(1, 1, kernel_size=(1, 1), padding=(1, 2))
y = layer1(x)
print(y, y.shape)
z = layer2(x)
print(z, z.shape)

結果:

tensor([[[[-1.0000,  2.0000],
          [ 3.5000, -4.0000]]]]) torch.Size([1, 1, 2, 2])
tensor([[[[-0.3515,  0.4479],
          [ 0.8476, -1.1510]]]], grad_fn=<ThnnConv2DBackward>) torch.Size([1, 1, 2, 2])
tensor([[[[-0.6553, -0.6553, -0.6553, -0.6553, -0.6553, -0.6553],
          [-0.6553, -0.6553,  0.2367, -2.4393, -0.6553, -0.6553],
          [-0.6553, -0.6553, -3.7772,  2.9127, -0.6553, -0.6553],
          [-0.6553, -0.6553, -0.6553, -0.6553, -0.6553, -0.6553]]]],
       grad_fn=<ThnnConv2DBackward>) torch.Size([1, 1, 4, 6])

可以看到 padding 為 $(1,2)$ 時,在高度上兩邊各增加了 $1$ 行,總共增加 $2$ 行。在寬度上兩邊各增加 $2$ 列,總共增加 $4$ 列。至於為什么增加的行列不是 $0$,這是因為有參數 bias 存在的緣故,此時 bias 值為 $-0.6553$(這個 bias 值初始值應該是一個隨機數)。

 

關於 dilation:

默認情況下 dilation 為 $(1,1)$,就是正常的緊密排布的卷積核。

下圖是 dilation 為 $(2,2)$ 的情況(沒有 padding,stride 為 $(1,1)$),藍色的是輸入圖像,綠色的是輸出圖像。

 

 

輸入圖像的 shape 是 $(N, C_{in}, H_{in}, W_{in})$,$N$ 是 batch size,$C_{in}$ 表示 channel 數,$H,W$ 分別表示高和寬。

輸出圖像的 shape $(N, C_{out}, H_{out}, W_{out})$ 可以通過計算得到:

這個式子很好理解,由於寬高的計算類似,所以只以高為例子來講:

$H_{in} + 2 \times \rm{padding}[0]$ 即輸入圖像補完 $0$ 之后的高度,一個卷積核在圖像上所能覆蓋的高度為 $(\rm{kernel\_size}[0] - 1) \times \rm{dilation}[0] + 1$(例如上面動圖就是 $(3 - 1) \times 2 + 1 = 5$),這兩個值相減即為,步長為 $1$ 時,卷積核在圖像高度上能滑動的次數。而這個次數除去實際步長 $stride[0]$ 再向下取整,即卷積核在圖像高度上實際能滑動的次數。這個實際滑動次數加上 $1$ 即輸出圖像的高度。

 

需要注意的是:kernel_size, stride, padding, dilation 不但可以是一個單個的 int ——表示在高度和寬度使用同一個 int 作為參數,也可以使用一個 (int1, int2) 的二元組(其實本質上單個的 int 也可以看作一個二元組 (int, int))。在元組中,第1個參數對應高度維度,第2個參數對應寬度維度。

 

另外,對於卷積核,它其實並不是二維的,它具有長寬深三個維度;實際上它的 channel 數等於輸入圖像的 channel 數 $C_{in}$,而卷積核的個數即輸出圖像的 channel 數 $C_{out}$。

以上圖為例,輸入圖像的 shape 是 $(C = 3, H = 6, W = 6)$,這里略去 batch size,第一個卷積核是 $(C = 3, H = 3, W = 3)$,他在輸入圖像上滑動並卷積后得到一張 $(C = 1, H = 4, W = 4)$ 的特征圖(feature map),第二個卷積核類似得到第二張 $(C = 1, H = 4, W = 4)$ 特征圖,那么輸出圖像就是把這兩張特征圖疊在一塊兒,shape 即為 $(C = 2, H = 4, W = 4)$。

 

 


 

這里順帶記錄一下 Batch norm 2D 是怎么做的:

如果把一個 shape 為 $(N, C, H, W)$ 類比為一摞書,這摞書總共有 N 本,每本均有 C 頁,每頁有 H 行,每行 W 個字符。BN 求均值時,相當於把這 $N$ 本書都選同一個頁碼加起來(例如第1本書的第36頁,第2本書的第36頁......),再除以每本書的該頁上的字符的總數 $N \times H \times W$,因此可以把 BN 看成求“平均書”的操作(注意這個“平均書”每頁只有一個字),求標准差時也是同理。

例如下圖,輸入的張量 shape 為 $(4, 3, 2, 2)$,對於所有 batch 中的同一個 channel 的元素進行求均值與方差,比如對於所有的 batch,都拿出來最后一個channel,一共有 $f_1 + f_2 + f_3 + f_4 = 4 + 4 + 4 + 4 = 16$ 個元素,然后去求這 $16$ 個元素的均值與方差。

 

求取完了均值與方差之后,對於這 $16$ 個元素中的每個元素分別進行歸一化,然后乘以 $\gamma$ 加上 $\beta$,公式如下

batch norm層能夠學習到的參數,對於一個特定的 channel 而言實際上是兩個參數 $\gamma, beta$,而對於所有的channel而言實際上就是 channel 數的兩倍。

關於其他的 Normalization 做法的形象理解可以參考https://zhuanlan.zhihu.com/p/69659844

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM