卷積核膨脹(dilation)解析
第一位大神解析:
-
deeplab方法概述 deeplab方法分為兩步走,第一步仍然採用了FCN得到 coarse score map並插值到原影象大小,然後第二步借用fully connected CRF對從FCN得到的分割結果進行細節上的refine。(有關FCN的內容介紹,可以參考我的前面得一篇部落格:http://blog.csdn.net/tangwei2014/article/details/46882257) 下面這張圖很清楚地展示了整個結構: 然後這張圖展示了CRF處理前後的效果對比,可以看出用了CRF以後,細節確實改善了很多:
-
deeplab對FCN更加優雅的處理方式 在第一步中,deeplab
-
Hole演算法 於是乎,作者想出了一招,來解決兩個看似有點矛盾的問題:既想利用已經訓練好的模型進行fine-tuning,又想改變網路結構得到更加dense的score map.
第二位大神解析:
原作者解析caffe的卷積層時,在conv_layer.cpp中有一個卷積核膨脹操作,在conv_layer.cpp的第17行有如下程式碼
const int kernel_extent = dilation_data[i] * (kernel_shape_data[i] - 1) + 1;
上面的程式碼描述了卷積核的膨脹操作,我們不妨來做個假設,卷積核為3*3的,膨脹係數為2,那麼,卷積核膨脹之後,卷積核的單邊尺寸就變成了2*(3-1)+1,即卷積核的尺寸變成了5*5,筆者在最初看到這一行程式碼的時候相當疑惑,不太明白卷積核由3*3變成5*5是怎麼操作的,這個時候,caffe.proto就起了作用,我們開啟caffe.proto,找到卷積層的引數定義,在message ConvolutionParameter中,找到關於dilation的定義如下
// Factor used to dilate the kernel, (implicitly) zero-filling the resulting
// holes. (Kernel dilation is sometimes referred to by its use in the
// algorithme à trous from Holschneider et al. 1987.)
repeated uint32 dilation = 18; // The dilation; defaults to 1
在caffe.proto中,闡述了卷積核膨脹的使用情景,即在à trous演算法中,這是一個有關小波分析的演算法。卷積核膨脹是將卷積核擴張到膨脹尺度約束的尺度中,並將原卷積核沒有佔用的區域填充零,為了使說明更加形象,下面筆者繪製卷積核膨脹示意圖為大家解析一下卷積核膨脹操作:
在上面的示意圖中,卷積核由3*3膨脹到了5*5,讀者朋友們可以看到,膨脹後的卷積核中填充了一些0,讀者朋友們可以試著畫出其他尺寸的卷積核搭配不同膨脹係數的膨脹效果,而具體的膨脹操作是在img2col中實現的,img2col.cpp筆者將在後話解析。
下面筆者分析一下膨脹係數與卷積核膨脹的關係,首先回到卷積核膨脹公式:
膨脹的卷積核尺寸 = 膨脹係數 * (原始卷積核尺寸 - 1) + 1
首先由於卷積的操作特性,卷積核尺寸是奇數,則原始卷積核尺寸減一為偶數。那麼,在上述公式中,膨脹係數*偶數-1為奇數,保證了膨脹的卷積核尺寸為奇數。其次,筆者認為,卷積核的膨脹係數刻畫了卷積核高和寬方向的擴張倍數,可將上述公式看作:
膨脹的卷積核尺寸 - 1 = 膨脹係數 * (原始卷積核尺寸 - 1)
到此為止,卷積核膨脹就解析完畢了,通過對卷積核膨脹的理解,筆者感受到,在閱讀原始碼不明白時,尤其在對卷積這種抽象的操作中的細節不明白時,可以動筆畫一畫,將不形象轉為形象,問題就迎刃而解了!