【目標檢測】【cnn】Densenet詳解

Densenet受啓發於resnet,通過shortcut(skip connection)建立前面層到後面層的聯繫,有助於訓練過程中的梯度反向傳播。相比於resnet,densenet設計了更密集的shortcut,建立了前面的所有層和後面的密集連接。Densenet還通過特徵在channel上的連接來實現特徵重用,這減少了DenseNet的參數量和計算成本。

DenseNet提出了一個非常激進的密集連接機制:互相連接所有的層。也就是每個層都會接受前面所有層作爲額外的輸入。這個層會與前面所有層在channel維度上連接(concat)在一起(各個層的特徵圖大小是相同的),並作爲下一層的輸入。也就是說,對於一個L層的網絡,DenseNet共包含L(L+1)/2個連接。DenseNet是直接concat來自不同層的特徵圖,這可以實現特徵重用,提升效率。

Densenet的前向傳播過程。

主要就是多層特徵連接的方式。x1的特徵圖包含了h1(x0)和x0,在channel維度上concat;x2的特徵圖包含了h1(x0), h2(h1(x0)+x0), x0(禁止套娃)也就是x0、x1和x2. 這些特徵圖都有一樣的尺度,在通道上是累加的,也就是前面的所有提取的數據都保留到後一層,相當於網絡參數量提高了,提高了網絡的表達能力。

所以只有在圖片小和通道數量少的情況才能用densenet,不然這通道數的暴增頂不住啊。。。

由於CNN中需要pooling或者stride>1的卷積來降低特徵圖的大小,而DenseNet的密集連接方式需要特徵圖大小保持一致。所以DenseNet中使用了DenseBlock+Transition的結構,DenseBlock是包含很多層的模塊,每個層的特徵圖大小相同,層與層之間採用密集連接的方式。而Transition模塊是連接兩個相鄰的DenseBlock,並且通過Pooling使特徵圖大小降低。

DenseBlock的映射是BN+ReLU+3x3 Conv。

DenseBlock的特徵圖數k的計算。所有DenseBlock中各個層卷積之後輸出k個特徵圖,即得到的特徵圖的channel數爲k。k在DenseNet中稱爲growth rate,這是一個超參數,一般情況下使用較小的k(比如12),就可以得到較好的性能。假設輸入層的channel數k0,那麼l層的輸入channel數爲k0+k(l-1),所以隨着層數的增加,通道數會成爆炸式增長。

DenseBlock採用bottleneck層來減少計算量。主要是在原有結構中增加1x1Conv,即BN+ReLU+1x1 Conv+BN+ReLU+3x3 Conv,成爲DenseNet-B結構。其中1x1 Conv得到的4k個特徵圖是爲了降低特徵數量(直接降低了channel數)。

Transition連接相鄰的DenseBlock,並且降低特徵圖大小。Transition包括一個1x1的卷積和2x2的AvgPooling,結構爲N+ReLU+1x1 Conv+2x2 AvgPooling。Transition層起到了壓縮模型的作用,可以通過設置1x1卷積層通道數來調節輸出的通道數。對於使用bottleneck層的DenseBlock結構和壓縮係數小於1的Transition組合結構稱爲DenseNet-BC。

ImageNet上的DenseNet:

DenseNet優點:

1、省參數。在 ImageNet 分類數據集上達到同樣的準確率,DenseNet 所需的參數量不到 ResNet 的一半。對於工業界而言,小模型可以顯著地節省帶寬,降低存儲開銷。

2、省計算。達到與 ResNet 相當的精度,DenseNet 所需的計算量也只有 ResNet 的一半左右。計算效率在深度學習實際應用中的需求非常強烈,從本次 CVPR 會上大家對模型壓縮以及 MobileNet 和 ShuffleNet 這些工作的關注就可以看得出來。最近我們也在搭建更高效的 DenseNet,初步結果表明 DenseNet 對於這類應用具有非常大的潛力,即使不用 Depth Separable Convolution 也能達到比現有方法更好的結果,預計在近期我們會公開相應的方法和模型。

3、抗過擬合。DenseNet 具有非常好的抗過擬合性能,尤其適合於訓練數據相對匱乏的應用。對於 DenseNet 抗過擬合的原因有一個比較直觀的解釋:神經網絡每一層提取的特徵都相當於對輸入數據的一個非線性變換,而隨着深度的增加,變換的複雜度也逐漸增加(更多非線性函數的複合)。相比於一般神經網絡的分類器直接依賴於網絡最後一層(複雜度最高)的特徵,DenseNet 可以綜合利用淺層複雜度低的特徵,因而更容易得到一個光滑的具有更好泛化性能的決策函數。實際上,DenseNet 的泛化性能優於其他網絡是可以從理論上證明的:去年的一篇幾乎與 DenseNet 同期發佈在 arXiv 上的論文(AdaNet: Adaptive Structural Learning of Artificial Neural Networks)所證明的結論(見文中 Theorem 1)表明類似於 DenseNet 的網絡結構具有更小的泛化誤差界。

4、泛化性能更強。如果沒有data augmention,CIFAR-100下,ResNet表現下降很多,DenseNet下降不多,說明DenseNet泛化性能更強。
 

這幾個優點解決的是神經網絡中的主要問題:

1.Underfitting(欠擬合)。一般來說,模型越爲複雜,表達能力越強,越不容易欠擬合。但是深度網絡不一樣,模型表達能力夠,但是算法不能達到那個全局的最優(resnet基本解決)。

2.Overfiting(過擬合),泛化能力下降。

3.實際系統的部署。如何提升效率和減少內存、能量消耗。
 

對densenet的改進:

1. 每層開始的瓶頸層(1x1 卷積)對於減少參數量和計算量非常有用。

2. 像 VGG 和 ResNet 那樣每做一次下采樣(down-sampling)之後都把層寬度(growth rate) 增加一倍,可以提高 DenseNet 的計算效率(FLOPS efficiency)。

3. 與其他網絡一樣,DenseNet 的深度和寬度應該均衡的變化,當然 DenseNet 每層的寬度要遠小於其他模型。

4. 每一層設計得較窄會降低 DenseNet 在 GPU 上的運算效率,但可能會提高在 CPU 上的運算效率。

 

原作者面對疑問的解釋

1、密集連接不會帶來冗餘嗎?

這是一個很多人都在問的問題,因爲「密集連接」這個詞給人的第一感覺就是極大的增加了網絡的參數量和計算量。但實際上 DenseNet 比其他網絡效率更高,其關鍵就在於網絡每層計算量的減少以及特徵的重複利用。DenseNet 的每一層只需學習很少的特徵,使得參數量和計算量顯著減少。比如對於 ImageNet 上的模型,ResNet 在特徵圖尺寸爲 7x7 的階段,每個基本單元(包含三個卷積層)的參數量爲 2048x512x1x1+512x512x3x3+512x2048x1x1=4.5M,而 DenseNet 每個基本單元(包含兩個卷積層,其輸入特徵圖的數量一般小於 2000)的參數量約爲 2000x4x32x1x1 + 4x32x32x3x3 = 0.26M,大幅低於 ResNet 每層的參數量。這就解釋了爲什麼一個 201 層的 DenseNet 參數量和計算量都只有一個 101 層 ResNet 的一半左右。

還有一個自然而然的問題就是,這麼多的密集連接,是不是全部都是必要的,有沒有可能去掉一些也不會影響網絡的性能?論文裏面有一個熱力圖(heatmap),直觀上刻畫了各個連接的強度。從圖中可以觀察到網絡中比較靠後的層確實也會用到非常淺層的特徵。

via

我們還做過一些簡單的實驗,比如每一層都只連接到前面最近的 m 層(例如 m=4),或者奇(偶)數層只與前面的偶(奇)數層相連,但這樣簡化後的模型並沒有比一個相應大小的正常 DenseNet 好。當然這些都只是一些非常初步的嘗試,如果採用一些好的剪枝(prune)的方法,我覺得 DenseNet 中一部分連接是可以被去掉而不影響性能的。

2、DenseNet 特別耗費顯存?

不少人跟我們反映過 DenseNet 在訓練時對內存消耗非常厲害。這個問題其實是算法實現不優帶來的。當前的深度學習框架對 DenseNet 的密集連接沒有很好的支持,我們只能藉助於反覆的拼接(Concatenation)操作,將之前層的輸出與當前層的輸出拼接在一起,然後傳給下一層。對於大多數框架(如 Torch 和 TensorFlow),每次拼接操作都會開闢新的內存來保存拼接後的特徵。這樣就導致一個 L 層的網絡,要消耗相當於 L(L+1)/2 層網絡的內存(第 l 層的輸出在內存裏被存了 (L-l+1) 份)。

解決這個問題的思路其實並不難,我們只需要預先分配一塊緩存,供網絡中所有的拼接層(Concatenation Layer)共享使用,這樣 DenseNet 對內存的消耗便從平方級別降到了線性級別。在梯度反傳過程中,我們再把相應卷積層的輸出複製到該緩存,就可以重構每一層的輸入特徵,進而計算梯度。當然網絡中由於 Batch Normalization 層的存在,實現起來還有一些需要注意的細節。

新的實現極大地減小了 DenseNet 在訓練時對顯存的消耗,比如論文中 190 層的 DenseNet 原來幾乎佔滿了 4 塊 12G 內存的 GPU,而優化過後的代碼僅需要 9G 的顯存,在單卡上就能訓練。

另外就是網絡在推理(或測試)的時候對內存的消耗,這個是我們在實際產品中(尤其是在移動設備上)部署深度學習模型時最關心的問題。不同於訓練,一般神經網絡的推理過程不需要一直保留每一層的輸出,因此可以在每計算好一層的特徵後便將前面層特徵佔用的內存釋放掉。而 DenseNet 則需要始終保存所有前面層的輸出。但考慮到 DenseNet 每一層產生的特徵圖很少,所以在推理的時候佔用內存不會多於其他網絡。

3、DenseNet 是受什麼啓發提出來的?

DenseNet 的想法很大程度上源於我們去年發表在 ECCV 上的一個叫做隨機深度網絡(Deep networks with stochastic depth)工作。當時我們提出了一種類似於 Dropout 的方法來改進ResNet。我們發現在訓練過程中的每一步都隨機地「扔掉」(drop)一些層,可以顯著的提高 ResNet 的泛化性能。這個方法的成功至少帶給我們兩點啓發:

首先,它說明了神經網絡其實並不一定要是一個遞進層級結構,也就是說網絡中的某一層可以不僅僅依賴於緊鄰的上一層的特徵,而可以依賴於更前面層學習的特徵。想像一下在隨機深度網絡中,當第 l 層被扔掉之後,第 l+1 層就被直接連到了第 l-1 層;當第 2 到了第 l 層都被扔掉之後,第 l+1 層就直接用到了第 1 層的特徵。因此,隨機深度網絡其實可以看成一個具有隨機密集連接的 DenseNet。

其次,我們在訓練的過程中隨機扔掉很多層也不會破壞算法的收斂,說明了 ResNet 具有比較明顯的冗餘性,網絡中的每一層都只提取了很少的特徵(即所謂的殘差)。實際上,我們將訓練好的 ResNet 隨機的去掉幾層,對網絡的預測結果也不會產生太大的影響。既然每一層學習的特徵這麼少,能不能降低它的計算量來減小冗餘呢?

參考:https://zhuanlan.zhihu.com/p/37189203

https://blog.csdn.net/comway_Li/article/details/82055229

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章