1. 程式人生 > >深度估計 Fully Convolutional Networks for Semantic Segmentation

深度估計 Fully Convolutional Networks for Semantic Segmentation

1.介紹

該文講述的是語義分割,但思路和框架和深度恢復是十分相似的,畢竟當前語義和深度問題本質上是一個畫素級的分類問題。從該文3000+引用用量也可見該文章的巨大啟發效果。

所謂全卷積網路,是指由僅由卷積層、池化層和非線性啟用函式層交錯組織起來的網路。

作者的貢獻在於將非常熱門且有效地做分類的卷積網路應用於語義分割中。整個框架是接受整張影象作為輸入,用卷積做一個coarse的分類輸出,然後將這些輸出與每個畫素聯絡在一起,得到最後的畫素級別的語義分類結果輸出。主要改進如下:這裡寫圖片描述

可以看出,作者將全連線層改為卷積層。 全連線層可以看成核大小為影象邊長的卷積層,感知到整張影象。所以相對於全連線層,普通的核很小的的卷積層只能感知上一層中的區域資訊,所謂卷積層能很好地保持空間資訊(不劇烈變化),有“spatial output”,而全連線層只有“non-spatial output”。而且卷積層可以隨意調整輸出大小(一般是降取樣,即影象變小),得到coarse 的輸出。

作者分別使用了pretrained VGG,AlexNet和自己實現的GoogleNet。將上述模型後半的全連線層改為卷積層。這樣這些模型就成了FCN了。再加上一個1x1x21(有21種類別)的卷積層作為預測輸出,得到縮小的語義map。最後再對輸出進行反捲積得到最終和原圖同等大小的輸出。

2.patch training 與fully convolutional training

語義分割是對每個畫素x分類,假如將整個影象作為輸入,那麼與x所在的object距離較遠的影象部分對x的分類將毫無作用。因此以前的做法是將影象分為很多塊,每次epoch是隨機選擇整個訓練集上的n個影象塊作為mini batch來做一次訓練。這就是所謂的“ patch training ”。而FCN的作者認為沒有這種必要,直接將整張影象作為輸入即可。如果patchwise 的一個batch剛好包含了價值函式所對整張圖receptive filed時,即相當於輸入整張影象。但patchwise的方法卻不可避免每取一次batch,總會有一些影象塊是有重疊的。輸入整張圖卻可以避免patchbatch之間的重疊,這樣更加高效。作者給的第二個理由是雖然在整個訓練集中的patches取樣雖然能減少類別之間的不平衡,緩和patch之間的空間重疊,但通過對最後輸出map的價值函式進行權重和取樣,也能達到這個效果。作者發現對於FCN來說,並沒有必要進行分類的平衡(因為整張圖片大部分都是背景)。

3.model

文章沒有細說模型的價值函式,但說明是用傳統的CNN進行多分類的模型,最後的價值函式是預測值與真實值的畫素重疊面積對於每個畫素的平均值。並且是考慮所有語義類包括背景的平均值。這其中忽略掉沒有真值或真值有問題(ambiguous)的影象部分。

4.unsample

隨著卷積層的預測深入,預測輸出的size越來越小,為了最終得到原圖每個畫素對應的預測值,需要對卷積層末端的預測值進行升取樣。shift-and-stitch 假如輸出o是輸入i大小(本文大小一般指影象長或寬)的1/f,那麼對輸入影象進行縮放平移到一個大小為f的區間,然後將shifted之後的輸入ii和o結合在一起作為新的輸入。儘管作者認為這種方法具有輸出更稠密且保持每個輸出的感知區域大小的優點(也有缺點,在此不贅述),但作者僅僅是嘗試了這種想法,實際上用的還是以下的升取樣的方法。backwards convolution

將影象由小變大的階段使用轉置卷積(deconvolution,backwards convolution 或transpose convolution)的方法提升輸出的解析度。轉置卷積的核引數初值為線性插值,但在整個訓練過程中會不斷學習調整最終確定。這種轉置卷積+非線性啟用函式構成的升取樣層,能模擬一個很好地非線性升取樣對映。

Refine(Combine what and where)

一般來說,隨著卷積層數的增多,每層的輸出會越來越模糊,這導致了單純通過上述的卷積網路後圖像變得十分鈍,分類效果不精細。為了更精細的分類,勢必引入更淺(前面)層的資訊。所以作者加了skip層,來融合底層的資訊:這裡寫圖片描述 第一行中用stride為32來進行融合,第二行用stride=15來融合,第三行用stride=8來融合,也就是越偏底層,stride越小,得到的結果越精細。對第一行中通過1x1卷積得到的最右端輸出結果FCN-32s(意思是需要進行32的unsample才能得到最終大小的影象),和一個卷積層conv進行stride為32的卷積,得到結果o1,同時此時pool4經過1x1核卷積處理得到o2;將o1和o2進行融合(直接加上去),最後再升取樣到原始影象得到FCN-16s。以下處理類似。 這種方式極大地提升了最後的精度,UI從3提升到62。效果如下:

這裡寫圖片描述

這樣一來,如果池化的stride越小,那麼淺層的輸出就越精細,並非越小越好。因為這樣一來,前面降取樣速度下降,同等層數下後方的卷積層的核就要增大。這樣對計算消耗影響太大了。

正所謂:Global information resolve what, and local information resolve where 這句話一定要寫出來:)

patch sampling

其實就是dropout。由於dropout丟棄了部分神經元,為了保持最後輸出數目不變,作者同等增加了每個batch的影象數目。作者嘗試了不同的dropout值,有效果上的提升但不明顯,於是作者最後結論是不用它。

最後,作者的程式碼奉上。

轉自 https://blog.csdn.net/Kevin_cc98/article/details/78935650