1.首先先定義進行卷積的參數:
- 輸入特征圖為高寬一樣的Hin*Hin大小的x
- 卷積核大小kernel_size
- 步長stride
- padding填充數(填充0)
- 輸出特征圖為Hout*Hout大小的y
計算式子為:
Hout = floor( Hin + 2*padding - kernel_size / stride) + 1
2.然后實現上面的卷積的轉置卷積
定義其參數為:
- 輸入特征圖為高寬一樣的Hout*Hout大小的y
- 卷積核大小kernel_size
- 步長stride
- paddingnew 填充數(填充0)
- 輸出特征圖為Hin*Hin大小的x
逆卷積的過程主要分兩步:
- 對輸入的特征圖y進行變換,得到新的特征圖ynew
- 內部變換,與卷積時設置的stride相關
- 外部變換,與卷積時設置的padding相關
- 根據得到的特征圖進行卷積即可
1)對輸入的特征圖y進行變換,得到新的特征圖ynew
1》內部變換
當卷積時設置的stride>1時,將對輸入的特征圖y進行插值操作(interpolation)。
即需要在輸入的特征圖y的每個相鄰值之間插入(stride-1)行和列0,因為特征圖中能夠插入的相鄰位置有(height-1)個位置,所以此時得到的特征圖的大小由Hout*Hout(Hout即height) 變為新的 Hout_new*Hout_new,即[Hout + (stride-1) * (Hout-1)] * [Hout + (stride-1) * (Hout-1)]
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