Dilated/Atrous conv 空洞卷积/多孔卷积
Dilated/Atrous conv 空洞卷積/多孔卷積
原文鏈接:https://blog.csdn.net/silence2015/article/details/79748729
DilatedDilated convolution/Atrousconvolution/Atrous convolutionconvolution可以叫空洞卷積或者擴張卷積。
空洞卷積誕生于圖像分割領域,圖像輸入到網絡中經過CNNCNN提取特征,再經過poolingpooling降低圖像尺度的同時增大感受野。由于圖像分割是pixel?wisepixel?wise預測輸出,所以還需要通過upsamplingupsampling將變小的圖像恢復到原始大小。upsamplingupsampling通常是通過deconvdeconv(轉置卷積)完成。因此圖像分割FCNFCN有兩個關鍵步驟:池化操作增大感受野,upsamplingupsampling操作擴大圖像尺寸。這兒有個問題,就是雖然圖像經過upsamplingupsampling操作恢復了大小,但是很多細節還是被池化操作丟失了。那么有沒有辦法既增大了感受野又不減小圖像大小呢?DilatedDilated convconv橫空出世。
在講空洞卷積都會用到原論文中的一張圖來說明
在空洞卷積中有個重要的參數叫raterate,這個參數代表了空洞的大小。?
要理解空洞概念和如何操作可以從兩個角度去看。?
1)從原圖角度,所謂空洞就是在原圖上做采樣。采樣的頻率是根據rate參數來設置的,當rate為1時候,就是原圖不丟失任何信息采樣,此時卷積操作就是標準的卷積操作,當rate>1,比如2的時候,就是在原圖上每隔一(rate-1)個像素采樣,如圖b,可以把紅色的點想象成在原圖上的采樣點,然后將采樣后的圖像與kernel做卷積,這樣做其實變相增大了感受野。?
2)從kernel角度去看空洞的話就是擴大kernel的尺寸,在kernel中,相鄰點之間插入rate-1個零,然后將擴大的kernel和原圖做卷積 ,這樣還是增大了感受野。
在VGG網絡中就證明了使用小卷積核疊加來取代大卷積核可以起到減少參數同時達到大卷積核同樣大小感受野的功效。但是通過疊加小卷積核來擴大感受野只能線性增長,公式為(kernelSize?1)?layers+1(kernelSize?1)?layers+1,,也就是線性增長,而空洞卷積可以以指數級增長感受野。
標準卷積方式?
空洞卷積方式?
空洞卷積在全卷積網絡(FCN)(FCN)中可以有效地控制計算特征圖響應的密度,在密集預測的任務中,如語義分割/semanticsemantic imageimage segmentation,segmentation, opticaoptical flowflow computationcomputation, oror depthdepth estimationestimation,當它和雙線性插值一起使用時可以替代轉置卷積。空洞卷積可以在kernel有效增大感受野的同時不增加模型參數或者計算量。在圖像需要全局信息或者語音文本需要較長的sequence信息依賴的問題中,都能較好的應用空洞卷積。在圖像分割,語音合成WaveNet,機器翻譯ByteNet中都有空洞卷積的身影。
在之前的一篇博文中,我稍微總結了deconv/轉置卷積概念和用法,現在把deconv和Dilated conv在一起比較一下。
deconvdeconv主要用在增大圖像尺寸,是upsamplingupsampling的一種。而空洞卷積并沒有做upsampling,而是為了增大感受野,并且可以不改變圖像大小(stridestride為1)。
對于標準的k*k的卷積核,stridestride為ss,分三種情況分析:
1)s>1s>1,在卷積同時并伴隨了downsamplingdownsampling操作,卷積后圖像變小。?
2)s=1s=1,在paddingpadding為SAMESAME時卷積后圖像大小不變?
3)s<1s<1,fractionallyfractionally stridedstrided convolutionconvolution,相當于對原圖先作了upsamplingupsampling操作擴大原圖,然后再卷積,這樣得到的結果圖會變大。
DilatedDilated convconv是在原圖上skipskip一些像素然后做卷積,或者是將kernelkernel填充擴大后來卷積,以達到增大感受野的效果。
在TensorflowTensorflow框架中可以通過兩種方式實現空洞卷積,tf.nn.atrous__conv2dtf.nn.atrous__conv2d或者tf.nn.conv2dtf.nn.conv2d。
tf.nn.atrous__conv2dtf.nn.atrous__conv2d有五個參數,value,filters,rate,padding,namevalue,filters,rate,padding,name。其中raterate就是代表對kernelkernel做填充的程度,在kernelkernel每個值之間填充rate?1rate?1個零,這樣得到的有效卷積核高為filterHeight+(filterHeight?1)?(rate?1)寬為filterWidth+(filterWidth?1)?(rate?1)。filterHeight+(filterHeight?1)?(rate?1)寬為filterWidth+(filterWidth?1)?(rate?1)。
在tf.nn.conv2d函數中有一個參數叫dilations,同樣可以是可以實現空洞卷積的效果
2018/4/2更新:
在實際使用中發現atrous_conv2d和conv2d對于空洞后卷積輸出的shape描述不清楚,自己搜資料發現輸出的shape不光和padding有關,還與rate有關。輸出shape計算思路如下,首先看padding,如果padding是SAME,那么不管rate是多少,都按照這個來算。如果padding是VALID,那么也是按照這個來算,只不過這兒的filter_size需要根據rate來重新算,也就是說空洞是加在卷積核上的,我們先對卷積核填充0,得到新的卷積核大小filter_height = heght+(height-1)*(rate-1),寬同理。將新的filter送到上面VALID模式下計算卷積輸出就是最后的輸出了。實際代碼輸出感受下
import tensorflow as tf import numpy as npinput_img_np = np.random.random((1, 256, 256, 1)).astype(np.float32) kernel = np.random.random((6,6,1,1)).astype(np.float32)with tf.Session() as sess:concrete_input_op = tf.constant(input_img_np)concrete_output_op = tf.nn.convolution(concrete_input_op, kernel, padding='SAME', dilation_rate=np.array([2, 2]))concrete_output = sess.run(concrete_output_op)print('convolution + CONCRETE + SAME')print('concrete_input_op: ', concrete_input_op.get_shape())print('concrete_output_op: ', concrete_output_op.get_shape())print('concrete_output:', concrete_output.shape)assert(concrete_input_op.get_shape() == concrete_output_op.get_shape())convolution + CONCRETE + SAME
Backend TkAgg is interactive backend. Turning interactive mode on.
concrete_input_op: ?(1, 256, 256, 1)
concrete_output_op: ?(1, 256, 256, 1)
concrete_output: (1, 256, 256, 1)?
convolution + UNDEF + SAME
undef_input_op: ?(?, 256, 256, 1)
undef_output_op: ?(?, 256, 256, 1)
undef_output: (1, 256, 256, 1)
convolution + CONCRETE + VALID
valid_concrete_input_op: ?(1, 256, 256, 1)
valid_concrete_output_op: ?(1, 246, 246, 1)
valid_concrete_output: (1, 246, 246, 1)
convolution + UNDEF + VALID
valid_undef_input_op: ?(?, 256, 256, 1)
valid_undef_output_op: ?(?, 246, 246, 1)
valid_undef_output: (1, 246, 246, 1)
?
?tf.nn.atrous_conv2d
# Now atrousconcrete_input_op = tf.constant(input_img_np)concrete_output_op = tf.nn.atrous_conv2d(concrete_input_op, kernel, padding='SAME', rate=2)concrete_output = sess.run(concrete_output_op)print('atrous_conv2d + CONCRETE + SAME')print('concrete_input_op: ', concrete_input_op.get_shape())print('concrete_output_op: ', concrete_output_op.get_shape())print('concrete_output_op: ', concrete_output_op.get_shape())print('concrete_output:', concrete_output.shape)assert(concrete_input_op.get_shape() == concrete_output_op.get_shape())atrous_conv2d + CONCRETE + SAME
concrete_input_op: ?(1, 256, 256, 1)
concrete_output_op: ?(1, 256, 256, 1)
concrete_output_op: ?(1, 256, 256, 1)
concrete_output: (1, 256, 256, 1)
atrous_conv2d + CONCRETE + VALID
valid_concrete_input_op: ?(1, 256, 256, 1)
valid_concrete_output_op: ?(1, 246, 246, 1)
valid_concrete_output: (1, 246, 246, 1)
參考文獻:
Tensorflow官方文檔?
知乎:如何理解空洞卷積(dilated convolution)??
https://github.com/tensorflow/tensorflow/issues/4742
?
總結
以上是生活随笔為你收集整理的Dilated/Atrous conv 空洞卷积/多孔卷积的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TensorFlow数据读取机制:文件队
- 下一篇: TensorFlow模型实现:UNet模