1. 程式人生 > >FCN用卷積層代替FC層原因(轉)

FCN用卷積層代替FC層原因(轉)

alex spa 內容 pool 計算 lex 級別 conv2 本質

分類任務

CNN對於常見的分類任務,基本是一個魯棒且有效的方法。例如,做物體分類的話,入門級別的做法就是利用caffe提供的alexnet的模型,然後把輸出的全連接層稍稍修改稱為自己想要的類別數,然後再根據實際需要修改網絡模型(通常是瘦身)。下面記錄幾個point。

關於crop

一般在訓練的時候會利用兩個手段做data augmentation,分別是mirror和crop。其中,mirror沒什麽特別,但是crop有一些東西我們需要了解。

  • 在訓練的時候,crop操作會在大圖上隨機切小圖,然後小圖才是進入CNN的數據;而在測試的時候,crop操作是直接在大圖中間取小圖;
  • 我們做前向的時候,可以考慮模擬訓練時候的crop機制,多crop幾份,然後每一個crop都前向一遍,然後綜合考慮多個crop的前向結果;
  • 上一點提到的多個crop類似於多次試驗求平均的感覺;
  • 多crop求平均的手法可以構成一個batch來一起走一次前向;

以上是比較普通的trick,仔細思考第四點的計算性能,我們會發現,這種做法對於一張完整的大圖而言,有很多像素都被重復計算了。那麽,下面介紹一種較為巧妙的思路(需要對卷積層以及對特征有比較深刻的理理解)。

  • 依然用普通的方式訓練一個CNN
  • 一般我們的網絡在最後面會加入全連接層把feature map壓成一個一維向量,然後我們需要先理解一個說法:全連接層實際上是n個1*1的卷積核對上層feature進行卷積,然後在對卷積後的feature做一次均值pooling;

下面用兩個簡單的例子說明:

例1
<fc1> output: 9  
<fc2> output: 1  

[1 2 3 4 5 6 7 8 9]
[a b c d e f g h i]
得到
[1*a+2*b+3*c+...+9*i]

則需要的9個權值,每個權值一一對應fc1的值。那麽假如,fc2換成卷積層,那麽

<fc1> output:9  
<conv2> output:1, kernel:(1,1)  

[1 2 3 4 5 6 7 8 9]
[a b c d e f g h i]
得到
[1*a 2*b 3*c ... 9*i]

剛好也是需要9個權值,一一對應fc1。但是呢,這時候經過conv2的卷積,目前的feature實際上就保持了和fc1一致的形狀。那麽怎麽把它變成我們想要的output=1呢?這時候就是一個均值加權的過程,即卷積後的九個值求加權平均得到真正的輸出。

例2

理解了例1後,再來理解例2

<conv1> outputsize:(1,2,2)  # 1通道,寬高各為2
<fc2> output: 2

1 2 
3 4 

a b       e  f
c d   ,   g  h

得到
[a*1+b*2+c*3+d*4, e*1+f*2+g*3+h*4]

這個網絡需要的同樣是4*2=8個權值,每4個一組分別對應展開conv1後的4個像素,共兩組,故可以得到兩個計算值。這時候,把網絡變成

<conv1> shape:(1,2,2)  # 1通道,寬高各為2
<conv2> kernel:(1,1), output:2

1 2 
3 4 

a b      e  f
c d   ,  g  h

得到兩個特征矩陣
1a 2b   1e 2f
3c 4d , 3g 4h 

實際上只需要分別把兩個矩陣所有元素求和就可以得到與全連接一樣的值。

回到正題,花了很多筆墨提出這個全連接層等同與1*1卷積核,是為了在前向時把全連接層替換掉。為什麽呢?假設沒有全連接層,實際上我們對於輸入圖片的大小是沒有任何限制的,大圖小圖一樣都經過卷積池化激活。這種網絡有人稱為全卷積網絡(FCN)。

好,那麽現在替換全連接層為卷積層之後,輸入圖片大小是任意的,那麽意味著最後一層出來的feature不再是1*1,而可能是m*n。所以為了映射到分類任務的結果,把最後的featuremap做一下求和,然後送入softmax層,就得到了每個類別的可能性。

那麽,為什麽我將這部分內容放在“關於crop”這個標簽下面呢?思考一下,假如用普通的crop策略,那麽是不是相當於全卷積到最後一層只取出crop區域對應的特征圖的點區域?全卷積是不是就相當於crop了全圖的所有能crop的區域並融合在一起?(有點拗口)核心的思想是,CNN訓練得到的是濾波器,本質上是對於某種特定的模式有響應,反之無響應,所以全卷積一直到最後一層,響應最強的特征圖,就是對應的分類。

FCN用卷積層代替FC層原因(轉)