1. 為什么要用shortcut連接
在實踐中,單純的前饋深層網絡特別容易出現梯度消失的問題,并且因為網絡太深,參數太多,訓練和測試耗時極大,這個時候就出現了殘差網絡ResNet和Highway Network,以ResNet為例,其在上下兩層之間構建了一個shortcut,使得下一層可以共享前一層的信息,其基本結構如下圖所示:
假設一個組合函數(里面可以包括BN,激活函數,卷積操作等),并且假設第l ll層的輸出為
,那么傳統的卷積網絡可以表示為(1-1):
而在resnet中,因為引入了殘差操作,因此公式化為(1-2):
然而作者認為,殘差網絡resnet在合并不同層的信息的時候,用的是向量加法操作(summation),這有可能會阻礙(impede)網絡中的信息流動。在《Deep networks with stochastic depth》的工作中,提出了一個觀點,就是resnet中多達上百層的卷積層對整體的效果貢獻是很少的,有許多層其實是冗余的,可以在訓練的過程中隨機丟掉(drop),實際上整個網絡并不需要那么多參數就可以表現得很好。(類似于dropout的做法,只不過是dropout是對一個層里面的神經元輸出進行丟棄,而stochastic depth是對整個層進行隨機丟棄,都可以看成是一種正則手段。)
作者基于這種觀察,將淺層的輸出合并起來,作為后面若干層的輸入,使得每一層都可以利用到前幾個層提取出來的特征,在傳統的CNN中,因為是串行的連接,L層網絡就有L個連接,而在DenseNet中,因為采用了密集連結,所以L層網絡有個連接,整個Dense連接見下圖所示:
其中的這幾層是經過了密集連結的一個單元,作者稱之為“Dense Block”,我們可以發現,其實這個block結構還是很簡單的,就是在block中位于l ll層的輸入同時合并(concatenate)了上層的所有輸出,因此其輸入feature map有
個,其中
是原始圖片的通道數,k稱為增長率,我們待會再談。同樣的,用公式去表達這個過程,就如式(1-3)所示:
2. 關于DenseNet的更多細節
2.1 composite function和transition layer
在本文中,一個組合單元包括有BN層,ReLU函數和卷積層,依次疊加。其中這里卷積層采用了3 × 3大小的卷積核。在CNN中,為了減少計算量,是需要進行下采樣的,經常由池化操作進行。但是為了在dense block中可以合并輸入,其輸出輸入的張量尺寸不能改變,因此在dense block中不能使用池化操作,而是應該在連接兩個dense block之間應用池化,這個中間層,作者稱之為transition layer。在transition layer中,依次疊加了一個BN層,1$\times1 大 小 的 卷 積 和 一 個 2 1大小的卷積和一個21大小的卷積和一個2\times2 的 均 值 池 化 。 其 中 的 1 2的均值池化。其中的12的均值池化。其中的1\times$1卷積是為了進一步壓縮張量的,這個我們后面談。
2.2 growth rate
如果每一個函數都輸出k個特征圖,那么在第l 層就會有
個輸入特征圖,其中的
是初始圖片的通道數。對比DenseNet和其他傳統網絡,前者特點就是可以做的很狹窄,因此這里的k不必取得很大(比如傳統的基本上都是64,32,48等等),在這里
,這樣就大大減少了參數量。這個超參數k kk就稱之為growth rate。
為什么不需要那么多的特征圖呢?作者認為特征圖可以看成是網絡的一種全局的狀態,而在densenet中,因為某一層和前面幾層都有連接,因此一旦全局狀態一旦寫入,就可以在后面的層里面直接挪用了,而不用像傳統的網絡一樣在層與層之間復制這些狀態。
2.3 bottleneck layer
這個層的引入原因很直接就是為了減少輸入量。盡管每一個層只是產生了k個輸出,但是經過若干層的疊加后,也會擴充的很大,會導致后面層的計算復雜度和參數問題,因此可以用的卷積操作進行降維,在本文中,具體操作是:在原先的3 × 3的卷積層前面加入一個1 × 1的卷積。具體的設置如:BN-ReLU-Conv(1×1)-BN-ReLU-Conv(3×3) 。作者統一讓每個1x1卷積輸出4 k個特征圖。(也就是說不管輸入的特征圖有多少通道,都會縮為4k個。)將具有bottleneck layer的densenet稱之為DenseNet-B。
(為什么1x1能夠降維?這個降維主要是體現在通道方向上的降維,可以將原先N個通道降到M個通道。)
2.4 compression
為了進一步增加模型的緊致性,作者在transition layer也進行了縮減特征圖的操作,同樣地,也是通過卷積實現,如果一個block輸出了m個特征圖,那么在接下來的transition layer中就縮減為⌊ θ m ⌋ 個特征圖,其中的
為縮減系數,有
。將同時具有bottleneck layer和transition layer(
)的densenet稱為DenseNet-BC。
3. 實驗部分
在ImageNet上,整個網絡的配置如:
實驗結果如:
其中藍色的表示最好結果,可以看到DenseNet的確是比其他網絡有著更為優良的表現,同時其參數數量更少。
在同樣的參數數量和運算量下的驗證準確率對比:
可以發現,在同樣的參數數量和運算量情況下,DenseNet無論是那種網絡配置,都比ResNet的結果要好。
然后在測試集上進行對比,可以發現結論和驗證集上的一致。
總而言之,實驗結果證明了DenseNet的有效性,并且在同樣參數數量和運算量的程度下,DenseNet可以表現得比同類型的ResNet更好,并且作者在實驗部分強調了他的DenseNet在ImageNet上的結果是沒有經過調優的,因此還可以繼續提高結果。
4. 分析與討論
為什么這個模型能夠work呢?作者給了幾個解釋:
采用了緊致性的模型,有著更少的參數,減少了過擬合。隱式深度監督(implict Deep supervision),因為存在有shortcut的存在,作為優化目標的loss function不必要從最后一層提取信息,可以直接取得前面層次的信息進行學習,類似與將分類器網絡連接在所有隱藏層里面進行學習的deeply-supervised nets(DSN)網絡。類似于ResNet,DenseNet這種shortcut的方式有利于梯度的傳導,減少了梯度消失。其實,這種密集連結的策略也類似于隨機丟棄層的Stochastic depth網絡,因為在Stochastic depth網絡中,池化層是不會被丟棄的,而中間的卷積層可能會被丟棄,也就是在訓練的時候,其實可以看出某兩個非直接連接的層有可能因為丟棄的原因而連接起來,因此兩者有點類似的地方。
按照設計,DenseNet應該可以通過前面層的信息中直接獲取特征圖從而得到提升小姑的,雖說實驗效果的確是比resnet的要好,但是前面層的信息的短接(shortcut)真的對分類結果有貢獻嗎?作者又補充了一個實驗:
作者訓練了一個網絡,然后將一個block中的源層(source layer)和目標層(target layer)之間的權值取均值,然后繪制成了一個熱值圖,如上。其中每一個圖都是一個block的層層連接權值均值圖。顏色越深表示目標層從源層里面得到了更多的貢獻,我們可以發現,目標層除了最近鄰的層之外,的確是在前面的若干層中獲得了不少信息的。
5. 其他
因為現在的框架對于densenet沒有直接的支持,因此實現的時候往往是采用concatenate實現的,將之前層的輸出與當前層的輸出拼接在一起,然后傳給下一層。對于大多數框架(如 Torch 和 TensorFlow),每次拼接操作都會開辟新的內存來保存拼接后的特征。這樣就導致一個 L 層的網絡,要消耗相當于 L(L+1)/2 層網絡的內存(第 l 層的輸出在內存里被存了 (L-l+1) 份)。
這里有一些框架的解決方案,可供參考,具體內容見引用1:
- Torch implementation: https://github.com/liuzhuang13/DenseNet/tree/master/models
- PyTorch implementation: https://github.com/gpleiss/efficient_densenet_pytorch
- MxNet implementation: https://github.com/taineleau/efficient_densenet_mxnet
- Caffe implementation:https://github.com/Tongcheng/DN_CaffeScript
Reference
- 《CVPR 2017最佳論文作者解讀:DenseNet 的“what”、“why”和“how”|CVPR 2017》
- 《DenseNet算法詳解》