1.首先先定義進行卷積的參數:html
- 輸入特徵圖爲高寬同樣的Hin*Hin大小的x
- 卷積核大小kernel_size
- 步長stride
- padding填充數(填充0)
- 輸出特徵圖爲Hout*Hout大小的y
計算式子爲:git
Hout = floor( Hin + 2*padding - kernel_size / stride) + 1github
2.而後實現上面的卷積的轉置卷積c#
定義其參數爲:ide
- 輸入特徵圖爲高寬同樣的Hout*Hout大小的y
- 卷積核大小kernel_size
- 步長stride
- paddingnew 填充數(填充0)
- 輸出特徵圖爲Hin*Hin大小的x
逆卷積的過程主要分兩步:ui
- 對輸入的特徵圖y進行變換,獲得新的特徵圖ynew
- 內部變換,與卷積時設置的stride相關
- 外部變換,與卷積時設置的padding相關
- 根據獲得的特徵圖進行卷積便可
1)對輸入的特徵圖y進行變換,獲得新的特徵圖ynewurl
1》內部變換spa
當卷積時設置的stride>1時,將對輸入的特徵圖y進行插值操做(interpolation)。.net
即須要在輸入的特徵圖y的每一個相鄰值之間插入(stride-1)行和列0,由於特徵圖中可以插入的相鄰位置有(height-1)個位置,因此此時獲得的特徵圖的大小由Hout*Hout(Hout即height) 變爲新的 Hout_new*Hout_new,即[Hout + (stride-1) * (Hout-1)] * [Hout + (stride-1) * (Hout-1)]htm
2》外部變換
爲了實現由Hout*Hout大小的y逆卷積獲得Hin*Hin大小的x,還須要設置paddingnew的值爲(kernel_size - padding - 1),這裏的padding是卷積操做時設置的padding值
因此計算式子變爲:
Hin = floor( [Hout_new + 2*paddingnew - kernel_size] / stride') + 1
⚠️該式子變換後,定義向下取整的分母stride'值爲定值1
Hout_new和paddingnew的值代入上面的式子,即變爲:
Hin = floor( Hout + (stride-1) * (Hout-1) + 2*(kernel_size - padding - 1) - kernel_size) + 1
化簡爲:
Hin = floor( (Hout - 1) * stride - 2*padding + kernel_size - 1) + 1
= (Hout - 1) * stride - 2*padding + kernel_size
這樣式子使的卷積Conv2d和逆卷積ConvTranspose2d在初始化時具備相同的參數,而在輸入和輸出形狀方面互爲倒數。
因此這個式子其實就是官網給出的式子:
可見這裏沒考慮output_padding
output_padding的做用:可見nn.ConvTranspose2d的參數output_padding的做用
3.下面舉例說明
https://github.com/vdumoulin/conv_arithmetic#convolution-arithmetic
1)當stride=1時,就不會進行插值操做,只會進行padding,舉例說明:
卷積操做爲:
藍色爲輸入特徵圖Hin*Hin=4*4,綠色爲輸出特徵圖Hout*Hout=2*2,卷積核kernel_size=3, stride=1
根據式子Hout = floor( Hin + 2*padding - kernel_size / stride) + 1
可得padding=0
其對應的逆卷積操做爲:
藍色爲輸入特徵圖Hout*Hout=2*2,綠色爲輸出特徵圖Hin*Hin=4*4,卷積核kernel_size=3, stride=1
卷積時的padding=0
將這些值代入上面的式子Hin = (Hout - 1) * stride - 2*padding + kernel_size
果真輸入Hout*Hout=2*2能獲得輸出Hin*Hin=4*4
變形過程爲:
paddingnew = kernel_size - padding -1 = 3 -0 -1 = 2
因此可見下方的藍色最後的大小爲7*7 = Hout + 2*paddingnew = 2 + 2*2 = 6
⚠️這裏可見是有padding的,爲何定義是爲no padding呢?
這是由於它對應的卷積操做的padding=0
1)當stride=2時,進行插值和padding操做,舉例說明:
卷積操做爲:
藍色爲輸入特徵圖Hin*Hin=5*5,綠色爲輸出特徵圖Hout*Hout=3*3,卷積核kernel_size=3, stride=2
根據式子Hout = floor( Hin + 2*padding - kernel_size / stride) + 1
可得padding=1
其對應的逆卷積操做爲:
藍色爲輸入特徵圖Hout*Hout=3*3,綠色爲輸出特徵圖Hin*Hin=5*5,卷積核kernel_size=3,stride=2
卷積時的padding=1
將這些值代入上面的式子Hin = (Hout - 1) * stride - 2*padding + kernel_size
果真輸入Hout*Hout=3*3能獲得輸出Hin*Hin=5*5
變形操做爲:
Hout_new = Hout + (stride-1) * (Hout-1) = 3 + (2-1)*(3-1) = 5
paddingnew = kernel_size - padding -1 = 3 -1 -1 = 1
因此可見下方的藍色最後的大小爲7*7 = Hout_new + 2*paddingnew = 5 + 2*1 = 7
⚠️由於這裏的逆卷積對應的卷積操做的padding= 1,因此這裏不是no padding,而是padding