一文搞懂 deconvolution、transposed convolution、sub-pixel or fractional convolution
- 2019 年 10 月 3 日
- 筆記
目錄
部落格:blog.shinelee.me | 部落格園 | CSDN
寫在前面
開篇先上圖,圖為deconvolution在像素級語義分割中的一種應用,直觀感覺deconvolution是一個upsampling的過程,像是convolution的對稱過程。
本文將深入deconvolution的細節,並通過如下方式展開:
- 先回答 什麼是deconvolution?為什麼會有transposed convolutionon、subpixel or fractional convolution這樣的名字?
- 再介紹 各種情形下 transposed convolution是如何進行的,並提供一種統一的計算方法。
什麼是deconvolution
首先要明確的是,deconvolution並不是個好名字,因為它存在歧義:
- deconvolution最初被定義為「inverse of convolution」或者「inverse filter」或者「解卷積」,是指消除先前濾波作用的方法。比如,我們認為原始影像是清晰的,但是通過透鏡觀測到的影像卻變得模糊,如果假設透鏡的作用相當於以某個kernel作用在原始影像上,由此導致影像變得模糊,那麼根據模糊的影像估計這個kernel或者根據模糊影像恢復原始清晰影像的過程就叫deconvolution。
- 後來論文Adaptive Deconvolutional Networks for Mid and High Level Feature Learning和Visualizing and Understanding Convolutional Networks又重新定義了deconvolution,實際上與transposed convolution、sub-pixel or fractional convolution指代相同。transposed convolution是一個更好的名字,sub-pixel or fractional convolution可以看成是transposed convolution的一個特例。對一個常規的卷積層而言,前向傳播時是convolution,將input feature map映射為output feature map,反向傳播時則是transposed convolution,根據output feature map的梯度計算出input feature map的梯度,梯度圖的尺寸與feature map的尺寸相同。
本文談論的是deconvolution的第2個含義,後面統一使用transposed convolution這個名字。
什麼是transposed convolution?A guide to convolution arithmetic for deep learning中有這樣一段話:
看完好像仍不是很直觀,transposed convolution到底對應的是什麼操作?等到文章的後面,這個問題的答案會逐漸清晰起來。
下面先以1個例子來對比convolution過程和transposed convolution過程,採用與A guide to convolution arithmetic for deep learning相同的設置:
- 2-D transposed convolutions ((N=2))
- square inputs ((i_1=i_2=i))
- square kernel size ((k_1=k_2=k))
- same strides along both axes ((s_1=s_2=s))
- same zero padding along both axes ((p_1=p_2=p))
- square outputs ((o_1=o_2=o))
若令(i=4)、(s=1)、(p=0)、(k=3),輸出尺寸(o=2),則convolution過程是將(4times 4)的map映射為(2times 2)的map,而transposed convolution過程則是將(2times 2)的map映射為(4times 4)的map,兩者的kernel size均為3,如下圖所示:
可以看到,convolution過程zero padding的數量與超參數(p)一致,但是transposed convolution實際的zero padding的數量為2,為什麼會這樣?是為了保持連接方式相同,下面具體看一下。
convolution過程
先看convolution過程,連接方式 如下圖所示,綠色表示輸出,藍色表示輸入,每個綠色塊具與9個藍色塊連接。
令卷積核(mathbf{w} = left(begin{array}{ccc} {w_{0,0}} & {w_{0,1}} & {w_{0,2}} \ {w_{1,0}} & {w_{1,2}} & {w_{1,2}} \ {w_{2,0}} & {w_{2,1}} & {w_{2,2}} end{array}right)),為了便於理解,將卷積寫成矩陣乘法形式,令(mathbf{x})為(4times 4)輸入矩陣以行優先方式拉成的長度為16的向量,(mathbf{y})為(2times 2)輸出矩陣以同樣方式拉成的長度為4的向量,同時將(mathbf{w})表示成(4times 16)的稀疏矩陣(mathbf{C}),
[ left(begin{array}{cccccccccccccccc}{w_{0,0}} & {w_{0,1}} & {w_{0,2}} & {0} & {w_{1,0}} & {w_{1,1}} & {w_{1,2}} & {0} & {w_{2,0}} & {w_{2,1}} & {w_{2,2}} & {0} & {0} & {0} & {0} & {0} \ {0} & {w_{0,0}} & {w_{0,1}} & {w_{0,2}} & {0} & {w_{1,0}} & {w_{1,1}} & {w_{1,2}} & {0} & {w_{2,0}} & {w_{2,1}} & {w_{2,2}} & {0} & {0} & {0} & {0} \ {0} & {0} & {0} & {0} & {w_{0,0}} & {w_{0,1}} & {w_{0,2}} & {0} & {w_{1,0}} & {w_{1,1}} & {w_{1,2}} & {0} & {w_{2,0}} & {w_{2,1}} & {w_{2,2}} & {0} \ {0} & {0} & {0} & {0} & {0} & {w_{0,0}} & {w_{0,1}} & {w_{0,2}} & {0} & {w_{1,0}} & {w_{1,1}} & {w_{1,2}} & {0} & {w_{2,0}} & {w_{2,1}} & {w_{2,2}}end{array}right) ]
則convolution過程可以描述為(mathbf{C} mathbf{x} = mathbf{y}),若(mathbf{C}_{i,j}=0)表示(mathbf{x}_j)和(mathbf{y}_i)間沒有連接。
transposed convolution過程
再看transposed convolution過程,如何將長度為4的向量(mathbf{y})映射為長度為16的向量且保持連接方式相同?只需將(mathbf{C})轉置,令(mathbf{C}^T mathbf{y} = mathbf{x}'),同樣地,(mathbf{C}^T_{j,i}=0)表示(mathbf{x}'_j)和(mathbf{y}_i)間沒有連接。
此時,(mathbf{C}^T)對應的卷積操作恰好相當於將kernel中心對稱,FULL zero padding,然後卷積,此時,1個藍色塊與9個綠色塊連接,且權重與Convolution過程相同
需要注意的是,transposed convolution的kernel與convolution的kernel可以有關,也可以無關,需要看應用在什麼場景,
- 在特徵可視化、訓練階段的反向傳播中應用的transposed convolution,並不是作為一個真正的layer存在於網路中,其kernel與convolution共享(但要經過中心對稱後再卷積,相當於上面的 $ mathbf{C} ^T $)。
- 在影像分割、生成模型、decoder中使用的transposed convolution,是網路中真實的layer,其kernel經初始化後需要通過學習獲得(所以卷積核也就無所謂中心對稱不對稱了)。
- 前向傳播為convolution/transposed convolution,則反向傳播為transposed convolution/convolution。
在上面舉的簡化的例子中,我們可以通過分析得知transposed convolution該如何進行,但是,對於更一般情況應該怎麼做?
transposed convolution的計算
對於一般情況,只需把握一個宗旨:transposed convolution將output size恢復為input size且保持連接方式相同。
對於convolution過程,我們知道其output map與input map的尺寸關係如下:
[o=leftlfloor frac{i+2p-k}{s} rightrfloor + 1]
若要將(o)恢復為(i),需考慮2種情況,(frac{i+2p-k}{s})整除以及不整除,先看整除的情況。
整除的情況
如果(frac{i+2p-k}{s})可以整除,則由上式可得
[i = so-s+k-2p = [o+(s-1)(o-1)]+(k-2p-1)]
因為transposed convolution也是卷積,為了符合上面卷積操作尺寸關係的數學形式,可進一步整理成
[i = frac{[o+(s-1)(o-1)] + [(k-1)+(k-2p-1)] – k}{1} + 1]
令(i'=o+(s-1)(o-1))、$p’=frac{(k-1)+(k-2p-1)}{2} = k-p-1 (、)s’=1(、)k’=k$,即transposed convolution實際卷積時使用的超參數,可以這樣理解:
-
(i'=o+(s-1)(o-1)):convolution的輸出為(otimes o),每行每列都是(o)個元素,有(o-1)個間隔,transposed convolution時在每個間隔處插入(s-1)個0,整體構成transposed convolution的input map;
-
$p’=frac{(k-1)+(k-2p-1)}{2} = k-p-1 $:在上一步input map的基礎上再進行padding,考慮convolution常用的幾種padding情況:
- VALID:(p=0),transposed convolution則需padding (p'=k-1),即FULL padding
- SAME:(p=frac{k-1}{2}=r),這裡考慮(k=2r+1)為奇數的一般情況,此時(p'=r),即SAME padding
- FULL:(p=k-1),則(p'=0),即VALID padding
可見,convolution和transposed convolution的padding也具有某種對稱性(p'+p=k-1);
-
(k'=k):transposed convolution的kernel size與convolution相同;
- (s'=1):transposed convolution的stride均為1,但也可以換個角度理解,如果認為(otimes o)相鄰元素間的距離為1個像素,那麼在間隔處插入(s-1)個0後((s > 1)),得到的input map相鄰元素間的距離就是亞像素的(sub-pixel),所以此時也可以稱之為 sub-pixel or fractional convolution;
-
(o'=i=frac{i'+2p'-k'}{s'}+1):transposed convolution的輸出與convolution的輸入具有相同尺寸。
不整除的情況
接下來再看(frac{i+2p-k}{s})不整除的情況,此時再按上面的方式計算得到的(o'=frac{i'+2p'-k'}{s'}+1)將小於(i),小多少呢?不難得出少(a = [(i+2p-k) mod s]),即
[o'=frac{i'+2p'-k'}{s'}+1=i-a]
為了讓(o'=i),可寫成
[o'= frac{i'+2p'+a-k'}{s'}+1]
只需在padding後,在下邊和右邊再擴展(a)行和列0,然後進行卷積即可。注意,因為(s'=1),我們可以將(a)放在分母也可以放在外面,之所以放在分母,是因為convolution過程中input map下邊和右邊的(a)行或列中的元素可能參與了運算,即與output map間存在連接,所以在transposed convolution時,為了保持同樣的連接,最後擴展的(a)行和列也要參與卷積,所以放在分母。
至此,再看transposed convolution的各種情況,就很容易推算了,更多例子可參見A guide to convolution arithmetic for deep learning。
總結
最後,總結一下,
- convolution和transposed convolution互為對稱過程,存在一個convolution,就存在一個與之對應的transposed convolution,反之亦然;
- convolution是將input size的map映射為output size的map,transposed convolution是將output size的map映射為input size的map——旨在將尺寸恢復;
- 兩者均使用卷積操作,為了方便,兩者使用同樣的stride、padding、kernel size超參數,但實際執行時的操作不同,一般情況下,transposed convolution與convolution實際超參數關係為:(i'=o+(s-1)(o-1))、$p’=frac{(k-1)+(k-2p-1)}{2} = k-p-1 (、)s’=1(、)k’=k$。
- 之所以做這樣的操作,是為了保證map間的連接方式相同(權重不一定相同),權重的設置需根據應用的場景,可能通過學習得到,也可能與convolution共享(但需要中心對稱後再使用)。
參考
- vdumoulin/conv_arithmetic
- A guide to convolution arithmetic for deep learning
- winter1516_lecture13.pdf
- Is the deconvolution layer the same as a convolutional layer?
- What are deconvolutional layers?