論文:密集連接卷積網(wǎng)絡(luò)?
論文鏈接:https://arxiv.org/pdf/1608.06993.pdf?
代碼的github鏈接:https://github.com/liuzhuang13/DenseNet?
MXNet版本代碼(有ImageNet預(yù)訓(xùn)練模型):https:? //github.com/miraclewkf/DenseNet
文章詳解:?
DenseNet(密集卷積網(wǎng)絡(luò))主要還是和ResNet及Inception網(wǎng)絡(luò)做對(duì)比,思想上有借鑒,但卻是全新的結(jié)構(gòu),網(wǎng)絡(luò)結(jié)構(gòu)并不復(fù)雜,卻非常有效值!眾所周知,最近一兩年卷積神經(jīng)網(wǎng)絡(luò)提高效果的方向,要么深(比如RESNET,解決了網(wǎng)絡(luò)深時(shí)候的梯度消失問題),要么寬(比如GoogleNet的盜夢空間),而作者則是從功能入手,通過對(duì)功能的極致利用達(dá)到更好的效果和更少的參數(shù)。先列下DenseNet的幾個(gè)優(yōu)點(diǎn),感受下它的強(qiáng)大:?
1,減輕了消失梯度(梯度消失)?
2,加強(qiáng)了特征的傳遞?
3,更有效地利用了特征?
4,一定程度上較少了參數(shù)數(shù)量
在保證網(wǎng)絡(luò)中層與層之間最大程度的信息傳輸?shù)那疤嵯?,直接將所有層連接起來!
先放一個(gè)密塊的結(jié)構(gòu)圖。在傳統(tǒng)的卷積神經(jīng)網(wǎng)絡(luò)中,如果你有L層,那么就會(huì)有L個(gè)連接,但是在DenseNet中,會(huì)有L(L + 1)/ 2個(gè)連接。。簡單講,每就是一層的輸入側(cè)來自前面所有層的輸出如下圖產(chǎn)品:X0是輸入,H1的輸入是X0(輸入),H2的輸入是X0和X1(X1是H1的輸出)......
二、網(wǎng)絡(luò)結(jié)構(gòu)
1. 緊密連接(Dense connectivity)
在DenseNet結(jié)構(gòu)中,講每一層的輸出都導(dǎo)入后面的所有層,與ResNet的相加不同的是,DenseNet結(jié)構(gòu)使用的是連結(jié)結(jié)構(gòu)(concatenate)。這樣的結(jié)構(gòu)可以減少網(wǎng)絡(luò)參數(shù),避免ResNet中可能出現(xiàn)的缺點(diǎn)(例如某些層被選擇性丟棄,信息阻塞等)。
2. 組成函數(shù)(Composite function)
Batch Normalization + ReLU + 3*3 Conv層
3. 過渡層(Transition Layer)
過渡層包含瓶頸層(bottleneck layer,即1*1卷積層)和池化層。
1)瓶頸層
1*1的卷積層用于壓縮參數(shù)。每一層輸出k個(gè)feature maps,理論上將每個(gè)Dense Block輸出為4k個(gè)feature maps,然而實(shí)際情況中會(huì)大于這個(gè)數(shù)字。卷積層的作用是將一個(gè)Dense Block的參數(shù)壓縮到4k個(gè)。
2)池化層
由于采用了Dense Connectivity結(jié)構(gòu),直接在各個(gè)層之間加入池化層是不可行的,因此采用的是Dense Block組合的方式,在各個(gè)Dense Block之間加入卷積層和池化層。
4. 增長率(Growth rate)
這里的增長率代表的是每一層輸出的feature maps的厚度。ResNet,GoogleNet等網(wǎng)絡(luò)結(jié)構(gòu)中經(jīng)常能見到輸出厚度為上百個(gè),其目的主要是為了提取不同的特征。但是由于DenseNet中每一層都能直接為后面網(wǎng)絡(luò)所用,所以k被限制在一個(gè)很小的數(shù)值。
5. 壓縮(Compression)
跟1*1卷積層作用類似,壓縮參數(shù)。作者選擇壓縮率(theta)為0.5。
包含bottleneck layer的叫DenseNet-B,包含壓縮層的叫DenseNet-C,兩者都包含的叫DenseNet-BC。
DenseNet的一個(gè)優(yōu)點(diǎn)是網(wǎng)絡(luò)更窄,參數(shù)更少,很大一部分原因得益于這種密
另外作者還觀察到這種dense connection有正則化的效果,因此對(duì)于過擬合有一定的抑制作用,博主認(rèn)為是因?yàn)閰?shù)減少了(后面會(huì)介紹為什么參數(shù)會(huì)減少),所以過擬合現(xiàn)象減輕。
文章中只有兩個(gè)公式,是用來闡述DenseNet和ResNet的關(guān)系,對(duì)于從原理上理解這兩個(gè)網(wǎng)絡(luò)還是非常重要的。
第一個(gè)公式是ResNet的。這里的l表示層,xl表示l層的輸出,Hl表示一個(gè)非線性變換。所以對(duì)于ResNet而言,l層的輸出是l-1層的輸出加上對(duì)l-1層輸出的非線性變換。

第二個(gè)公式是DenseNet的。[x0,x1,…,xl-1]表示將0到l-1層的輸出feature map做concatenation。concatenation是做通道的合并,就像Inception那樣。而前面resnet是做值的相加,通道數(shù)是不變的。Hl包括BN,ReLU和3*3的卷積。

所以從這兩個(gè)公式就能看出DenseNet和ResNet在本質(zhì)上的區(qū)別,太精辟。
前面的Figure 1表示的是dense block,而下面的Figure 2表示的則是一個(gè)DenseNet的結(jié)構(gòu)圖,在這個(gè)結(jié)構(gòu)圖中包含了3個(gè)dense block。作者將DenseNet分成多個(gè)dense block,原因是希望各個(gè)dense block內(nèi)的feature map的size統(tǒng)一,這樣在做concatenation就不會(huì)有size的問題。
這個(gè)Table1就是整個(gè)網(wǎng)絡(luò)的結(jié)構(gòu)圖。這個(gè)表中的k=32,k=48中的k是growth rate,表示每個(gè)dense block中每層輸出的feature map個(gè)數(shù)。為了避免網(wǎng)絡(luò)變得很寬,作者都是采用較小的k,比如32這樣,作者的實(shí)驗(yàn)也表明小的k可以有更好的效果。根據(jù)dense block的設(shè)計(jì),后面幾層可以得到前面所有層的輸入,因此concat后的輸入channel還是比較大的。另外這里每個(gè)dense block的3*3卷積前面都包含了一個(gè)1*1的卷積操作,就是所謂的bottleneck layer,目的是減少輸入的feature map數(shù)量,既能降維減少計(jì)算量,又能融合各個(gè)通道的特征,何樂而不為。另外作者為了進(jìn)一步壓縮參數(shù),在每兩個(gè)dense block之間又增加了1*1的卷積操作。因此在后面的實(shí)驗(yàn)對(duì)比中,如果你看到DenseNet-C這個(gè)網(wǎng)絡(luò),表示增加了這個(gè)Translation layer,該層的1*1卷積的輸出channel默認(rèn)是輸入channel到一半。如果你看到DenseNet-BC這個(gè)網(wǎng)絡(luò),表示既有bottleneck layer,又有Translation layer。
再詳細(xì)說下bottleneck和transition layer操作。在每個(gè)Dense Block中都包含很多個(gè)子結(jié)構(gòu),以DenseNet-169的Dense Block(3)為例,包含32個(gè)1*1和3*3的卷積操作,也就是第32個(gè)子結(jié)構(gòu)的輸入是前面31層的輸出結(jié)果,每層輸出的channel是32(growth rate),那么如果不做bottleneck操作,第32層的3*3卷積操作的輸入就是31*32+(上一個(gè)Dense Block的輸出channel),近1000了。而加上1*1的卷積,代碼中的1*1卷積的channel是growth rate*4,也就是128,然后再作為3*3卷積的輸入。這就大大減少了計(jì)算量,這就是bottleneck。至于transition layer,放在兩個(gè)Dense Block中間,是因?yàn)槊總€(gè)Dense Block結(jié)束后的輸出channel個(gè)數(shù)很多,需要用1*1的卷積核來降維。還是以DenseNet-169的Dense Block(3)為例,雖然第32層的3*3卷積輸出channel只有32個(gè)(growth rate),但是緊接著還會(huì)像前面幾層一樣有通道的concat操作,即將第32層的輸出和第32層的輸入做concat,前面說過第32層的輸入是1000左右的channel,所以最后每個(gè)Dense Block的輸出也是1000多的channel。因此這個(gè)transition layer有個(gè)參數(shù)reduction(范圍是0到1),表示將這些輸出縮小到原來的多少倍,默認(rèn)是0.5,這樣傳給下一個(gè)Dense Block的時(shí)候channel數(shù)量就會(huì)減少一半,這就是transition layer的作用。文中還用到dropout操作來隨機(jī)減少分支,避免過擬合,畢竟這篇文章的連接確實(shí)多。
實(shí)驗(yàn)結(jié)果:?
作者在不同數(shù)據(jù)集上采用的DenseNet網(wǎng)絡(luò)會(huì)有一點(diǎn)不一樣,比如在Imagenet數(shù)據(jù)集上,DenseNet-BC有4個(gè)dense block,但是在別的數(shù)據(jù)集上只用3個(gè)dense block。其他更多細(xì)節(jié)可以看論文3部分的Implementation Details。訓(xùn)練的細(xì)節(jié)和超參數(shù)的設(shè)置可以看論文4.2部分,在ImageNet數(shù)據(jù)集上測試的時(shí)候有做224*224的center crop。
Table2是在三個(gè)數(shù)據(jù)集(C10,C100,SVHN)上和其他算法的對(duì)比結(jié)果。ResNet[11]就是kaiming He的論文,對(duì)比結(jié)果一目了然。DenseNet-BC的網(wǎng)絡(luò)參數(shù)和相同深度的DenseNet相比確實(shí)減少了很多!參數(shù)減少除了可以節(jié)省內(nèi)存,還能減少過擬合。這里對(duì)于SVHN數(shù)據(jù)集,DenseNet-BC的結(jié)果并沒有DenseNet(k=24)的效果好,作者認(rèn)為原因主要是SVHN這個(gè)數(shù)據(jù)集相對(duì)簡單,更深的模型容易過擬合。在表格的倒數(shù)第二個(gè)區(qū)域的三個(gè)不同深度L和k的DenseNet的對(duì)比可以看出隨著L和k的增加,模型的效果是更好的。
Figure3是DenseNet-BC和ResNet在Imagenet數(shù)據(jù)集上的對(duì)比,左邊那個(gè)圖是參數(shù)復(fù)雜度和錯(cuò)誤率的對(duì)比,你可以在相同錯(cuò)誤率下看參數(shù)復(fù)雜度,也可以在相同參數(shù)復(fù)雜度下看錯(cuò)誤率,提升還是很明顯的!右邊是flops(可以理解為計(jì)算復(fù)雜度)和錯(cuò)誤率的對(duì)比,同樣有效果。
Figure4也很重要。左邊的圖表示不同類型DenseNet的參數(shù)和error對(duì)比。中間的圖表示DenseNet-BC和ResNet在參數(shù)和error的對(duì)比,相同error下,DenseNet-BC的參數(shù)復(fù)雜度要小很多。右邊的圖也是表達(dá)DenseNet-BC-100只需要很少的參數(shù)就能達(dá)到和ResNet-1001相同的結(jié)果。
另外提一下DenseNet和隨機(jī)深度的關(guān)系,在隨機(jī)深度中,殘中的層在訓(xùn)練過程中會(huì)被隨機(jī)掉掉,其實(shí)這就會(huì)使得相鄰層之間直接連接,這和DenseNet是很像的。
總結(jié):?
博主讀完這篇文章真的有點(diǎn)相見恨晚的感覺,半年前就在的arXiv上掛出來了,聽說當(dāng)時(shí)就引起了轟動(dòng),后來又被選為CVPR2017的口服,感覺要撼動(dòng)RESNET的地位了,再加上現(xiàn)在很多分類檢測的網(wǎng)絡(luò)都是在RESNET上做的,這豈不是大地震了。驚訝之余來總結(jié)下這篇文章,該文章提出的DenseNet核心思想在于建立了不同層之間的連接關(guān)系,充分利用了功能,進(jìn)一步減輕了梯度消失問題,加深網(wǎng)絡(luò)不是問題,而且訓(xùn)練效果非常好。另外,利用瓶頸層,翻譯層以及較小的增長率使得網(wǎng)絡(luò)變窄,參數(shù)減少,有效抑制了過擬合,同時(shí)計(jì)算量也減少了.DenseNet優(yōu)點(diǎn)很多,而且在和RESNET的對(duì)比中優(yōu)勢還是非常明顯的。
黃高博士及劉壯取得聯(lián)系兩位作者對(duì)?DenseNet 的詳細(xì)介紹及常見疑問解答
https://www.leiphone.com/news/201708/0MNOwwfvWiAu43WO.html