SENET 轉載

https://blog.csdn.net/wangkun1340378/article/details/79092001

https://blog.csdn.net/u014380165/article/details/78006626

論文:Squeeze-and-Excitation Networks
論文鏈接:https://arxiv.org/abs/1709.01507
代碼地址:https://github.com/hujie-frank/SENet
PyTorch代碼地址:https://github.com/miraclewkf/SENet-PyTorch
 

我們從最基本的卷積操作開始說起。近些年來,卷積神經網絡在很多領域上都取得了巨大的突破。而卷積核作爲卷積神經網絡的核心,通常被看做是在局部感受野上,將空間上(spatial)的信息和特徵維度上(channel-wise)的信息進行聚合的信息聚合體。卷積神經網絡由一系列卷積層、非線性層和下采樣層構成,這樣它們能夠從全局感受野上去捕獲圖像的特徵來進行圖像的描述。

然而去學到一個性能非常強勁的網絡是相當困難的,其難點來自於很多方面。最近很多工作被提出來從空間維度層面來提升網絡的性能,如 Inception 結構中嵌入了多尺度信息,聚合多種不同感受野上的特徵來獲得性能增益;在 Inside-Outside 網絡中考慮了空間中的上下文信息;還有將 Attention 機制引入到空間維度上,等等。這些工作都獲得了相當不錯的成果。

我們可以看到,已經有很多工作在空間維度上來提升網絡的性能。那麼很自然想到,網絡是否可以從其他層面來考慮去提升性能,比如考慮特徵通道之間的關係?我們的工作就是基於這一點並提出了 Squeeze-and-Excitation Networks(簡稱 SENet)。在我們提出的結構中,Squeeze 和 Excitation 是兩個非常關鍵的操作,所以我們以此來命名。我們的動機是希望顯式地建模特徵通道之間的相互依賴關係。另外,我們並不打算引入一個新的空間維度來進行特徵通道間的融合,而是採用了一種全新的「特徵重標定」策略。具體來說,就是通過學習的方式來自動獲取到每個特徵通道的重要程度,然後依照這個重要程度去提升有用的特徵並抑制對當前任務用處不大的特徵。

上圖是我們提出的 SE 模塊的示意圖。給定一個輸入 x,其特徵通道數爲 c_1,通過一系列卷積等一般變換後得到一個特徵通道數爲 c_2 的特徵。與傳統的 CNN 不一樣的是,接下來我們通過三個操作來重標定前面得到的特徵。

首先是 Squeeze 操作,我們順着空間維度來進行特徵壓縮,將每個二維的特徵通道變成一個實數,這個實數某種程度上具有全局的感受野,並且輸出的維度和輸入的特徵通道數相匹配。它表徵着在特徵通道上響應的全局分佈,而且使得靠近輸入的層也可以獲得全局的感受野,這一點在很多任務中都是非常有用的。

其次是 Excitation 操作,它是一個類似於循環神經網絡中門的機制。通過參數 w 來爲每個特徵通道生成權重,其中參數 w 被學習用來顯式地建模特徵通道間的相關性。

最後是一個 Reweight 的操作,我們將 Excitation 的輸出的權重看做是進過特徵選擇後的每個特徵通道的重要性,然後通過乘法逐通道加權到先前的特徵上,完成在通道維度上的對原始特徵的重標定。

上左圖是將 SE 模塊嵌入到 Inception 結構的一個示例。方框旁邊的維度信息代表該層的輸出。

這裏我們使用 global average pooling 作爲 Squeeze 操作。緊接着兩個 Fully Connected 層組成一個 Bottleneck 結構去建模通道間的相關性,並輸出和輸入特徵同樣數目的權重。我們首先將特徵維度降低到輸入的 1/16,然後經過 ReLu 激活後再通過一個 Fully Connected 層升回到原來的維度。這樣做比直接用一個 Fully Connected 層的好處在於:1)具有更多的非線性,可以更好地擬合通道間複雜的相關性;2)極大地減少了參數量和計算量。然後通過一個 Sigmoid 的門獲得 0~1 之間歸一化的權重,最後通過一個 Scale 的操作來將歸一化後的權重加權到每個通道的特徵上。

除此之外,SE 模塊還可以嵌入到含有 skip-connections 的模塊中。上右圖是將 SE 嵌入到 ResNet 模塊中的一個例子,操作過程基本和 SE-Inception 一樣,只不過是在 Addition 前對分支上 Residual 的特徵進行了特徵重標定。如果對 Addition 後主支上的特徵進行重標定,由於在主幹上存在 0~1 的 scale 操作,在網絡較深 BP 優化時就會在靠近輸入層容易出現梯度消散的情況,導致模型難以優化。

目前大多數的主流網絡都是基於這兩種類似的單元通過 repeat 方式疊加來構造的。由此可見,SE 模塊可以嵌入到現在幾乎所有的網絡結構中。通過在原始網絡結構的 building block 單元中嵌入 SE 模塊,我們可以獲得不同種類的 SENet。如 SE-BN-Inception、SE-ResNet、SE-ReNeXt、SE-Inception-ResNet-v2 等等。

從上面的介紹中可以發現,SENet 構造非常簡單,而且很容易被部署,不需要引入新的函數或者層。除此之外,它還在模型和計算複雜度上具有良好的特性。拿 ResNet-50 和 SE-ResNet-50 對比舉例來說,SE-ResNet-50 相對於 ResNet-50 有着 10% 模型參數的增長。額外的模型參數都存在於 Bottleneck 設計的兩個 Fully Connected 中,由於 ResNet 結構中最後一個 stage 的特徵通道數目爲 2048,導致模型參數有着較大的增長,實驗發現移除掉最後一個 stage 中 3 個 build block 上的 SE 設定,可以將 10% 參數量的增長減少到 2%。此時模型的精度幾乎無損失。

另外,由於在現有的 GPU 實現中,都沒有對 global pooling 和較小計算量的 Fully Connected 進行優化,這導致了在 GPU 上的運行時間 SE-ResNet-50 相對於 ResNet-50 有着約 10% 的增長。儘管如此,其理論增長的額外計算量僅僅不到 1%,這與其在 CPU 運行時間上的增長相匹配(~2%)。可以看出,在現有網絡架構中嵌入 SE 模塊而導致額外的參數和計算量的增長微乎其微。

在訓練中,我們使用了一些常見的數據增強方法和 Li Shen 提出的均衡數據策略。爲了提高訓練效率,我們使用了我們自己優化的分佈式訓練系統 ROCS, 並採用了更大的 batch-size 和初始學習率。所有的模型都是從頭開始訓練的

接下來,爲了驗證 SENets 的有效性,我們將在 ImageNet 數據集上進行實驗,並從兩個方面來進行論證。一個是性能的增益 vs. 網絡的深度; 另一個是將 SE 嵌入到現有的不同網絡中進行結果對比。另外,我們也會展示在 ImageNet 競賽中的結果。

首先我們來看一下網絡的深度對 SE 的影響。上表分別展示了 ResNet-50、ResNet-101、ResNet-152 和嵌入 SE 模型的結果。第一欄 Original 是原作者實現的結果,爲了進行公平的比較,我們在 ROCS 上重新進行了實驗得到 Our re-implementation 的結果(ps. 我們重實現的精度往往比原 paper 中要高一些)。最後一欄 SE-module 是指嵌入了 SE 模塊的結果,它的訓練參數和第二欄 Our re-implementation 一致。括號中的紅色數值是指相對於 Our re-implementation 的精度提升的幅值。

從上表可以看出,SE-ResNets 在各種深度上都遠遠超過了其對應的沒有 SE 的結構版本的精度,這說明無論網絡的深度如何,SE 模塊都能夠給網絡帶來性能上的增益。值得一提的是,SE-ResNet-50 可以達到和 ResNet-101 一樣的精度;更甚,SE-ResNet-101 遠遠地超過了更深的 ResNet-152。

上圖展示了 ResNet-50 和 ResNet-152 以及它們對應的嵌入 SE 模塊的網絡在 ImageNet 上的訓練過程,可以明顯地看出加入了 SE 模塊的網絡收斂到更低的錯誤率上。

另外,爲了驗證 SE 模塊的泛化能力,我們也在除 ResNet 以外的結構上進行了實驗。從上表可以看出,將 SE 模塊嵌入到 ResNeXt、BN-Inception、Inception-ResNet-v2 上均獲得了不菲的增益效果。由此看出,SE 的增益效果不僅僅侷限於某些特殊的網絡結構,它具有很強的泛化性。

上圖展示的是 SE 嵌入在 ResNeXt-50 和 Inception-ResNet-v2 的訓練過程對比。

在上表中我們列出了一些最新的在 ImageNet 分類上的網絡的結果。其中我們的 SENet 實質上是一個 SE-ResNeXt-152(64x4d),在 ResNeXt-152 上嵌入 SE 模塊,並做了一些其他修改和訓練優化上的小技巧,這些我們會在後續公開的論文中進行詳細介紹。可以看出 SENet 獲得了迄今爲止在 single-crop 上最好的性能。

最後,在 ILSVRC 2017 競賽中,我們的融合模型在測試集上獲得了 2.251% Top-5 錯誤率。對比於去年第一名的結果 2.991%, 我們獲得了將近 25% 的精度提升。

 

附:看了下caffe代碼(.prototxt文件),和文章的實現還有些不一樣。下圖是在Inception中添加SENet的可視化結果:SE-BN-Inception,在Inception中是在每個Inception的後面連上一個SENet,下圖的上面一半就是一個Inception,下面一半就是一個SENet,然後這個SENet下面又連着一個新的Inception。

這裏寫圖片描述

注意看這個SENet的紅色部分都是用卷積操作代替文中的全連接層操作實現的,本質上沒有什麼區別。具體來說,inception_3a_11_down是輸出channel爲16的11卷積,其輸入channel是256,這也符合文中說的縮減因子爲16(256/16=16);而inception_3a_11_up是輸出channel爲256的11卷積。其它層都和文中描述一致,比如inception_3a_global_pool是average pooling,inception_3a_prob是sigmoid函數。

SE-ResNet-50的情況也類似,如下圖。在ResNet中都是在Residual block中嵌入SENet。下圖最左邊的長條連線是原來Residual block的skip connection,右下角的conv2_2_global_pool到conv2_2_prob以及左邊那條連線都是SENet。不過也是用兩個1*1卷積代替文中的兩個全連接層。

這裏寫圖片描述

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