轉載:https://zhuanlan.zhihu.com/p/124626648
轉載:https://www.cnblogs.com/wanghui-garcia/p/10791328.html
1. 卷積 Convolution
1.1 卷積輸出尺寸
輸出圖像尺寸可以根據以下公式獲得
:輸入圖像尺寸
: padding 大小
: 卷積核大小
: 步長

卷積:藍色的輸入圖片(4 x4),深藍色代表卷積核(3 x 3),綠色為輸出圖像(2 x 2)
假如現在有一個4 x 4的圖片, 使用一個3 x 3的kernel 進行卷積
圖片: 卷積核:
strides = 1 , padding = 0, 卷積后,輸出圖像的尺寸為
如果卷積核很大,那么可以使用傅里葉變換, 提升卷積的性能。
2. 反卷積 Transposed Convolution
由於卷積核一般比原始圖像小,所以卷積之后的圖像尺寸往往會變小。有時候我們需要將卷積后的圖像還原成原始圖像的尺寸,即實現圖像從小分辨率到大分辨率的映射,這種操作就叫做上采樣(Upsampling)。而反卷積正是一種上采樣方法。
反卷積,又稱為轉置卷積(Transposed Convolution,),它是一種特殊的卷積,先padding來擴大圖像尺寸,緊接着跟正向卷積一樣,旋轉卷積核180度,再進行卷積計算。看上去就像,已知正向卷積的輸出圖像,卷積核,得到正向卷積中的原始圖像(並非真的得到原始圖像,像素點是不一樣的,但是尺寸是一致的)。
它看上去像是正向卷積的逆運算,但其實並不是。因為反卷積只能還原原始圖像的尺寸,但是並不能真的恢復原始圖像內容,即每個元素值其實是不一樣的。
卷積過程中:
表示輸出,
表示輸入,
:表示kernel的大小,
:表示padding,
: 表達strides
反卷積過程中:
表示輸出,
表示輸入,
:表示kernel的大小,
:表示padding,
: 表達strides
卷積后的 則反卷積的
, 一般卷積核是不會變的,
,需要注意的是,卷積與反卷積的padding很可能是不一樣。
2.1 Striding
反卷積的Striding跟卷積有點不一樣,它在輸入的每個元素之間插入 個值為0的元素
Transposed convolution : Striding
如果我們將反卷積看成是一種特殊的卷積,它其實是根據反卷積中指定的步長strides, 修改了輸入 , 根據strding 進行補0操作,得到
, 其大小變為
, 然后對
進行s=1的卷積。例如,對應上面的三個子圖,
對應的
,
對應的
,
對應的
。

反卷積:藍色是輸入(3 x 3), 灰色是卷積核(3 x 3), 綠色是輸出(5 x 5),padding=1,strides = 2

反卷積:藍色是輸入(5 x 5), 灰色是卷積核(3 x 3), 綠色是輸出(5 x 5),padding=1,strides =1
3 反卷積的輸出尺寸
可見這里沒考慮output_padding
output_padding的作用:可見nn.ConvTranspose2d的參數output_padding的作用.
論文 A guide to convolution arithmetic for deep learning 涉及了14種有關反卷積的尺寸大小公式的關系,但是歸納起來就只有兩種情況。
3.1
反卷積的輸出尺寸為 或者
對應上面提到的卷積的例子,分別用上面兩條公式進行驗算,驗算結果都成立。
卷積時, ,
,
,
, 所以計算的結果
反卷積, ,
,
,
,
代入第一個式子
代入第二個式子

反卷積,藍色是輸入(2 x 2), 灰色是卷積核(3 x 3), 綠色是輸出(4 x 4),padding=2
4.下面舉例說明
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