介紹
終于可以說(shuō)一下Resnet分類(lèi)網(wǎng)絡(luò)了揭璃,它差不多是當(dāng)前應(yīng)用最為廣泛的CNN特征提取網(wǎng)絡(luò)。它的提出始于2015年亭罪,作者中間有大名鼎鼎的三位人物He-Kaiming, Ren-Shaoqing, Sun-Jian瘦馍。絕對(duì)是華人學(xué)者的驕傲啊。
VGG網(wǎng)絡(luò)試著探尋了一下深度學(xué)習(xí)網(wǎng)絡(luò)的深度究竟可以深幾許以能持續(xù)地提高分類(lèi)準(zhǔn)確率应役。我們的一般印象當(dāng)中情组,深度學(xué)習(xí)愈是深(復(fù)雜,參數(shù)多)愈是有著更強(qiáng)的表達(dá)能力箩祥。憑著這一基本準(zhǔn)則CNN分類(lèi)網(wǎng)絡(luò)自Alexnet的7層發(fā)展到了VGG的16乃至19層院崇,后來(lái)更有了Googlenet的22層∨圩妫可后來(lái)我們發(fā)現(xiàn)深度CNN網(wǎng)絡(luò)達(dá)到一定深度后再一味地增加層數(shù)并不能帶來(lái)進(jìn)一步地分類(lèi)性能提高底瓣,反而會(huì)招致網(wǎng)絡(luò)收斂變得更慢,test dataset的分類(lèi)準(zhǔn)確率也變得更差盲泛。排除數(shù)據(jù)集過(guò)小帶來(lái)的模型過(guò)擬合等問(wèn)題后濒持,我們發(fā)現(xiàn)過(guò)深的網(wǎng)絡(luò)仍然還會(huì)使分類(lèi)準(zhǔn)確度下降(相對(duì)于較淺些的網(wǎng)絡(luò)而言)键耕。
正是受制于此不清不楚的問(wèn)題寺滚,VGG網(wǎng)絡(luò)達(dá)到19層后再增加層數(shù)就開(kāi)始導(dǎo)致分類(lèi)性能的下降柑营。而Resnet網(wǎng)絡(luò)作者則想到了常規(guī)計(jì)算機(jī)視覺(jué)領(lǐng)域常用的residual representation的概念,并進(jìn)一步將它應(yīng)用在了CNN模型的構(gòu)建當(dāng)中村视,于是就有了基本的residual learning的block官套。它通過(guò)使用多個(gè)有參層來(lái)學(xué)習(xí)輸入輸出之間的殘差表示,而非像一般CNN網(wǎng)絡(luò)(如Alexnet/VGG等)那樣使用有參層來(lái)直接嘗試學(xué)習(xí)輸入蚁孔、輸出之間的映射奶赔。實(shí)驗(yàn)表明使用一般意義上的有參層來(lái)直接學(xué)習(xí)殘差比直接學(xué)習(xí)輸入、輸出間映射要容易得多(收斂速度更快)杠氢,也有效得多(可通過(guò)使用更多的層來(lái)達(dá)到更高的分類(lèi)精度)站刑。
當(dāng)下Resnet已經(jīng)代替VGG成為一般計(jì)算機(jī)視覺(jué)領(lǐng)域問(wèn)題中的基礎(chǔ)特征提取網(wǎng)絡(luò)。當(dāng)下Facebook乍提出的可有效生成多尺度特征表達(dá)的FPN網(wǎng)絡(luò)也可通過(guò)將Resnet作為其發(fā)揮能力的基礎(chǔ)網(wǎng)絡(luò)從而得到一張圖片最優(yōu)的CNN特征組合集合鼻百。
深度殘差學(xué)習(xí)(Deep Residual learning)
殘差學(xué)習(xí)
若將輸入設(shè)為X绞旅,將某一有參網(wǎng)絡(luò)層設(shè)為H,那么以X為輸入的此層的輸出將為H(X)温艇。一般的CNN網(wǎng)絡(luò)如Alexnet/VGG等會(huì)直接通過(guò)訓(xùn)練學(xué)習(xí)出參數(shù)函數(shù)H的表達(dá)因悲,從而直接學(xué)習(xí)X -> H(X)。
而殘差學(xué)習(xí)則是致力于使用多個(gè)有參網(wǎng)絡(luò)層來(lái)學(xué)習(xí)輸入勺爱、輸出之間的參差即H(X) - X即學(xué)習(xí)X -> (H(X) - X) + X晃琳。其中X這一部分為直接的identity mapping,而H(X) - X則為有參網(wǎng)絡(luò)層要學(xué)習(xí)的輸入輸出間殘差琐鲁。
下圖為殘差學(xué)習(xí)這一思想的基本表示卫旱。
Identity mapping
上小節(jié)中,我們知道殘差學(xué)習(xí)單元通過(guò)Identity mapping的引入在輸入围段、輸出之間建立了一條直接的關(guān)聯(lián)通道誊涯,從而使得強(qiáng)大的有參層集中精力學(xué)習(xí)輸入、輸出之間的殘差蒜撮。一般我們用F(X, Wi)來(lái)表示殘差映射暴构,那么輸出即為:Y = F(X, Wi) + X。當(dāng)輸入段磨、輸出通道數(shù)相同時(shí)取逾,我們自然可以如此直接使用X進(jìn)行相加。而當(dāng)它們之間的通道數(shù)目不同時(shí)苹支,我們就需要考慮建立一種有效的identity mapping函數(shù)從而可以使得處理后的輸入X與輸出Y的通道數(shù)目相同即Y = F(X, Wi) + Ws*X砾隅。
當(dāng)X與Y通道數(shù)目不同時(shí),作者嘗試了兩種identity mapping的方式债蜜。一種即簡(jiǎn)單地將X相對(duì)Y缺失的通道直接補(bǔ)零從而使其能夠相對(duì)齊的方式晴埂,另一種則是通過(guò)使用1x1的conv來(lái)表示W(wǎng)s映射從而使得最終輸入與輸出的通道達(dá)到一致的方式究反。
實(shí)驗(yàn)比較所用到的殘差網(wǎng)絡(luò)結(jié)構(gòu)與樸素網(wǎng)絡(luò)結(jié)構(gòu)
作者為了表明殘差網(wǎng)絡(luò)的有效性,共使用了三種網(wǎng)絡(luò)進(jìn)行實(shí)驗(yàn)儒洛。其一為VGG19網(wǎng)絡(luò)(這是VGG paper中最深的亦是最有效的一種網(wǎng)絡(luò)結(jié)構(gòu))精耐,另外則是順著VGG網(wǎng)絡(luò)思維繼續(xù)加深其層次而形成的一種VGG樸素網(wǎng)絡(luò),它共有34個(gè)含參層琅锻。最后則是與上述34層樸素網(wǎng)絡(luò)相對(duì)應(yīng)的Resnet網(wǎng)絡(luò)卦停,它主要由上節(jié)中所介紹的殘差單元來(lái)構(gòu)成。
在具體實(shí)現(xiàn)殘差網(wǎng)絡(luò)時(shí)恼蓬,對(duì)于其中的輸入惊完、輸出通道數(shù)目不同的情況作者使用了兩種可能的選擇。A)shortcut直接使用identity mapping处硬,不足的通道通同補(bǔ)零來(lái)對(duì)齊小槐;B)使用1x1的Conv來(lái)表示W(wǎng)s映射,從而使得輸入荷辕、輸出通道數(shù)目相同凿跳。
自下面兩表中,我們可看出殘差網(wǎng)絡(luò)能夠在深度增加的情況下維持強(qiáng)勁的準(zhǔn)確率增長(zhǎng)桐腌,有效地避免了VGG網(wǎng)絡(luò)中層數(shù)增加到一定程度拄显,模型準(zhǔn)確度不升反降的問(wèn)題。
然后自下表中案站,我們可以看到常規(guī)Resnet網(wǎng)絡(luò)與其它網(wǎng)絡(luò)如VGG/Googlenet等在Imagenet validation dataset上的性能比較躬审。
bottleneck構(gòu)建模塊
為了實(shí)際計(jì)算的考慮,作者提出了一種bottleneck的結(jié)構(gòu)塊來(lái)代替常規(guī)的Resedual block蟆盐,它像Inception網(wǎng)絡(luò)那樣通過(guò)使用1x1 conv來(lái)巧妙地縮減或擴(kuò)張feature map維度從而使得我們的3x3 conv的filters數(shù)目不受外界即上一層輸入的影響承边,自然它的輸出也不會(huì)影響到下一層module。
不過(guò)它純是為了節(jié)省計(jì)算時(shí)間進(jìn)而縮小整個(gè)模型訓(xùn)練所需的時(shí)間而設(shè)計(jì)的石挂,對(duì)最終的模型精度并無(wú)影響博助。
CIFAR10上更深的Resnet網(wǎng)絡(luò)
作者進(jìn)一步在小的CIFAR10數(shù)據(jù)集上嘗試了更深的Resnet網(wǎng)絡(luò),其深度最多達(dá)到了1202層痹愚。不過(guò)卻發(fā)現(xiàn)分類(lèi)性能終于開(kāi)始有了一定下降富岳。作者分析認(rèn)為可能是層數(shù)過(guò)多,導(dǎo)致模型過(guò)于復(fù)雜拯腮,而CIFAR-10較小的數(shù)據(jù)集造成了它的過(guò)擬合吧窖式。
如下表為其瘋狂的實(shí)驗(yàn)結(jié)果。
代碼實(shí)例
數(shù)據(jù)輸入層
name: "ResNet-50"
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
mirror: true
crop_size: 224
mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"
}
data_param {
source: "examples/imagenet/ilsvrc12_train_lmdb"
batch_size: 50
backend: LMDB
prefetch: 2
}
}
如下為構(gòu)成Resnet網(wǎng)絡(luò)的一個(gè)residual block表示动壤。注意它這里的identity mapping中包含了一個(gè)1x1 conv表示的Ws萝喘。而網(wǎng)絡(luò)中其它的若干模塊則可能直接使用的identity mapping,而不含任何有參層。
layer {
bottom: "pool1"
top: "res2a_branch1"
name: "res2a_branch1"
type: "Convolution"
convolution_param {
num_output: 256
kernel_size: 1
pad: 0
stride: 1
bias_term: false
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
bottom: "res2a_branch1"
top: "res2a_branch1"
name: "bn2a_branch1"
type: "BatchNorm"
batch_norm_param {
}
}
layer {
bottom: "res2a_branch1"
top: "res2a_branch1"
name: "scale2a_branch1"
type: "Scale"
scale_param {
bias_term: true
}
}
layer {
bottom: "pool1"
top: "res2a_branch2a"
name: "res2a_branch2a"
type: "Convolution"
convolution_param {
num_output: 64
kernel_size: 1
pad: 0
stride: 1
bias_term: false
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
bottom: "res2a_branch2a"
top: "res2a_branch2a"
name: "bn2a_branch2a"
type: "BatchNorm"
batch_norm_param {
}
}
layer {
bottom: "res2a_branch2a"
top: "res2a_branch2a"
name: "scale2a_branch2a"
type: "Scale"
scale_param {
bias_term: true
}
}
layer {
bottom: "res2a_branch2a"
top: "res2a_branch2a"
name: "res2a_branch2a_relu"
type: "ReLU"
relu_param {
}
}
layer {
bottom: "res2a_branch2a"
top: "res2a_branch2b"
name: "res2a_branch2b"
type: "Convolution"
convolution_param {
num_output: 64
kernel_size: 3
pad: 1
stride: 1
bias_term: false
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
bottom: "res2a_branch2b"
top: "res2a_branch2b"
name: "bn2a_branch2b"
type: "BatchNorm"
batch_norm_param {
}
}
layer {
bottom: "res2a_branch2b"
top: "res2a_branch2b"
name: "scale2a_branch2b"
type: "Scale"
scale_param {
bias_term: true
}
}
layer {
bottom: "res2a_branch2b"
top: "res2a_branch2b"
name: "res2a_branch2b_relu"
type: "ReLU"
relu_param {
}
}
layer {
bottom: "res2a_branch2b"
top: "res2a_branch2c"
name: "res2a_branch2c"
type: "Convolution"
convolution_param {
num_output: 256
kernel_size: 1
pad: 0
stride: 1
bias_term: false
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
bottom: "res2a_branch2c"
top: "res2a_branch2c"
name: "bn2a_branch2c"
type: "BatchNorm"
batch_norm_param {
}
}
layer {
bottom: "res2a_branch2c"
top: "res2a_branch2c"
name: "scale2a_branch2c"
type: "Scale"
scale_param {
bias_term: true
}
}
layer {
bottom: "res2a_branch1"
bottom: "res2a_branch2c"
top: "res2a"
name: "res2a"
type: "Eltwise"
eltwise_param {
}
}
layer {
bottom: "res2a"
top: "res2a"
name: "res2a_relu"
type: "ReLU"
relu_param {
}
}
Resnet網(wǎng)絡(luò)的最后若干層阁簸。與其它VGG/Alexnet或者Googlenet并無(wú)不同爬早。
layer {
bottom: "res5c"
top: "pool5"
name: "pool5"
type: "Pooling"
pooling_param {
kernel_size: 7
stride: 1
pool: AVE
}
}
layer {
bottom: "pool5"
top: "fc1000"
name: "fc1000"
type: "InnerProduct"
inner_product_param {
num_output: 1000
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0
}
}
}
layer {
bottom: "fc1000"
bottom: "label"
top: "prob"
name: "prob"
type: "SoftmaxWithLoss"
include {
phase: TRAIN
}
}
layer {
name: "probt"
type: "Softmax"
bottom: "fc1000"
top: "probt"
include {
phase: TEST
}
}
layer {
name: "accuracy/top-1"
type: "Accuracy"
bottom: "fc1000"
bottom: "label"
top: "accuracy/top-1"
accuracy_param
{
top_k: 1
}
include {
phase: TEST
}
}
layer {
name: "accuracy/top-5"
type: "Accuracy"
bottom: "fc1000"
bottom: "label"
top: "accuracy/top-5"
accuracy_param
{
top_k: 5
}
include {
phase: TEST
}
}
參考文獻(xiàn)
- Deep Residual Learning for Image Recognition, He-Kaiming, 2015
- https://github.com/intel/caffe