關於轉置卷積(反捲積)的理解

轉自 https://blog.csdn.net/isMarvellous/article/details/80087705ide

什麼是轉置卷積(反捲積)?
轉置卷積(Transposed Convolution)又稱爲反捲積(Deconvolution)。在PyTorch中可使用torch.nn.ConvTranspose2d()來調用,在Caffe中也有對應的層deconv_layer。.net

轉置卷積經常用於CNN中對特徵圖進行上採樣,好比語義分割和超分辨率任務中。之因此叫轉置卷積是由於,它實際上是把咱們平時所用普通卷積操做中的卷積核作一個轉置,而後把普通卷積的輸出做爲轉置卷積的輸入,而轉置卷積的輸出,就是普通卷積的輸入。這樣說可能有點繞,咱們能夠參照CNN中的反向傳播過程來理解,轉置卷積形式上就和一個卷積層的反向梯度計算相同。既然是輸入輸出對調,那麼就有兩個很重要的特性:blog

轉置的卷積核變爲了普通卷積核的轉置;
若是把由輸入特徵圖到輸出特徵圖的計算過程畫成一個計算圖,那麼輸入輸出元素的鏈接關係是不變的
關於第二點,也就是說,在普通卷積中,若元素a和元素1有鏈接(元素1由a計算獲得),那麼在相應的轉置卷積中,元素1和元素a依然是有鏈接的(元素a由元素1計算獲得)。token

下面就基於此討論一下我對轉置卷積計算過程的一個理解。這並非一個嚴格的推導,只是爲了形象地幫助理解爲何要這樣計算,或者說這個計算過程是怎麼來的。而後再總結一下轉置卷積輸出特徵圖大小的計算。因爲是本身的我的看法,不免有疏漏或理解不許確的地方,這裏總結出來,但願你們一塊兒來討論。get

普通卷積的計算過程
以下圖:
io

 

 

這是一個卷積核大小爲3x3,步長爲2,padding爲1的普通卷積。卷積核在紅框位置時輸出元素1,在綠色位置時輸出元素2。咱們能夠發現,輸入元素a僅和一個輸出元素有運算關係,也就是元素1,而輸入元素b和輸出元素1, 2均有關係。同理c只和一個元素2有關,而d和1,2,3,4四個元素都有關。那麼在進行轉置卷積時,依然應該保持這個鏈接關係不變。sed

轉置卷積(反捲積)的計算過程
根據前面的分析,咱們須要將上圖中綠色的特徵圖做爲輸入,藍色的特徵圖做爲輸出,而且保證鏈接關係不變。也就是說,a只和1有關,b和1,2兩個元素有關,其它類推。怎麼才能達到這個效果呢?咱們能夠先用0給綠色特徵圖作插值,插值的個數就是使相鄰兩個綠色元素的間隔爲卷積的步長,同時邊緣也須要進行與插值數量相等的補0。以下圖:
im

 

 

注意,這時候卷積核的滑動步長就不是2了,而是1,步長體如今了插值補0的過程當中。總結

通常在CNN中,轉置卷積用於對特徵圖進行上採樣,好比咱們想要將特徵圖擴大2倍,那麼就可使用步長爲2的轉置卷積。可是且慢!爲何咱們這裏2x2的輸入,只獲得了3x3的輸出呢?說好的擴大2倍呢?不該該是4x4麼?
別急,咱們來算一算爲何是3x3。
咱們將2x2的特徵圖插空並在邊緣補0後,邊長變成了2x2+1=5,使用3x3的卷積核作滑動步長爲1的卷積,獲得的特徵圖邊長爲(5-3+1)/1=3。因此咱們只獲得了3x3而非4x4的輸出。那麼在通常狀況下,輸出特徵圖的大小要怎麼計算呢?下面咱們來總結一下。img

輸出特徵圖的尺寸計算假設咱們作轉置卷積的輸入特徵圖大小爲 n×nn×n,卷積核大小爲 k×kk×k,後面爲了表示方便,咱們直接使用邊長來表示大小。步長stride爲ss,那麼轉置卷積須要在四周每一個邊緣補0的數量爲s−1s−1,邊緣和內部插空補0後輸入特徵圖大小變爲s×n+s−1s×n+s−1;使用大小爲kk的卷積核進行卷積(滑動步長爲1),獲得的輸出特徵圖大小爲:(s×n+s−1−k+1)/1=s×n+(s−k)(s×n+s−1−k+1)/1=s×n+(s−k)。能夠看到,轉置卷積並非嚴格將輸入特徵圖變爲了s倍,而是還相差了個s−ks−k。這和PyTorch中的torch.nn.ConvTranspose2d()獲得的結果是一致的。

相關文章
相關標籤/搜索