近年熱門分類CNN網絡結構的總結

總結的網絡結構有:LeNetAlexNetZF-NetVGG谷歌系列 :Inception v1到v4ResnetResnetXtSeNetDenseNetDPN

LeNet

創新點:定義了CNN的基本組件,是CNN的鼻祖。

LeNet是卷積神經網絡的祖師爺LeCun在1998年提出,用於解決手寫數字識別的視覺任務。自那時起,CNN的最基本的架構就定下來了:卷積層、池化層、全連接層。

網絡結構:
在這裏插入圖片描述
在這裏插入圖片描述

LaNet-5的侷限性
CNN能夠得出原始圖像的有效表徵,這使得CNN能夠直接從原始像素中,經過極少的預處理,識別視覺上面的規律。然而,由於當時缺乏大規模訓練數據,計算機的計算能力也跟不上,LeNet-5 對於複雜問題的處理結果並不理想。


AlexNet

2012年,Imagenet比賽冠軍的model,作者是Alex,Hinton的學生

論文鏈接

參考:
在AlexNet中LRN 局部響應歸一化的理解
tf.nn.conv3d和tf.nn.max_pool3d這兩個tensorflow函數的功能和參數
Tensorflow的LRN是怎麼做的
1D,2D,3D卷積的區別
3d卷積是如何計算的


創新點:

(1)成功使用ReLU作爲CNN的激活函數,並驗證其效果在較深的網絡超過了Sigmoid,成功解決了Sigmoid在網絡較深時的梯度彌散問題。雖然ReLU激活函數在很久之前就被提出了,但是直到AlexNet的出現纔將其發揚光大。

(2)訓練時使用Dropout隨機忽略一部分神經元,以避免模型過擬合。Dropout雖有單獨的論文論述,但是AlexNet將其實用化,通過實踐證實了它的效果。在AlexNet中主要是最後幾個全連接層使用了Dropout。

(3)在CNN中使用重疊的最大池化(相鄰池化窗口之間會有重疊區域,此時kernel size>stride)。此前CNN中普遍使用平均池化,AlexNet全部使用最大池化,避免平均池化的模糊化效果。並且AlexNet中提出讓步長比池化核的尺寸小,這樣池化層的輸出之間會有重疊和覆蓋,提升了特徵的豐富性。

網絡結構:
在這裏插入圖片描述

AlexNet將LeNet的思想發揚光大,把CNN的基本原理應用到了很深很寬的網絡中。說實話,這個model的意義比後面那些model都大很多,首先它證明了CNN在複雜模型下的有效性,然後GPU實現使得訓練在可接受的時間範圍內得到結果,確實讓CNN和GPU都大火了一把,順便推動了有監督DL的發展。

關於爲什麼使用max pooling的理解:

池化的兩種常見誤差歸納如下:
(1)鄰域大小受限造成的估計值方差增大;(2)卷積層參數誤差造成估計均值的偏移。
一般來說,mean-pooling能減小第一種誤差,更多的保留圖像的背景信息;max-pooling能減小第二種誤差,更多的保留紋理信息。
邊緣檢測,就是因爲邊緣信息跟背景信息差別大,所以才能檢測。max-pooling就是保留了最明顯的信息。mean-pooling因爲平均考慮,所以背景信息也保留了,所以肯定會丟失信息。

使用實驗證明:

  • 重疊池化:其他的設置都不變的情況下, top-1和top-5 的錯誤率分別減少了0.4% 和0.3%。

(4)提出了LRN層,對局部神經元的活動創建競爭機制,使得其中響應比較大的值變得相對更大,並抑制其他反饋較小的神經元,增強了模型的泛化能力。

LRN全稱是local response normalization,局部響應歸一化。

LRN的動機是 對於圖像中的每個位置來說,我們可能並不需要太多的高激活神經元。但是後來,很多研究者發現 LRN 起不到太大作用,因爲並不重要,而且我們現在並不用 LRN 來訓練網絡。

與BN的區別:
BN歸一化主要發生在不同的樣本之間,LRN歸一化主要發生在不同的卷積核的輸出之間。
在這裏插入圖片描述

公式:
在這裏插入圖片描述
其次,官方API的介紹是這樣的:

	sqr_sum[a, b, c, d] = sum(input[a,b, c, d - depth_radius : d + depth_radius + 1] ** 2)
	output = input / (bias +alpha * sqr_sum) ** beta

以alexnet的論文爲例,輸入暫且定爲 [batch_size, 224, 224, 96],這裏224×224是圖片的大小,經過第一次卷積再經過ReLU,就是LRN函數的輸入。

注意上面API說明裏的sum函數,意思就是,可能解釋起來比較拗口,針對batch裏每一個圖的後3維向量,[224, 224, d - depth_radius : d + depth_radius + 1],對它按照半徑 depth_radius求每個圖裏的每個像素的平方,再把這2× depth_radius+1個平方過後的圖片加起來,就得到了這個batch的sqr_sum。

LRN的Pytorch代碼:

	class LRN(nn.Module):
    '''
    這個網絡貌似後續被其它正則化手段代替,如dropout、batch normalization等。
    目前該網絡基本上很少使用了,這裏爲了原生的AlexNet而實現
    '''
	    def __init__(self, local_size=1, alpha=1.0, beta=0.75, ACROSS_CHANNELS=False):
	        super(LRN, self).__init__()
	        self.ACROSS_CHANNELS = ACROSS_CHANNELS
	        if self.ACROSS_CHANNELS:
	            self.average=nn.AvgPool3d(kernel_size=(local_size, 1, 1), #0.2.0_4會報錯,需要在最新的分支上AvgPool3d纔有padding參數
	                    stride=1,
	                    padding=(int((local_size-1.0)/2), 0, 0)) 
	        else:
	            self.average=nn.AvgPool2d(kernel_size=local_size,
	                    stride=1,
	                    padding=int((local_size-1.0)/2))
	        self.alpha = alpha
	        self.beta = beta	    
	        
	    def forward(self, x):
	        if self.ACROSS_CHANNELS:
	            div = x.pow(2).unsqueeze(1)
	            div = self.average(div).squeeze(1)
	            div = div.mul(self.alpha).add(1.0).pow(self.beta)#這裏的1.0即爲bias
	        else:
	            div = x.pow(2)
	            div = self.average(div)
	            div = div.mul(self.alpha).add(1.0).pow(self.beta)
	        x = x.div(div)
	        return x

我對公式的理解:x、y指的是固定的同一層同一位置width和height的值,i指的是第i層,公式只對第四維channal操作,depth_radius是可選的特徵圖範圍,也就是對同一層同一位置不同的特徵圖的信息做累加操作。
代碼中ACROSS_CHANNELS是否跨通道,使用3d的池化,也就是在第二維多了一個depth維度,3d一般用來處理視頻,考慮時間維度的信息,多出來的維度是幀數。


ZF-Net

2013 ImageNet分類任務的冠軍,其網絡結構較AlexNet沒什麼改進,只是調了調參,性能較AlexNet提升了不少。
ZF-Net只是將AlexNet第一層卷積核由11變成7,步長由4變爲2,第3,4,5卷積層轉變爲384,384,256。

創新點:

使用了更小的卷積核

在這裏插入圖片描述


VGG

論文鏈接
參考博客:VGG模型核心拆解VGGNet網絡結構

牛津大學計算機視覺組和DeepMind公司共同研發一種深度卷積網絡,在ImageNet 2014年比賽上獲得了分類項目的第二名,GoogleNet是第一名。

創新點:

  • 全部使用更小的3*3卷積核,探索以堆疊小尺寸卷積核的方式來替代大尺寸卷積核,加深網絡。

  • 預訓練(pre-trained)技巧。訓練時,先訓練級別簡單(層數較淺)的VGGNet的A級網絡,然後使用A網絡的權重來初始化後面的複雜模型,加快訓練的收斂速度。

  • 採用了Multi-Scale的方法來針對訓練和預測做數據增強。

VGGNet使用了Multi-Scale的方法做數據增強,將原始圖像縮放到不同尺寸S,然後再隨機裁切,這樣能增加很多數據量,對於防止模型過擬合有很不錯的效果。實踐中,作者令S在[256,512]這個區間內取值,使用Multi-Scale獲得多個版本的數據,並將多個版本的數據合在一起進行訓練。

  • 實驗證明了LRN層無性能增益(A和A-LRN)。LRN是一種跨通道去normalize像素值的方法。

爲什麼使用3 * 3卷積來代替7 * 7或5 * 5卷積?

  • 非線性操作更多,學習特徵的能力更強。因爲如果使用的都是線性操作,相當於整個網絡都在做同樣的事情,至是單純地把參數加倍,加多少層都是一樣的效果。非線性函數可以更好的擬合複雜的函數。
  • 參數量更少。

感受野的計算:

	假設輸入i*i
	3*3卷積:
	    第一次     (i-3)/1+1 = i-2
	    第二次     (i-2-3)/1+1 = i-4
	    第三次     (i-4-3)/1+1 = i-6
	5*5卷積:    (i-5)/1+1 = i-4
	7*7卷積:    (i-7)/1+1 = i-6

可以看出:兩個 3 * 3 卷積層的串聯相當於1個 5 * 5 的卷積層,3個 3 * 3 的卷積層串聯相當於1個 7 * 7 的卷積層,即3個 3 * 3 卷積層的感受野大小相當於1個 7 * 7 的卷積層。

參數的計算 :

		對於33*3卷積,(C * C * 3 * 3) *3= 27C^2 
		對於17*7卷積,(C * C * 7 * 7) = 49C^233*3卷積的參數量小於17*7卷積

        對於23*3卷積,(C * C * 3 * 3) *2= 18C^2 
        對於15*5卷積,(C * C * 5 * 5) = 25C^223*3卷積的參數量小於15*5卷積

網絡結構
在這裏插入圖片描述


谷歌系列 :Inception v1到v4

Paper列表:

[v1] Going Deeper with Convolutions, 6.67% test error, 2014
[v2] Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift, 4.8% test error, 2015
[v3] Rethinking the Inception Architecture for Computer Vision, 3.5% test error,2015
[v4] Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning, 3.08% test error,2016

大體思路:引用自博客

  • Inception v1的網絡,將1x1,3x3,5x5的conv和3x3的pooling,stack在一起,一方面增加了網絡的width,另一方面增加了網絡對尺度的適應性;
  • v2的網絡在v1的基礎上,進行了改進,一方面了加入了BN層,減少了Internal - Covariate Shift(內部neuron的數據分佈發生變化),使每一層的輸出都規範化到一個N(0, 1)的高斯,另外一方面學習VGG用2個3x3的conv替代inception模塊中的5x5,既降低了參數數量,也加速計算;
  • v3一個最重要的改進是分解(Factorization),將7x7分解成兩個一維的卷積(1x7,7x1),3x3也是一樣(1x3,3x1),這樣的好處,既可以加速計算(多餘的計算能力可以用來加深網絡),又可以將1個conv拆成2個conv,使得網絡深度進一步增加,增加了網絡的非線性,還有值得注意的地方是網絡輸入從224x224變爲了299x299,更加精細設計了35x35/17x17/8x8的模塊;
  • v4研究了Inception模塊結合Residual Connection能不能有改進,發現ResNet的結構可以極大地加速訓練,同時性能也有提升,主要目的是提升速度;同時將卷積層堆疊順序(1x1,3x3)變成 (3x3, 1x1)。

GoogLeNet(即Inception V1)

之所以是GoogLeNet而非GoogleNet,文章說是爲了向早期的LeNet致敬。

論文鏈接
GoogLeNet系列解讀
GoogleNet系列論文學習

在ImageNet2014和VGG競爭的第一名,這兩個網絡的大體思路都是一致的:go deeper。不同的是GoogleNet提出了Inception結構,往寬度探索,ImageNet主要還是在AlexNet結構上探索。

創新點:

  • 引入Inception結構
  • 中間層的輔助LOSS單元
  • 後面的全連接層全部替換爲簡單的全局平均池化(GAP)

網絡結構
在這裏插入圖片描述

Inception結構
在這裏插入圖片描述
對上圖做以下說明:

1 . 採用不同大小的卷積核意味着不同大小的感受野,最後拼接意味着不同尺度特徵的融合;
2 . 之所以卷積核大小採用1、3和5,主要是爲了方便對齊。設定卷積步長stride=1之後,只要分別設定pad=0、1、2,那麼卷積之後便可以得到相同維度的特徵,然後這些特徵就可以直接拼接在一起了;
3 . 文章說很多地方都表明pooling挺有效,所以Inception裏面也嵌入了;
4 . 網絡越到後面,特徵越抽象,而且每個特徵所涉及的感受野也更大了,因此隨着層數的增加,3x3和5x5卷積的比例也要增加。

改進版本:使用1 * 1卷積降維
在這裏插入圖片描述
全連接層一般是用來做分類,後接softmax等激活函數來輸出分類的概率。
全局平均池化(GAP)來替代全連接層,原因是:對每個通道的feature map降維,尺寸降爲1 * 1,既能實現全連接層的功能,又能避免全連接層的參數量過大、過擬合的問題。
Global Average Pooling全局平均池化的一點理解關於 global average pooling

BN-GoogLeNet(即BN-Inception、Inception V2)

參考博客:
1.《Batch Normalization Accelerating Deep Network Training by Reducing Internal Covariate Shift》閱讀筆記與實現
2.從白化到BN、計算過程、求導過程
改進:

  • 使用BN層,這樣做的好處是:
    ① 允許使用更高的學習速率並且不太關心初始化,加快訓練速度。如果每層的scale不一致,實際上每層需要的學習率是不一樣的,同一層不同維度的scale往往也需要不同大小的學習率,通常需要使用最小的那個學習率才能保證損失函數有效下降,Batch Normalization將每層、每維的scale保持一致,那麼我們就可以直接使用較高的學習率進行優化。
    ② 訓練深度神經網絡的複雜性在於,每層輸入的分佈在訓練過程中會發生變化,因爲前面的層的參數會發生變化。BN使每一層的輸出都規範化到一個N(0, 1)的高斯,減輕了Internal Covariate Shift。
  • 使用兩個3 * 3卷積模塊代替一個5 * 5(學習VGG),降低參數數量,加速計算。
  • 移除或使用較低的dropout。 dropout是常用的防止overfitting的方法,而導致overfit的位置往往在數據邊界處,如果初始化權重就已經落在數據內部,overfit現象就可以得到一定的緩解。論文中最後的模型分別使用10%、5%和0%的dropout訓練模型,與之前的40%-50%相比,可以大大提高訓練速度。
  • 降低L2權重衰減係數。 還是一樣的問題,邊界處的局部最優往往有幾維的權重(斜率)較大,使用L2衰減可以緩解這一問題,現在用了Batch Normalization,就可以把這個值降低了,論文中降低爲原來的5倍。
  • 取消Local Response Normalization層。 由於使用了一種Normalization,再使用LRN就顯得沒那麼必要了。而且LRN實際上也沒那麼work。

Inception V3

參考博客
改進:

  • 重大改進:使用分解卷積(Factorizing into smaller convolution) ,例如1 * 7、7 * 1 代替 7 * 7Conv,多餘的計算能力可以多設1 * 1卷積來加深網絡,增強非線性。
  • 優化方式選擇RMSProp,需要求參數的二階導。
    在這裏插入圖片描述
  • label smoothing
    在這裏插入圖片描述
new_labels = (1.0 - label_smoothing) * one_hot_labels + label_smoothing / num_classes

在網絡實現的時候,令 label_smoothing = 0.1,num_classes = 1000。Label smooth提高了網絡精度0.2%。

我對label smoothing理解是這樣的,它把原來很突兀的one_hot_labels稍微的平滑了一點,槍打了出頭鳥,削了立於雞羣那隻鶴的腦袋,分了點身高給雞們,避免了網絡過度學習labels而產生的弊端。

  • bn-auxiliary classifier
    引入了附加分類器,其目的是從而加快收斂。輔助分類器其實起着着regularizer的作用。當輔助分類器使用了batch-normalized或dropout時,主分類器效果會更好。
    1. 輸入:3 * 299 * 299
	
	############################## 輸入處理 ###############################
	# (Basic Conv Model:Conv2d->bn->relu)                                                
	######################################################################
    2. Basic_Conv_Model: 32 * 149 *149 (k=3,s=23. Basic_Conv Model: 32 * 147 *147 (k=34. Basic_Conv_Model: 64 * 147 *147 (k=3,p=15. max_pool :64 * 73 * 73 (k=3,s=26. Basic_Conv_Model: 80 *  73 * 73 (k=17. Basic_Conv_Model: 192 * 71 * 71 (k=38. max_pool :192 * 35 * 35 (k=3,s=2############################## InceptionA ###############################
	# branch1: 1 * 1 Conv  
	# branch2: 1 * 1 Conv -> 5 * 5 Conv (p=2)
	# branch3: 1 * 1 Conv -> 3 * 3 Conv (p=1)   -> 3 * 3 Conv (p=1)  
	# branch4: avg_pool(k=3,p=1) -> 1 * 1 Conv                                         
	######################################################################
    9. 256 * 35 * 35 
    10.  288 * 35 * 35 
    11.  288 * 35 * 35 

    ############################## InceptionB ##############################
	# branch1: 3 * 3 Conv  (s=2)
	# branch2: 1 * 1 Conv -> 3 * 3 Conv (p=1)   -> 3 * 3 Conv (s=2)  
	# branch3: max_pool(k=3,s=2)                                    
	######################################################################
    12. 768 * 17 * 17
    
    ############################## InceptionC ##############################
	# branch1: 1 * 1 Conv  
	# branch2: 1 * 1 Conv -> 1 * 7 Conv (p=(0,3))  -> 7 * 1 Conv (p=(3,0))  
	# branch3: 1 * 1 Conv -> 7 * 1 Conv (p=(3,0))  -> 1 * 7 Conv (p=(0,3)) 
	#          -> 7 * 1 Conv (p=(3,0)) -> 1 * 7 Conv (p=(0,3))       
	# branch4: avg_pool(k=3,p=1) -> 1 * 1 Conv                          
	######################################################################
    13.  768 * 17 * 17
    14.  768 * 17 * 17
    15.  768 * 17 * 17
    16.  768 * 17 * 17
 
    ############################## InceptionD ##############################
	# branch1: 1 * 1 Conv -> 3 * 3 Conv(s=2)
	# branch2: 1 * 1 Conv -> 1 * 7 Conv (p=(0,3))->7 * 1 Conv(p=(3,0))  
	#          -> 3 * 3 Conv(s=2)
	# branch3: 1 * 1 Conv -> 7 * 1 Conv (p=(3,0))  -> 1 * 7 Conv (p=(0,3)) 
	#               -> 7 * 1 Conv (p=(3,0)) -> 1 * 7 Conv (p=(0,3))       
	# branch4: max_pool(k=3,s=2)                  
	######################################################################
    17. 1280 * 8 * 8
  
    ############################## InceptionE ##############################
	# branch1: 1 * 1 Conv  
	# 1 * 1 Conv的參數共享  
	# branch2_1: 1 * 1 Conv -> 1 * 3 Conv (p=(0,3)) 
	# branch2_2: 1 * 1 Conv -> 3 * 1 Conv (p=(3,0))  
	# 1 * 1 、3 * 3 Conv的參數共享    
	# branch3_1: 1 * 1 Conv -> 3 * 3 Conv (p=1) -> 1 * 3 Conv (p=(0,3)) 
	# branch3_2: 1 * 1 Conv -> 3 * 3 Conv (p=1) -> 3 * 1 Conv (p=(3,0))  ,     
	# branch4: avg_pool(k=3,p=1) -> 1 * 1 Conv                          
	######################################################################
    18. 2048 * 8 * 8
    19. 2048 * 8 * 8
  
    # 輸出處理
    20. avg pool :2048 * 1 * 1 (k=821. dropout : 2048 * 1 * 1 
    22. flatten :2048 
    23. fc:  num_class

Inception V4

網絡結構圖
16年提出,受到15年resnet的啓發。
inception v4實際上是把原來的inception v3加上了resnet的方法,從一個節點能夠跳過一些節點直接連入之後的一些節點,並且殘差也跟着過去一個。
另外就是V4把一個先1 * 1再3 * 3那步換成了先3 * 3再1 * 1.
論文說引入resnet不是用來提高深度,進而提高準確度的,只是用來提高速度的。


Resnet

論文鏈接
作者何凱明,ImageNet 2015比賽classification任務上獲得第一名。

問題引出:

退化問題。隨着網絡的加深,出現了訓練集準確率下降的現象,我們可以確定這不是由於Overfit造成的(過擬合的情況訓練集應該準確率很高);所以作者針對這個問題提出了一種全新的網絡,叫深度殘差網絡,它允許網絡儘可能的加深,其中引入了全新的結構。
在這裏插入圖片描述

殘差指的是什麼?

其中ResNet提出了兩種mapping:一種是identity mapping,指的就是圖1中”彎彎的曲線”,另一種residual mapping(18、34使用basicblock,50、101、152使用bottleneck),指的就是除了”彎彎的曲線“那部分,所以最後的輸出是y=F(x)+shortcut(x),最大的優勢就是既能避免梯度消失、梯度爆炸又不增加額外的複雜度。identity mapping顧名思義,就是指本身,也就是公式中的x,而residual mapping指的是“差”,也就是y−x,所以殘差指的就是F(x)部分。shortcut是在F(x)和x維度不匹配時使用,使用1 * 1卷積來統一維度。

於是通過VGG19設計出了plain 網絡和殘差網絡,如下圖中部和右側網絡。然後利用這兩種網絡進行實驗對比。
在這裏插入圖片描述

論文中討論了多張shortcut的形式,最後發現a的效果好。
在這裏插入圖片描述

ResnetXt

論文:Aggregated Residual Transformations for Deep Neural Networks Saining
參考博客:ResnetXt算法詳解
Resnet的變體,ImageNet 2016的第二名,出自論文“Aggregated Residual Transformations for Deep Neural Networks”,主要是將殘差塊的中間的 3x3卷積層變成group卷積,同時擴大了3x3卷積的輸入輸出通道數,使得在與對應的ResNet網絡的計算量和參數個數相近的同時提高網絡的性能。值得一提的是,ResNeXt與常用的ResNet對應的層數完全相同,都是50、101、152層。ResNeXt已經被很多網絡用來當作backbone,例如Mask RCNN中除了使用ResNet,也嘗試使用了ResNeXt-101和ResNeXt-152。

解釋cardinality:
原文的解釋是the size of the set of transformations,如下圖(左Resnet,右ResnetXt)右邊是 cardinality=32 ,這裏注意每個被聚合的拓撲結構都是一樣的(這也是和 Inception 的差別,減輕設計負擔)
在這裏插入圖片描述
參數量對比:

   #Resnet
   256*1*1*64+64*3*3*64+64*1*1*256 = 69632
   #ResnetXt
   (256*1*1*4+4*3*3*4+4*1*1*256)*32 = 70144

可見參數量差不多,網絡寬度卻增加了不少。

作者提出 ResNeXt 的主要原因在於:傳統的要提高模型的準確率,都是加深或加寬網絡,但是隨着超參數數量的增加(比如channels數,filter size等等),網絡設計的難度和計算開銷也會增加。因此本文提出的 ResNeXt 結構可以在不增加參數複雜度的前提下提高準確率,同時還減少了超參數的數量。

附上原文比較核心的一句話,點明瞭增加 cardinality 比增加深度和寬度更有效:
在這裏插入圖片描述

當然還有一些數據證明 ResNeXt 網絡的優越性,例如原文中的這句話:In particular, a 101-layer ResNeXt is able to achieve better accuracy than ResNet-200 but has only 50% complexity.

下圖列舉了 ResNet-50 和 ResNeXt-50 的內部結構,最後兩行說明二者之間的參數量差別不大。
在這裏插入圖片描述


SeNet

論文:Squeeze-and-Excitation Networks
參考博客: SeNet算法筆記

ImageNet 2017第一名, Momenta (自動駕駛公司) 胡杰。
在這裏插入圖片描述

問題引出:
卷積神經網絡建立在卷積運算的基礎上,通過融合局部感受野內的空間信息和通道信息來提取信息特徵。爲了提高網絡的代表性能力,許多現有工作已經顯示出 增強空間編碼 的好處。我們的目標是確保能夠 提高網絡對信息特徵的敏感度 ,以便後續轉換可以利用這些功能,並抑制不太有用的功能。我們建議通過顯式建模 通道依賴性 來實現這一點,以便在進入下一個轉換之前通過兩步重新校準濾波器響應。

貢獻:

  • 引入“擠壓和激勵模塊”(Squeeze-and-Excitation):通過顯示的對卷積層特徵之間的通道相關性進行建模來提升模型的表徵能力;
  • 提出了特徵重校準機制:通過使用全局信息去選擇性的增強可信息化的特徵並同時壓縮那些無用的特徵。
    def forward(self, x):
        out = F.relu(self.bn1(x))
        #維度對齊
        shortcut = self.shortcut(out) if hasattr(self, 'shortcut') else x
        out = self.conv1(out)
        out = self.conv2(F.relu(self.bn2(out)))

        # Squeeze
        w = F.avg_pool2d(out, out.size(2))
        w = F.relu(self.fc1(w))
        w = F.sigmoid(self.fc2(w))
        # Excitation
        out = out * w

        out += shortcut
        return out
  • 解釋Squeeze操作:
    網絡較低的層次其感受野尺寸很小(一般做1 * 1Conv來解決維度不匹配),Squeeze操作順着空間維度來進行特徵壓縮(平均池化,將feature map的尺寸壓縮爲1 * 1),將每個二維的特徵通道變成一個實數,這個實數某種程度上具有全局的感受野,並且輸出的維度和輸入的特徵通道數相匹配。它表徵着在特徵通道上響應的全局分佈,而且使得靠近輸入的層也可以獲得全局的感受野。

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

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

在實際網絡中怎麼添加SE模塊?
Figure2是在Inception中加入SE block的情況。在這裏插入圖片描述
Figure3是在ResNet中添加SE block的情況。
在這裏插入圖片描述
這兩個全連接層的作用就是融合各通道的feature map信息,因爲前面的squeeze都是在某個channel的feature map裏面操作。


DenseNet

這篇文章是 CVPR 2017的oral論文

參考AI之路的博客
論文:Densely Connected Convolutional Networks
原作者的一些解釋


最近的研究表明,想要訓練一個更深更準確的網絡,讓靠近輸入的層和靠近輸出的層之間有更短的連接是有效的。

優點:

  • 緩解梯度消失 。這個思想是基於ResNet的,DenseNet中的每一層可以直接接觸到原始輸入並且能接觸到損失拿到梯度。
  • 正則化效果。論文中提出Composite function,包含BN->Relu->Conv
  • 特徵重用。減少特徵圖的數量,使網絡更narrow,參數更少, 因此能夠更深,效果比ResNet好。
  • 抗過擬合性。在CIFAR的數據集上做過實驗,卷積每一層特徵的提取都相當於對輸入做非線性變換,而DenseNet匯聚了淺層特徵的特點,有更好的泛化性。
    在這裏插入圖片描述

傳統的神經網絡L層就會有L個連接,但是在DenseNet中,會有L(L+1)/2個連接,改動最大的地方是在block結構中,ResNet將輸入block 的部分和輸出結果做累加,而DenseNet直接將兩者concat起來,所以叫做密集連接。

以下兩個公式能說明兩者的不同:
ResNet在這裏插入圖片描述, Densenet在這裏插入圖片描述

以下是一個layer的示例圖:
在這裏插入圖片描述
在這裏插入圖片描述

網絡結構設置
在這裏插入圖片描述
其中growth rate(即k)是卷積核個數變換的基數。

文章同時提出了DenseNet`,DenseNet-B,DenseNet-BC,三種結構,具體區別如下:

  • 原始DenseNet:

Dense Block模塊:BN+Relu+Conv(3*3)+dropout

transition layer模塊:BN+Relu+Conv(11)(filternum:m)+dropout+Pooling(22)

  • DenseNet-B:

Dense Block模塊:BN+Relu+Conv(11)(filternum:4K)+dropout+BN+Relu+Conv(33)+dropout

transition layer模塊:BN+Relu+Conv(11)(filternum:m)+dropout+Pooling(22)

  • DenseNet-BC:

Dense Block模塊:BN+Relu+Conv(11)(filternum:4K)+dropout+BN+Relu+Conv(33)+dropout

transition layer模塊:BN+Relu+Conv(11)(filternum:θm,其中0<θ<1,文章取θ=0.5)+dropout+Pooling(22)

其中,DenseNet-B在原始DenseNet的基礎上,在Dense Block模塊中加入了1*1卷積,使得將每一個layer輸入的feature map都降爲到4k的維度,大大的減少了計算量。

DenseNet-BC在DenseNet-B的基礎上,在transitionlayer模塊中加入了壓縮率θ參數,論文中將θ設置爲0.5,這樣通過1*1卷積,將上一個Dense Block模塊的輸出feature map維度減少一半。

反正無腦用DenseNet-BC就行了

訓練細節:
使用隨機梯度下降(SGD)訓練所有網絡。

  • 在CIFAR和SVHN上,我們使用批量訓練大小爲64,分別訓練300和40個時期。 最初的學習率設定爲0.1,並且在訓練時期總數的50%和75%時除以10。
  • 在ImageNet上,我們訓練90個時期的模型,批量大小爲256。學習率最初設定爲0.1,並在epoch 30和60時除以10。

DPN

論文:Dual Path Networks,CVPR 2017
參考博客:DPN(Dual Path Network)算法詳解

優點:
1、關於模型複雜度,作者的原文是這麼說的:The DPN-92 costs about 15% fewer parameters than ResNeXt-101 (32 4d), while the DPN-98 costs about 26% fewer parameters than ResNeXt-101 (64 4d).
2、關於計算複雜度,作者的原文是這麼說的:DPN-92 consumes about 19% less FLOPs than ResNeXt-101(32 4d), and the DPN-98 consumes about 25% less FLOPs than ResNeXt-101(64 4d).
在這裏插入圖片描述

class Bottleneck(nn.Module):
    def __init__(self, last_planes, in_planes, out_planes, dense_depth, stride, first_layer):
        super(Bottleneck, self).__init__()
        self.out_planes = out_planes
        self.dense_depth = dense_depth

        self.conv1 = nn.Conv2d(last_planes, in_planes, kernel_size=1, bias=False)
        self.bn1 = nn.BatchNorm2d(in_planes)
        self.conv2 = nn.Conv2d(in_planes, in_planes, kernel_size=3, stride=stride, padding=1, groups=32, bias=False)
        self.bn2 = nn.BatchNorm2d(in_planes)
        self.conv3 = nn.Conv2d(in_planes, out_planes+dense_depth, kernel_size=1, bias=False)
        self.bn3 = nn.BatchNorm2d(out_planes+dense_depth)

        self.shortcut = nn.Sequential()
        if first_layer:
            self.shortcut = nn.Sequential(
                nn.Conv2d(last_planes, out_planes+dense_depth, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(out_planes+dense_depth)
            )

    def forward(self, x): #假設輸入x維度(3,32,32)
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.layer1(out) #320*32*32(out_plane+(num_block+1)*dense_depth)
        out = self.layer2(out) #672*16*16
        out = self.layer3(out) #1528*8*8
        out = self.layer4(out) #2560*4*4
        out = F.avg_pool2d(out, 4)
        out = out.view(out.size(0), -1)
        out = self.linear(out)
        return out

大體的思路是:bottleneck的一條路線學習Resnet的shortcut,對x做維度對齊;一條路線學DenseNet,通過堆疊卷積模塊1 * 1 conv->bn->relu->3 * 3 conv->bn->relu->1 * 1 conv->bn來擴大感受野,最後彙總兩條路線的輸出做concat,一層包含num_blocks個bottleneck,每層的輸出通道數爲out_plane+(num_block+1)*dense_depth

有一個細節,3*3的卷積採用的是group操作,類似ResNeXt。

解釋 group conv

我們假設上一層的輸出feature map有N個,即通道數channel=N,也就是說上一層有N個卷積核。再假設羣卷積的羣數目M。那麼該羣卷積層的操作就是,先將channel分成M份。每一個group對應N/Mchannel,與之獨立連接。然後各個group卷積完成後將輸出疊在一起(concatenate),作爲這一層的輸出channel。這一操作適用於多GPU並行。

實驗結果:
在這裏插入圖片描述
在這裏插入圖片描述
Figure 3,關於訓練速度和存儲空間的對比。現在對於模型的改進,可能準確率方面的提升已經很難作爲明顯的創新點,因爲幅度都不大,因此大部分還是在模型大小計算複雜度上優化,同時只要準確率還能提高一點就算進步了。


後續閱讀路線

MobileNetV2
在這裏插入圖片描述


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