深度学习之卷积神经网络(11)卷积层变种
深度學(xué)習(xí)之卷積神經(jīng)網(wǎng)絡(luò)(11)卷積層變種
- 1. 空洞卷積
- 2. 轉(zhuǎn)置卷積
- 矩陣角度
- 轉(zhuǎn)置卷積實(shí)現(xiàn)
- 3. 分離卷積
卷積神經(jīng)網(wǎng)絡(luò)的研究產(chǎn)生了各種各樣優(yōu)秀的網(wǎng)絡(luò)模型,還提出了各種卷積層的變種,本節(jié)將重點(diǎn)介紹書中典型的卷積層變種。
1. 空洞卷積
?普通的卷積層為了減少為了的參數(shù)量,卷積核的設(shè)計(jì)通常選擇較小的1×11×11×1和3×33×33×3感受野大小。小卷積核使得網(wǎng)絡(luò)提取特征時(shí)的感受野區(qū)域有限,但是增大感受野區(qū)域又會(huì)增加網(wǎng)絡(luò)的參數(shù)量和計(jì)算代價(jià),因此需要權(quán)衡設(shè)計(jì)。
?空洞卷積(Dilated/Atrous Convolution)的提出較好地解決了這個(gè)問(wèn)題,空洞卷積在普通卷積的感受野上增加一個(gè)Dilation Rate參數(shù),用于控制感受野區(qū)域的采樣步長(zhǎng),如下圖所示:
當(dāng)感受野的采樣步長(zhǎng)Dilation Rate為1時(shí),每個(gè)感受野采樣點(diǎn)之間的距離為1,此時(shí)的空洞卷積退化為普通的卷積; 當(dāng)Dilation Rate為2時(shí),感受野每2個(gè)單元采樣一個(gè)點(diǎn),如上圖中間綠色方框中綠色格子所示,每個(gè)采樣格子之間的距離為2; 同樣的方法,最右邊圖的Dilation Rate為3,采樣步長(zhǎng)為3,盡管Dilation Rate的增大會(huì)使得感受野區(qū)域增大,但是實(shí)際參與運(yùn)算的點(diǎn)數(shù)仍然保持不變。
?以輸入為單通道的7×77×77×7張量,單個(gè)3×33×33×3卷積核為例,如下圖所示。在初始位置,感受野從最上、最右位置開始采樣,每隔一個(gè)點(diǎn)采樣一次,共采集9個(gè)數(shù)據(jù)點(diǎn),如下圖中綠色方框所示。這9個(gè)數(shù)據(jù)點(diǎn)與卷積核相乘運(yùn)算,寫入輸出張量的對(duì)應(yīng)位置。
?卷積核窗口按著步長(zhǎng)為s=1s=1s=1向右移動(dòng)一個(gè)單位,如下圖所示,同樣進(jìn)行個(gè)點(diǎn)采樣,共采樣9個(gè)數(shù)據(jù)點(diǎn),與卷積核完成相乘累加運(yùn)算,寫入輸出張量對(duì)應(yīng)為,直至卷積核移動(dòng)至最下方、最右邊位置。需要注意區(qū)分的是,卷積核窗口的移動(dòng)步長(zhǎng)s和感受野區(qū)域的采樣步長(zhǎng)Dilation Rate是不同的概念。
?空洞卷積在不增加網(wǎng)絡(luò)參數(shù)的條件下,提供了更大的感受野窗口。但是在使用空洞卷積設(shè)置網(wǎng)絡(luò)模型時(shí),需要精心設(shè)計(jì)Dilation Rate參數(shù)來(lái)避免出現(xiàn)網(wǎng)格效應(yīng),同樣較大的Dilation Rate參數(shù)并不利于小物體的檢測(cè)、語(yǔ)義分割等任務(wù)。
?在TensorFlow中,可以通過(guò)設(shè)置layers.Conv2D()類的dilation_rate參數(shù)來(lái)選擇使用普通卷積還是空洞卷積。例如:
運(yùn)行結(jié)果如下圖所示:

當(dāng)dilation_rate參數(shù)設(shè)置為默認(rèn)值1時(shí),使用普通卷積方式進(jìn)行計(jì)算; 當(dāng)dilation_rate參數(shù)大于1時(shí),采用空洞卷積方式進(jìn)行計(jì)算。
2. 轉(zhuǎn)置卷積
?轉(zhuǎn)置卷積(Transposed Convolution,或Fractionally Strided Convolution,部分資料也稱之為反卷積/Deconvolution,實(shí)際上反卷積在數(shù)學(xué)上定義為卷積的逆過(guò)程,單轉(zhuǎn)置卷積并不能恢復(fù)出原卷積的輸入,因此稱為反卷積并不妥當(dāng))通過(guò)在輸入之間填充大量的padding來(lái)實(shí)現(xiàn)輸出高寬大于輸入高寬的效果,從而實(shí)現(xiàn)向上采樣的目的,如下圖所示。我們先介紹轉(zhuǎn)置卷積的計(jì)算過(guò)程,再介紹轉(zhuǎn)置卷積與普通卷積的聯(lián)系。
?為了簡(jiǎn)化討論,我們此處只討論輸入h=wh=wh=w,即輸入高寬相等的情況。
o+2p?k\boldsymbol {o+2p-k}o+2p?k為s\boldsymbol ss倍數(shù)
?考慮輸入為2×22×22×2的單通道特征圖,轉(zhuǎn)置卷積核為3×33×33×3大小,步長(zhǎng)為s=2s=2s=2,填充p=0p=0p=0的例子。首先再輸入數(shù)據(jù)點(diǎn)之間均勻插入s?1s-1s?1個(gè)空白數(shù)據(jù)點(diǎn),得到3×33×33×3的矩陣,如下圖第2個(gè)矩陣所示,根據(jù)填充量3×33×33×3矩陣周圍填充相應(yīng)k?p?1=3?0?1=2k-p-1=3-0-1=2k?p?1=3?0?1=2行/列,此時(shí)輸入張量的高寬為7×77×77×7,如下圖中第3個(gè)矩陣所示。
?在7×77×77×7的輸入張量上,進(jìn)行3×33×33×3卷積核,步長(zhǎng)s′=1s'=1s′=1,填充p=0p=0p=0的普通卷積運(yùn)算(注意,此階段的普通卷積的步長(zhǎng)s′s's′始終為1,與轉(zhuǎn)置卷積的步長(zhǎng)sss不同),根據(jù)普通卷積的輸出計(jì)算公式,得到輸出大小為:
o=[i+2?p?ks′]+1=[7+2?0?31]+1=5o=[\frac{i+2*p-k}{s'} ]+1=[\frac{7+2*0-3}{1}]+1=5o=[s′i+2?p?k?]+1=[17+2?0?3?]+1=5
5×55×55×5大小的輸出。我們直接按照此計(jì)算流程給出最終轉(zhuǎn)置卷積輸出與輸入關(guān)系。在o+2p?ko+2p-ko+2p?k為sss倍數(shù)時(shí),滿足關(guān)系:
o=(i?1)s+k?2po=(i-1)s+k-2po=(i?1)s+k?2p
?轉(zhuǎn)置卷積并不是普通的逆過(guò)程,但是二者之間有一定的聯(lián)系,同時(shí)轉(zhuǎn)置卷積也是基于普通卷積實(shí)現(xiàn)的。在相同的設(shè)定下,輸入x\boldsymbol xx經(jīng)過(guò)普通卷積運(yùn)算得到o=Conv(x)\boldsymbol o=\text{Conv}(\boldsymbol x)o=Conv(x),我們將o送入轉(zhuǎn)置卷積運(yùn)算后,得到x′=ConvTranspose(o)\boldsymbol x'=\text{ConvTranspose}(\boldsymbol o)x′=ConvTranspose(o),其中x′≠x\boldsymbol x'≠\boldsymbol xx′?=x,但是x′\boldsymbol x'x′與x\boldsymbol xx形狀相同。我們可以用輸入為5×55×55×5,步長(zhǎng)s=2s=2s=2,填充p=0p=0p=0,3×33×33×3卷積核的普通卷積運(yùn)算進(jìn)行驗(yàn)證演示,如下圖所示:
?可以看到,將轉(zhuǎn)置卷積的輸出5×55×55×5在同設(shè)定條件下送入普通卷積,可以得到2×22×22×2的輸出,此大小恰好就是轉(zhuǎn)置卷積的輸入大小,同時(shí)我們也觀察到,輸出2×22×22×2矩陣并不是轉(zhuǎn)置卷積輸入的2×22×22×2矩陣。轉(zhuǎn)置卷積與普通卷積并不是互為逆過(guò)程,不能恢復(fù)出對(duì)方的輸入內(nèi)容,僅能恢復(fù)出等大小的張量。因此稱之為反卷積并不切貼。
&emspl;基于TensorFlow實(shí)現(xiàn)上述例子的轉(zhuǎn)置卷積運(yùn)算,代碼如下:
運(yùn)行結(jié)果如下圖所示:
?現(xiàn)在我們將普通卷積的輸出作為轉(zhuǎn)置卷積的輸入,驗(yàn)證轉(zhuǎn)置卷積的輸出是否為5×55×55×5,代碼如下:
運(yùn)行結(jié)果如下:
o+2p?k\boldsymbol{o+2p-k}o+2p?k不為s\boldsymbol ss倍數(shù)
?讓我們更加深入地分析卷積運(yùn)算中輸入與輸出大小關(guān)系的一個(gè)細(xì)節(jié)。考慮卷積運(yùn)算的輸出表達(dá)式:
o=[i+2?p?ks′]+1o=[\frac{i+2*p-k}{s'} ]+1o=[s′i+2?p?k?]+1
當(dāng)步長(zhǎng)s>1s>1s>1時(shí),[i+2?p?ks′][\frac{i+2*p-k}{s'} ][s′i+2?p?k?]向下取整運(yùn)算使得出現(xiàn)多種不同輸入尺寸iii對(duì)應(yīng)到相同的輸出尺寸ooo上。舉個(gè)例子,考慮輸入大小為6×66×66×6,卷積核大小為3×33×33×3,步長(zhǎng)為1的卷積運(yùn)算,代碼如下:
運(yùn)行結(jié)果如下圖所示:
此種情況也能獲得2×22×22×2大小的卷積輸出,與利用普通卷積可以獲得相同大小的輸出。因此,不同輸入大小的卷積運(yùn)算可能獲得相同大小的輸出。考慮到卷積與專制卷積輸入輸出大小關(guān)系互換,從轉(zhuǎn)置卷積的角度來(lái)說(shuō),輸入尺寸iii經(jīng)過(guò)轉(zhuǎn)置卷積運(yùn)算后,可能獲得不同的輸出ooo大小。因此通過(guò)填充aaa行、aaa列來(lái)實(shí)現(xiàn)不同大小的輸出ooo,從而恢復(fù)普通卷積不同大小的輸入的情況,其中aaa關(guān)系為:
a=(o+2p?k)a=(o+2p-k)%sa=(o+2p?k)
此時(shí)轉(zhuǎn)置卷積的輸出變?yōu)?
o=(i?1)s+k?2p+ao=(i-1)s+k-2p+ao=(i?1)s+k?2p+a
?在TensorFlow中間,不需要手動(dòng)指定aaa參數(shù),只需要指定輸出尺寸即可,TensorFlow會(huì)自動(dòng)推導(dǎo)需要填充的行列數(shù)aaa,前提是輸出尺寸合法。例如:
運(yùn)行結(jié)果如下所示:
通過(guò)改變參數(shù)output_shape=[1, 5, 5, 1]也可以獲得高寬為5×5的張量。
矩陣角度
?轉(zhuǎn)置卷積的轉(zhuǎn)置是指卷積核W\boldsymbol WW產(chǎn)生的稀疏矩陣W′\boldsymbol W'W′在計(jì)算過(guò)程中需要先轉(zhuǎn)置W′T\boldsymbol W'^TW′T,再進(jìn)行矩陣相乘運(yùn)算,而普通卷積并沒(méi)有轉(zhuǎn)置W′\boldsymbol W'W′的步驟。這也是它被稱為轉(zhuǎn)置卷積的名字的由來(lái)。
?考慮普通Conv2d運(yùn)算: X\boldsymbol XX和W\boldsymbol WW,需要根據(jù)strides將卷積核在行、列方向循環(huán)移動(dòng)獲取參與運(yùn)算的感受野的數(shù)據(jù),串行計(jì)算每個(gè)窗口的“相乘累加”值,計(jì)算效率極地。為了加速運(yùn)算,在數(shù)學(xué)上可以將卷積核W\boldsymbol WW根據(jù)strides重排成稀疏矩陣W′\boldsymbol W'W′,再通過(guò)W′@X′\boldsymbol W'@\boldsymbol X'W′@X′一次完成運(yùn)算(實(shí)際上,W′\boldsymbol W'W′矩陣過(guò)于稀疏,導(dǎo)致很多無(wú)用的0乘運(yùn)算,很多深度學(xué)習(xí)框架也不是通過(guò)這種方式實(shí)現(xiàn)的)。
?以4行4列的輸入X\boldsymbol XX,高寬為3×3,步長(zhǎng)為1,無(wú)padding的卷積核W\boldsymbol WW的卷積運(yùn)算為例,首先將X\boldsymbol XX打平成X′\boldsymbol X'X′,如下圖所示:
然后將卷積核W\boldsymbol WW轉(zhuǎn)換成稀疏矩陣W′\boldsymbol W'W′,如下圖所示:
?此時(shí)通過(guò)一次矩陣相乘即可實(shí)現(xiàn)普通卷積運(yùn)算:
O′=W′@X′\boldsymbol O'=\boldsymbol W'@\boldsymbol X'O′=W′@X′
如果給定O\boldsymbol OO,希望能夠生成與X\boldsymbol XX相同形狀大小的張量,怎么實(shí)現(xiàn)呢?將W′\boldsymbol W'W′轉(zhuǎn)置后與上圖方法重排后的O′\boldsymbol O'O′完成矩陣相乘即可:
X′=W′T@O′\boldsymbol X'=\boldsymbol W'^T@\boldsymbol O'X′=W′T@O′
得到的X′\boldsymbol X'X′通過(guò)reshape操作變?yōu)榕c原來(lái)的輸入X\boldsymbol XX尺寸一致,但是內(nèi)容不同。例如O′\boldsymbol O'O′的shape為[4,1][4,1][4,1],W′T\boldsymbol W'^TW′T的shape為[16,4][16,4][16,4],Reshape后即可產(chǎn)生[4,4][4,4][4,4]形狀的張量。由于轉(zhuǎn)置卷積在矩陣運(yùn)算時(shí),需要將W′\boldsymbol W'W′轉(zhuǎn)置后才能與轉(zhuǎn)置卷積的輸入O′\boldsymbol O'O′矩陣相乘,故稱為轉(zhuǎn)置卷積。
?轉(zhuǎn)置卷積具有“放大特征圖”的功能,在生成對(duì)抗網(wǎng)絡(luò)、語(yǔ)義分割等中得到了廣泛應(yīng)用,如DCGAN[1]中的生成器通過(guò)堆疊轉(zhuǎn)置卷積層實(shí)現(xiàn)逐層“放大”特征圖,最后獲得十分逼真的生成圖片。
[1] A. Radford, L. Metz 和 S. Chintala, Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks, 2015.
轉(zhuǎn)置卷積實(shí)現(xiàn)
?在TensorFlow中,可以通過(guò)nn.conv2d_transpose實(shí)現(xiàn)轉(zhuǎn)置卷積運(yùn)算。我們先通過(guò)nn.conv2d完成普通卷積運(yùn)算。注意轉(zhuǎn)置卷積的卷積核的定義格式為[k,k,cout,cin][k,k,c_{out},c_{in}][k,k,cout?,cin?]。例如:
import tensorflow as tf from tensorflow.keras import layers, optimizers, datasets, Sequential# 創(chuàng)建4×4大小的輸入 x = tf.range(16)+1 x = tf.reshape(x, [1, 4, 4, 1]) x = tf.cast(x, tf.float32) # 創(chuàng)建3×3卷積核 w = tf.constant([[-1, 2, -3.], [4, -5, 6], [-7, 8, -9]]) w = tf.expand_dims(w, axis=2) w = tf.expand_dims(w, axis=3) # 普通卷積運(yùn)算 out = tf.nn.conv2d(x, w, strides=1, padding='VALID') print(out)
運(yùn)行結(jié)果如下圖所示:
?保持strides=1,padding=‘VALID’,卷積核不變的情況下,我們通過(guò)卷積核www與輸出outoutout的轉(zhuǎn)置卷積運(yùn)算嘗試恢復(fù)與輸入xxx相同大小的高寬張量,代碼如下:
運(yùn)行結(jié)果如下所示:
tf.Tensor( [[[[ 56.][ -51.][ 46.][ 183.]][[-148.][ -35.][ 35.][-123.]][[ 88.][ 35.][ -35.][ 63.]][[ 532.][ -41.][ 36.][ 729.]]]], shape=(1, 4, 4, 1), dtype=float32)
可以看到,轉(zhuǎn)置卷積生成了4×44×44×4的特征圖,單特征圖的數(shù)據(jù)與輸入xxx并不相同。
?在使用tf.nn.conv2d_transpose進(jìn)行轉(zhuǎn)置卷積運(yùn)算時(shí),需要額外手動(dòng)設(shè)置輸出的高寬。tf.nn.conv2d_transpose并不支持自定義padding設(shè)置,只能設(shè)置為VALID或者SAME。
?當(dāng)設(shè)置padding=‘VALID’時(shí),輸出大小表達(dá)為:
o=(i?1)s+ko=(i-1)s+ko=(i?1)s+k
?當(dāng)設(shè)置padding=‘SAME’時(shí),輸出大小表達(dá)為:
o=i?so=i\cdot so=i?s
?如果我們還是對(duì)轉(zhuǎn)置卷積原理細(xì)節(jié)暫時(shí)無(wú)法理解,可以先牢記上述兩個(gè)表達(dá)式即可。例如:
2×22×22×2的轉(zhuǎn)置卷積輸入與3×33×33×3的卷積核運(yùn)算,strides=1,padding=‘VALID’時(shí),輸出大小為:
h′=w′=(2?1)?1+3=4h'=w'=(2-1)\cdot1+3=4h′=w′=(2?1)?1+3=4
2×22×22×2的轉(zhuǎn)置卷積輸入與3×33×33×3的卷積核運(yùn)算,strides=1,padding=‘VALID’時(shí),輸出大小為:
h′=w′=2?3=6h'=w'=2\cdot3=6h′=w′=2?3=6
?轉(zhuǎn)置卷積也可以和其他層一樣,通過(guò)layers.Conv2DTranspose類創(chuàng)建一個(gè)轉(zhuǎn)置卷積層,然后調(diào)用實(shí)例即可完成向前計(jì)算。代碼如下:
運(yùn)行結(jié)果如下:
tf.Tensor( [[[[ 6.942313 ][ 33.887856 ][ 24.800087 ][ -4.222195 ]][[ 21.720724 ][ 68.23484 ][ 73.74913 ][ 28.219326 ]][[ 15.284215 ][ 10.42746 ][ 12.951116 ][ 20.34887 ]][[ -1.9099097][-26.6492 ][-56.841545 ][-32.62231 ]]]], shape=(1, 4, 4, 1), dtype=float32)3. 分離卷積
?這里以深度可分離卷積(Depth-wise Separable Convolution)為例。普通卷積在對(duì)多通道輸入進(jìn)行運(yùn)算時(shí),卷積核的每個(gè)通道與輸入的每個(gè)通道分別進(jìn)行卷積運(yùn)算,得到多通道的特征圖,再對(duì)應(yīng)元素相加產(chǎn)生單個(gè)卷積核的最終輸出,如下圖所示:
?分離卷積的計(jì)算流程則不同,卷積核的每個(gè)通道與輸入的每個(gè)通道進(jìn)行卷積預(yù)算,得到多個(gè)通道的中間特征,如下圖所示。這個(gè)多通道的中間特征張量接下來(lái)進(jìn)行多個(gè)1×11×11×1卷積核的普通卷積運(yùn)算,得到多個(gè)高寬不變的輸出,這些輸出在通道軸上面進(jìn)行拼接,從而產(chǎn)生最終的分離卷積層的輸出。可以看到,分離卷積層包含了兩步卷積運(yùn)算,第一步卷積運(yùn)算是單個(gè)卷積核,第二個(gè)卷積運(yùn)算包含了多個(gè)卷積核。
?那么采用分離卷積有什么優(yōu)勢(shì)呢?一個(gè)很明顯的優(yōu)勢(shì)在于,同樣的輸入和輸出,采用Separable Convolution的參數(shù)量約是普通卷積的13\frac{1}{3}31?。考慮上圖中的普通卷積和分離卷積的例子。普通卷積的參數(shù)量是
3?3?3?4=1083\cdot3\cdot3\cdot4=1083?3?3?4=108
分離卷積的第一部分參數(shù)量是
3?3?3?1=273\cdot3\cdot3\cdot1=273?3?3?1=27
第二部分參數(shù)量是
1?1?3?4=121\cdot1\cdot3\cdot4=121?1?3?4=12
分離卷積的總參數(shù)量只有39,但是卻能實(shí)現(xiàn)普通卷積同樣的輸入輸出尺寸變換。分離卷積在Xception和MobileNets等對(duì)計(jì)算代價(jià)敏感的領(lǐng)域中得到了大量應(yīng)用。
總結(jié)
以上是生活随笔為你收集整理的深度学习之卷积神经网络(11)卷积层变种的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 前端工程师美工学习建议用的软件:C4D
- 下一篇: 深度学习之卷积神经网络(12)深度残差网