【卷積神經網絡】Lesson 2--深層卷積神經網絡

課程來源:吳恩達 深度學習課程 《卷積神經網絡》
筆記整理:王小草
時間:2018年6月6日python


outline:git

本文第1節主要會講解5個經典的神經網絡:
- LeNet-5(1998年)
- AlexNet(2012年ILSVRC第一名)
- z-net(2013年ILSVRC第一名)
- VGG(2014年ILSVRC第二名,但被普遍應用於其餘圖像任務)
- GoogleNet(2014年ILSVRC第一名)github

而後第2節講解ResNet:
2015年imageNet圖像分類分任務第一名。即殘差網絡,它的特色是很是深,是一個深達152層的神經網絡,而且在如何有效訓練方面,總結出來一些有趣的想法和竅門。web

第3節會講解一個Inception神經網絡的實例分析算法

瞭解了以上神經網絡網絡以後,你就會對如何構建有效的卷積神經網絡更有感受。網絡

1.經典網絡

1.1 CNN的演化

下圖是截取劉昕博士總結的CNN演化歷史圖。起點是神經認知機模型,此時已經出現了卷積結構,經典的LeNet誕生於1998年。然而以後CNN的鋒芒開始被SVM等手工設計的特徵蓋過。隨着ReLU和dropout的提出,以及GPU和大數據帶來的歷史機遇,CNN在2012年迎來了歷史突破–AlexNet.
QQ截圖20161114113400.png-63.3kB數據結構

1.2 Lenet-5

下圖是lenet的結構,與目前不斷改進中的CNN同樣,也一樣具備卷積層,池化層,全連接層。
QQ截圖20161114113734.png-84kBapp

原論文:Lecun et al.,1998.Gradienct-based learning applied to document recognition
對該論文,建議精讀第2段(重點介紹了本節要講的網絡),泛讀第3段(一些有趣的實驗結果)框架

輸入層
輸入層是一張黑白圖片,大小是32*32(1個顏色通道)。dom

卷積層1–C1
輸入層的下一層即是第1個卷積層了。這個卷積層有6個卷積核(每一個神經元對應一個卷積核),核大小是5*5.即輸出的是6個28*28的feature map,每一個feature map都提取了一個局部特徵。

這一層須要訓練的參數個數是(5*5+1)*6 = 156 。加1是由於每個卷積核線性計算中還有一個bais偏執項參數。

如此一來,C1中的連接數共有156*(28*28) = 122304個。

池化層1–S2
池化層也叫向下採樣層,是爲了下降網絡訓練參數及模型的過擬合程度。
C1的輸出就是S2的輸入,S2的輸入大小爲6 * 28 * 28.

窗口大小爲2*2,步長爲2,因此採樣以後的S2輸出是6 * 14 * 14

卷積層2–C3
C3有16個卷積核(16個神經元),一樣也是經過5 * 5的卷積核,獲得16個10 * 10 的feature map。

在C1中是有6個卷積核的,如今有16個,每一個卷積核都是提取了一個局部的特徵。因此16個卷積核其實表明着C1中6中特徵的組合。

池化層2–S4
一樣,經過對C3的向下採樣,輸出以後的大小爲16 * 5 * 5.

卷積層3–C5
C5有120個卷積核,每一個單元與S4的所有16個單元的5*5鄰域相連,因爲S4層特徵圖的大小也爲5*5(同濾波器同樣),故C5特徵圖的大小爲1*1:這構成了S4和C5之間的全鏈接。之因此仍將C5標示爲卷積層而非全相聯層,是由於若是LeNet-5的輸入變大,而其餘的保持不變,那麼此時特徵圖的維數就會比1*1大。C5層有48120個可訓練鏈接。

全連接層1–F6
F6層有84個單元(之因此選這個數字的緣由來自於輸出層的設計),與C5層全相連。有10164個可訓練參數。如同經典神經網絡,F6層計算輸入向量和權重向量之間的點積,再加上一個偏置。而後將其傳遞給sigmoid函數產生單元i的一個狀態。

輸出層–output
輸出層由歐式徑向基函數(Euclidean Radial Basis Function)單元組成,每類一個單元,每一個有84個輸入。
換句話說,每一個輸出RBF單元計算輸入向量和參數向量之間的歐式距離。輸入離參數向量越遠,RBF輸出的越大。用機率術語來講,RBF輸出能夠被理解爲F6層配置空間的高斯分佈的負log-likelihood。給定一個輸式,損失函數應能使得F6的配置與RBF參數向量(即模式的指望分類)足夠接近。

如今其實不多用歐式徑向基函數做爲輸出層了,通常都是用softmax層作多分類,比較直觀的圖:
image_1cf5jokvl15q94es1vh61otb1mr49.png-89.1kB

相比現代版本,這個神經網絡有點小,只有約6萬個參數,而如今,咱們常常看到一千萬到一億個參數的神經網絡。

2.3 Alexnet

AlexNet 能夠說是具備歷史意義的一個網絡結構,能夠說在AlexNet以前,深度學習已經沉寂了好久。歷史的轉折在2012年到來,AlexNet 在當年的ImageNet圖像分類競賽中,top-5錯誤率比上一年的冠軍降低了十個百分點,並且遠遠超過當年的第二名。

AlexNet 之因此可以成功,深度學習之因此可以重回歷史舞臺,緣由在於:
(1)非線性激活函數:ReLU
(2)防止過擬合的方法:Dropout,Data augmentation
(3)大數據訓練:百萬級ImageNet圖像數據
(4)其餘:GPU實現,LRN歸一化層的使用
(5)Alexnet比LeNet-5要深,其參數數量有600萬個
(6)使用了local response normalization(後來學者發現這個並不重要,所以此處不詳細講述)

原論文:[Krizhevsky et al.,2012.ImageNet classification with deep convolutional neaural networks]

2.3.1 結構

Alexnet的結構以下:
QQ截圖20161114132145.png-47.4kB

還有一張圖可能更直觀:
image_1cf6in08r1l35b7gacfefr309.png-192.9kB

alexnet總共包括8層,其中前5層convolutional(包含pool),後面3層是full-connected,文章裏面說的是減小任何一個卷積結果會變得不好,下面我來具體講講每一層的構成:

conv1:
第一層卷積層 輸入圖像爲227*227*3(paper上貌似有點問題224*224*3)的圖像,使用了96個kernels(96,11,11,3),以4個pixel爲一個單位來右移或者下移(步長爲4),可以產生96個55*55個卷積後的矩形框值。

pool2:
而後進行response-normalized(實際上是Local Response Normalized,後面我會講下這裏)和pooled以後,pool這一層好像caffe裏面的alexnet和paper裏面不太同樣,alexnet裏面採樣了兩個GPU,因此從圖上面看第一層卷積層厚度有兩部分,池化pool_size=(3,3),滑動步長爲2個pixels,獲得96個27*27個feature。

conv3:
第二個卷積層使用256個(一樣,分佈在兩個GPU上,每一個128kernels(5*5*48)),作pad_size(2,2)的處理,以1個pixel爲單位移動,可以產生256*27*27個卷積後的矩陣框,

pool4:
作LRN處理,而後pooled,池化以3*3矩形框,2個pixel爲步長,獲得256個13*13個features。

conv5:
使用384個kernels(3*3*384,pad_size=(1,1),獲得384*15*15,kernel_size爲(3,3),以1個pixel爲步長,獲得384*13*13)

conv6:
使用384個kernels(pad_size(1,1)獲得384*15*15,核大小爲(3,3)步長爲1個pixel,獲得384*13*13)

conv7:
使用256個kernels(pad_size(1,1)獲得384*15*15,核大小爲(3,3)步長爲1個pixel,獲得256*13*13)

pool7:
通過一個池化層,pool_size=(3,3),步長爲2,獲得6*6*256

full8:
將6*6*256平鋪成9216*1的向量,進入全鏈接層,該層的神經元個數爲4096,即有w權重參數維度4096*9216個。

full9:
該層神經元個數仍然是4096個

softmax10:
以上輸出,進入softmax層,由於由1000個分類,所以爲1000個神經元,每一個神經元輸出對應類別的機率。注意caffe圖中全鏈接層中有relu、dropout、innerProduct。

Alexnet總共有5個卷積層,具體的數據流以下:
QQ截圖20161114132850.png-185.7kB

以下有更清晰的數據結構(截圖自http://blog.csdn.net/sunbaigui/article/details/39938097
QQ截圖20161114133243.png-78.5kB
QQ截圖20161114133111.png-80.1kB
QQ截圖20161114133123.png-91.8kB
QQ截圖20161114133137.png-115kB
QQ截圖20161114133149.png-82.9kB

2.3.2 優勢

Data augmentation
有一種觀點認爲神經網絡是靠數據喂出來的,若增長訓練數據,則可以提高算法的準確率,由於這樣能夠避免過擬合,而避免了過擬合你就能夠增大你的網絡結構了。當訓練數據有限的時候,能夠經過一些變換來從已有的訓練數據集中生成一些新的數據,來擴大訓練數據的size。
其中,最簡單、通用的圖像數據變形的方式:
從原始圖像(256,256)中,隨機的crop出一些圖像(224,224)。【平移變換,crop】
水平翻轉圖像。【反射變換,flip】
給圖像增長一些隨機的光照。【光照、彩色變換,color jittering】

AlexNet 訓練的時候,在data augmentation上處理的很好:
隨機crop。訓練時候,對於256*256的圖片進行隨機crop到224*224,而後容許水平翻轉,那麼至關與將樣本倍增到((256-224)^2)*2=2048。
測試時候,對左上、右上、左下、右下、中間作了5次crop,而後翻轉,共10個crop,以後對結果求平均。做者說,不作隨機crop,大網絡基本都過擬合(under substantial overfitting)。
對RGB空間作PCA,而後對主成分作一個(0, 0.1)的高斯擾動。結果讓錯誤率又降低了1%。

ReLU 激活函數
Sigmoid 是經常使用的非線性的激活函數,它可以把輸入的連續實值「壓縮」到0和1之間。特別的,若是是很是大的負數,那麼輸出就是0;若是是很是大的正數,輸出就是1.
可是它有一些致命的 缺點:
Sigmoids saturate and kill gradients. sigmoid 有一個很是致命的缺點,當輸入很是大或者很是小的時候,會有飽和現象,這些神經元的梯度是接近於0的。若是你的初始值很大的話,梯度在反向傳播的時候由於須要乘上一個sigmoid 的導數,因此會使得梯度愈來愈小,這會致使網絡變的很難學習。
Sigmoid 的 output 不是0均值. 這是不可取的,由於這會致使後一層的神經元將獲得上一層輸出的非0均值的信號做爲輸入。
產生的一個結果就是:若是數據進入神經元的時候是正的(e.g. x>0 elementwise in f=wTx+b),那麼 w 計算出的梯度也會始終都是正的。
固然了,若是你是按batch去訓練,那麼那個batch可能獲得不一樣的信號,因此這個問題仍是能夠緩解一下的。所以,非0均值這個問題雖然會產生一些很差的影響,不過跟上面提到的 kill gradients 問題相比仍是要好不少的。

Alex用ReLU代替了Sigmoid,發現使用 ReLU 獲得的SGD的收斂速度會比 sigmoid/tanh 快不少。
主要是由於它是linear,並且 non-saturating(由於ReLU的導數始終是1),相比於 sigmoid/tanh,ReLU 只須要一個閾值就能夠獲得激活值,而不用去算一大堆複雜的運算。

Dropout
結合預先訓練好的許多不一樣模型,來進行預測是一種很是成功的減小測試偏差的方式(Ensemble)。但由於每一個模型的訓練都須要花了好幾天時間,所以這種作法對於大型神經網絡來講太過昂貴。
然而,AlexNet 提出了一個很是有效的模型組合版本,它在訓練中只須要花費兩倍於單模型的時間。這種技術叫作Dropout,它作的就是以0.5的機率,將每一個隱層神經元的輸出設置爲零。以這種方式「dropped out」的神經元既不參與前向傳播,也不參與反向傳播。
因此每次輸入一個樣本,就至關於該神經網絡就嘗試了一個新的結構,可是全部這些結構之間共享權重。由於神經元不能依賴於其餘特定神經元而存在,因此這種技術下降了神經元複雜的互適應關係。
正因如此,網絡須要被迫學習更爲魯棒的特徵,這些特徵在結合其餘神經元的一些不一樣隨機子集時有用。在測試時,咱們將全部神經元的輸出都僅僅只乘以0.5,對於獲取指數級dropout網絡產生的預測分佈的幾何平均值,這是一個合理的近似方法。

多GPU訓練
單個GTX 580 GPU只有3GB內存,這限制了在其上訓練的網絡的最大規模。所以他們將網絡分佈在兩個GPU上。
目前的GPU特別適合跨GPU並行化,由於它們可以直接從另外一個GPU的內存中讀出和寫入,不須要經過主機內存。
他們採用的並行方案是:在每一個GPU中放置一半核(或神經元),還有一個額外的技巧:GPU間的通信只在某些層進行。

QQ截圖20161114133650.png-47.8kB

例如,第3層的核須要從第2層中全部核映射輸入。然而,第4層的核只須要從第3層中位於同一GPU的那些核映射輸入。
Local Responce Normalization
一句話歸納:本質上,這個層也是爲了防止激活函數的飽和的。

2.3.3 AlexNet On Tensorflow

代碼位置:
http://www.cs.toronto.edu/~guerzhoy/tf_alexnet/

tflearn裏面有一個alexnet來分類Oxford的例子,好開心,在基於tflearn對一些平常layer的封裝,代碼量只有不到50行,看了下內部layer的實現,挺不錯的,寫代碼的時候能夠多參考參考,代碼地址https://github.com/tflearn/tflearn/blob/master/examples/images/alexnet.py.

from __future__ import division, print_function, absolute_import

import tflearn
from tflearn.layers.core import input_data, dropout, fully_connected
from tflearn.layers.conv import conv_2d, max_pool_2d
from tflearn.layers.normalization import local_response_normalization
from tflearn.layers.estimator import regression

import tflearn.datasets.oxflower17 as oxflower17
X, Y = oxflower17.load_data(one_hot=True, resize_pics=(227, 227))

# Building 'AlexNet'
network = input_data(shape=[None, 227, 227, 3])
network = conv_2d(network, 96, 11, strides=4, activation='relu')
network = max_pool_2d(network, 3, strides=2)
network = local_response_normalization(network)
network = conv_2d(network, 256, 5, activation='relu')
network = max_pool_2d(network, 3, strides=2)
network = local_response_normalization(network)
network = conv_2d(network, 384, 3, activation='relu')
network = conv_2d(network, 384, 3, activation='relu')
network = conv_2d(network, 256, 3, activation='relu')
network = max_pool_2d(network, 3, strides=2)
network = local_response_normalization(network)
network = fully_connected(network, 4096, activation='tanh')
network = dropout(network, 0.5)
network = fully_connected(network, 4096, activation='tanh')
network = dropout(network, 0.5)
network = fully_connected(network, 17, activation='softmax')
network = regression(network, optimizer='momentum',
                     loss='categorical_crossentropy',
                     learning_rate=0.001)

# Training
model = tflearn.DNN(network, checkpoint_path='model_alexnet',
                    max_checkpoints=1, tensorboard_verbose=2)
model.fit(X, Y, n_epoch=1000, validation_set=0.1, shuffle=True,
          show_metric=True, batch_size=64, snapshot_step=200,
          snapshot_epoch=False, run_id='alexnet_oxflowers17')

2.4 ZFNet

首先來簡單地介紹一下ZFNet這個CNN模型。它是2013年ILSVRC比賽的冠軍。它是在Alexnet的基礎上作一點點的改進和變換。結構以下:

QQ截圖20161114141203.png-142kB

ZFNet與Alexnet有兩點差異
1.在卷積層1中,VGG的卷積核是11*11大小,而且步長爲4;在ZFNet中,卷積核大小改成了7 * 7, 步長改成了2.
2.在卷積層3,4,5中,神經元的個數分別由VGG的384,384,256變成了512,1024,512.

其他結構與AlexNet徹底一致。

ZFNet將top5的錯誤率從15.4%降低到了14.8%,提高並無特別驚人。

2.5 VGG

原論文:[Simonyan&Zisserman 2015. Very deep conblutional networks for large-scale iamge recognition]

2.5.1 結構

VGGnet是Oxford的Visual Geometry Group的team,在ILSVRC 2014上的相關工做,主要工做是證實了增長網絡的深度可以在必定程度上影響網絡最終的性能,以下圖,文章經過逐步增長網絡深度來提升性能,雖然看起來有一點小暴力,沒有特別多取巧的,可是確實有效,不少pretrained的方法就是使用VGG的model(主要是16和19),VGG相對其餘的方法,參數空間很大,最終的model有500多m,alnext只有200m,googlenet更少,因此train一個vgg模型一般要花費更長的時間,所幸有公開的pretrained model讓咱們很方便的使用。paper中的幾種模型以下:

QQ截圖20161114141739.png-315.7kB

QQ截圖20161114141706.png-36.7kB

論文的做者試驗了多種深度與結構的CNN, 在16層的時候達到了最好。因此咱們如今通常都使用VGG-16,VGG-19.

如下是VGG每一層的數據維度
QQ截圖20161114142056.png-85.6kB

如下是計算VGG每一層須要的顯存,是能夠經過參數的數量進行估算的。要運行一個VGG,一張圖片須要給它93M,並且這只是前向計算的,若是還藥後向計算,那麼要93*2.
QQ截圖20161114142128.png-516kB

2.5.2 VGG on tensorflow

import tflearn
from tflearn.layers.core import input_data, dropout, fully_connected
from tflearn.layers.conv import conv_2d, max_pool_2d
from tflearn.layers.estimator import regression

# Data loading and preprocessing
import tflearn.datasets.oxflower17 as oxflower17
X, Y = oxflower17.load_data(one_hot=True)

# Building 'VGG Network'
network = input_data(shape=[None, 224, 224, 3])

network = conv_2d(network, 64, 3, activation='relu')
network = conv_2d(network, 64, 3, activation='relu')
network = max_pool_2d(network, 2, strides=2)

network = conv_2d(network, 128, 3, activation='relu')
network = conv_2d(network, 128, 3, activation='relu')
network = max_pool_2d(network, 2, strides=2)

network = conv_2d(network, 256, 3, activation='relu')
network = conv_2d(network, 256, 3, activation='relu')
network = conv_2d(network, 256, 3, activation='relu')
network = max_pool_2d(network, 2, strides=2)

network = conv_2d(network, 512, 3, activation='relu')
network = conv_2d(network, 512, 3, activation='relu')
network = conv_2d(network, 512, 3, activation='relu')
network = max_pool_2d(network, 2, strides=2)

network = conv_2d(network, 512, 3, activation='relu')
network = conv_2d(network, 512, 3, activation='relu')
network = conv_2d(network, 512, 3, activation='relu')
network = max_pool_2d(network, 2, strides=2)

network = fully_connected(network, 4096, activation='relu')
network = dropout(network, 0.5)
network = fully_connected(network, 4096, activation='relu')
network = dropout(network, 0.5)
network = fully_connected(network, 17, activation='softmax')

network = regression(network, optimizer='rmsprop',
                     loss='categorical_crossentropy',
                     learning_rate=0.001)

# Training
model = tflearn.DNN(network, checkpoint_path='model_vgg',
                    max_checkpoints=1, tensorboard_verbose=0)
model.fit(X, Y, n_epoch=500, shuffle=True,
          show_metric=True, batch_size=32, snapshot_step=500,
          snapshot_epoch=False, run_id='vgg_oxflowers17')

2.殘差網絡

2.1 殘差網絡介紹

原論文連接:https://arxiv.org/abs/1512.03385

當神經網絡深度很深的時候,殘差作後向計算求導時會變得很是很是小,因此訓練起來很是困難。可是每每神經網絡越深它的效果也越好。

因此,得想一個辦法得讓神經網絡又深又好訓練。因而微軟亞洲研究院提出ResNet,在2015年的ILSVRC比賽中得到了冠軍,比VGG還要深8倍。(152層)

深層的CNN訓練困難在於梯度衰減,即便使用bantch normalization,幾十層的CNN也很是難訓練。
離輸入層越遠,殘差傳回來的信號也就很是弱了,從而致使了失真。

因而ResNet設計了這樣一個結構:residual block
QQ截圖20161114151147.png-40kB

F(x)是一個殘差的隱射,將它加上從根部傳過來的原始的信息x再去通過激勵函數relu往下走。

從而,原來的每層計算以下:
image_1cf6kva141bl9nb7v2e7d31dlam.png-28.1kB
如今a[l+2]中增添了a[l]的信息:
image_1cf6l0o47rvnksjvt1r9a1g3r13.png-18.2kB
這個傳殘差的的過程叫作「shot cut」,有時也叫作「skip connection」

整個ResNet的結構能夠以下圖:
QQ截圖20161114152005.png-74.7kB

使用resNet的效果對比:
image_1cf6l698lh9ril01oub1fhf1k6s1g.png-25kB
普通神經網絡,隨着深度的增長,訓練的偏差會增大,而使用殘差網絡,則不管深度如何增長,訓練的偏差都是逐漸降低的。

2.2 Deep Residual Network tflearn實現

from __future__ import division, print_function, absolute_import

import tflearn

# Residual blocks
# 32 layers: n=5, 56 layers: n=9, 110 layers: n=18
n = 5

# Data loading
from tflearn.datasets import cifar10
(X, Y), (testX, testY) = cifar10.load_data()
Y = tflearn.data_utils.to_categorical(Y, 10)
testY = tflearn.data_utils.to_categorical(testY, 10)

# Real-time data preprocessing
img_prep = tflearn.ImagePreprocessing()
img_prep.add_featurewise_zero_center(per_channel=True)

# Real-time data augmentation
img_aug = tflearn.ImageAugmentation()
img_aug.add_random_flip_leftright()
img_aug.add_random_crop([32, 32], padding=4)

# Building Residual Network
net = tflearn.input_data(shape=[None, 32, 32, 3],
                         data_preprocessing=img_prep,
                         data_augmentation=img_aug)
net = tflearn.conv_2d(net, 16, 3, regularizer='L2', weight_decay=0.0001)
net = tflearn.residual_block(net, n, 16)
net = tflearn.residual_block(net, 1, 32, downsample=True)
net = tflearn.residual_block(net, n-1, 32)
net = tflearn.residual_block(net, 1, 64, downsample=True)
net = tflearn.residual_block(net, n-1, 64)
net = tflearn.batch_normalization(net)
net = tflearn.activation(net, 'relu')
net = tflearn.global_avg_pool(net)
# Regression
net = tflearn.fully_connected(net, 10, activation='softmax')
mom = tflearn.Momentum(0.1, lr_decay=0.1, decay_step=32000, staircase=True)
net = tflearn.regression(net, optimizer=mom,
                         loss='categorical_crossentropy')
# Training
model = tflearn.DNN(net, checkpoint_path='model_resnet_cifar10',
                    max_checkpoints=10, tensorboard_verbose=0,
                    clip_gradients=0.)

model.fit(X, Y, n_epoch=200, validation_set=(testX, testY),
          snapshot_epoch=False, snapshot_step=500,
          show_metric=True, batch_size=128, shuffle=True,
          run_id='resnet_cifar10')

3.3 1*1卷積

1*1的卷積有什麼用,聽上去好搞笑哦。實際上它頗有用。
以下網絡,輸入時6*6*32的圖片,通過1*1*32的卷積核,再通過relu會獲得6*6*Filter_num的矩陣
image_1cf884qkl1f8n1uitv39rvv1uubm.png-70.2kB
這個過程稱爲1*1卷積,或者網絡中的網絡

何時使用1*1卷積呢?當channel數目很是多的時候。
咱們知道pool layer能夠壓縮hight和width的大小,可是channel的大小卻沒法壓縮。而使用1*1卷積就能夠解決這個問題。若設置n個1*1的卷積核,則最後的輸出矩陣的channel數目就是n

來個例子:
image_1cf88v757d8l1e2t1untvusncl13.png-68.3kB
輸入的維度是28*28*192,192的channel樹忒大了,想要縮小,就是用32個1*1*192的卷積核進行卷積,最終輸出維度是28*28*32.同理,你也能夠用這種方式來增長channel數目。
(後面你會發現1*1卷積對侯建Inception網絡頗有幫助)

4. 谷歌Inception網絡

在構建神經網絡的時候,咱們須要去設計須要多少卷積核呀,卷積核大小是多少呀,須要多少卷積層與池化層呀等等。而Inception網絡實在是幫助你去決定這些東東,雖然所以網絡結構複雜了不少,可是網絡表現卻很是好。

4.1 Inception結構

假設有一個28*28*192的輸入
image_1cf93b625hk11jfl1lopur6qrf1g.png-19.9kB

不知道要用多少大小的卷積核去卷積,所以先用64個1*1卷積核,獲得28*28*64的輸出
image_1cf93dchb1meftjhj781726nps1t.png-40.7kB

接着在用128個3*3的卷積核,獲得28*28*128的輸出,將這個輸出疊加在已有的輸出上
image_1cf93g5gg1mev1h221olpvf9l7b2a.png-55.6kB

再接着用32個5*5的卷積核,獲得28*28*32的輸出,再疊加到已有輸出上
image_1cf93k3tn675nvv3b12j212572n.png-74.1kB

再來一個池化層,32個1*1,步長爲1,則獲得輸出爲28*28*32,將這個輸出也堆疊在已有的輸出上
image_1cf93n0b69jkjn513np1o8v18ok34.png-88.6kB

綜上全部輸出疊加獲得維度爲28*28*256,而以上過程就是Inception的核心了,來自論文[Szegedy et al.2014.Going Deeper with Convolutions]

基於以上,咱們有3類卷積,1類池化,無需人爲去選擇到底要哪一個卷積,或要不要池化和卷積,在訓練的過程當中,模型自動會去學習參數,並決定選用哪一個類型。但這樣,也加大了計算量

4.2 Inception的問題-計算量大

以5*5的卷積核爲例來看看它的計算量。
image_1cf949snu1pq51d3113ds10371gtd3h.png-51.3kB
輸入是28*28*192,卷積核大小是5*5,有32個,所以總的計算量是28*28*32*5*5*192 = 1.2億。嚇人。

解決辦法,是上一節提到的1*1卷積,假設用16個1*1的卷積核進行卷積,則原來28*28*192的維度就會縮減到28*28*16,再在上面作5*5的卷積,則計算量大大縮減.
第一步計算量爲28*28*16*192=2.4m
第二部計算量爲28*28*32*5*5*16=10.0m
與上文的120m降低了不少。
image_1cf94h98e1gck2th18afcsn18a33u.png-63.8kB
中間的這個28*28*16的輸出層,有時咱們稱之爲瓶頸層(bottleneck layer)

4.3 構建完整的Inception網絡

回顧一下Inception模塊
image_1cf95aoqaeh18vu1up1fk21b7i4o.png-216.1kB

輸入時前一層的激活函數的輸出,大小有28*28*192

中間過程作4個類型的堆疊:
(1)直接進行1*1卷積,輸出28*28*64
(2)進行3*3卷積,可是爲了減少計算量,前面先放了一個1*1卷積,使channel層數目由192降低到了96,最終輸出28*28*128
(3)進行5*5卷積,一樣爲了減少計算量,前面先放了一個1*1卷積,使channel層數目由192降低到了16,最終輸出28*28*32
(4)池化,輸出28*28*192,而後用1*1卷積將192降低到了32

最終左右結果堆疊在一塊兒輸出28*28*256

完整的Inception網絡結構圖:
image_1cf9598vkf4rubp17on3drd0v4b.png-106.2kB
看上去複雜得密集恐懼症,其實其是由一個一個上文那樣的Inception模塊組合起來的,中間穿插一些max pool layer來減少hight和wighth.

論文中的完整網絡其實還有一小塊細節,就是在中間的隱藏層,也會額外接上全鏈接層與softmax層作分類,從而避免過擬合。
image_1cf95td3c1me27vv1dbr19d62df55.png-180.2kB

爲何要取名爲Inception呢?看過電影《Inception(盜夢空間)》的不解釋。

4.4 GoogLeNet

參考博客「http://hacker.duanshishi.com/?p=1678

GoogLeNet是ILSVRC 2014的冠軍,主要是致敬經典的LeNet-5算法,主要是Google的team成員完成,paper見Going Deeper with Convolutions.相關工做主要包括LeNet-五、Gabor filters、Network-in-Network.Network-in-Network改進了傳統的CNN網絡,採用少許的參數就輕鬆地擊敗了AlexNet網絡,使用Network-in-Network的模型最後大小約爲29MNetwork-in-Network caffe model.GoogLeNet借鑑了Network-in-Network的思想

QQ截圖20161114144415.png-170.6kB

整體結構:

1.包括Inception模塊的全部卷積,都用了修正線性單元(ReLU);

2.網絡的感覺野大小是224x224,採用RGB彩色通道,且減去均值;

3.#3x3 reduce和#5x5 reduce分別表示3x3和5x5的卷積前縮減層中1x1濾波器的個數;pool proj表示嵌入的max-pooling以後的投影層中1x1濾波器的個數;縮減層和投影層都要用ReLU;

4.網絡包含22個帶參數的層(若是考慮pooling層就是27層),獨立成塊的層總共有約有100個;

5.網絡中間的層次生成的特徵會很是有區分性,給這些層增長一些輔助分類器。這些分類器以小卷積網絡的形式放在Inception(4a)和Inception(4b)的輸出上。在訓練過程當中,損失會根據折扣後的權重(折扣權重爲0.3)疊加到總損失中。

輔助分類器的具體細節:

1.均值pooling層濾波器大小爲5x5,步長爲3,(4a)的輸出爲4x4x512,(4d)的輸出爲4x4x528;

2.1x1的卷積有用於降維的128個濾波器和修正線性激活;

3.全鏈接層有1024個單元和修正線性激活;

4.dropout層的dropped的輸出比率爲70%;

5.線性層將softmax損失做爲分類器(和主分類器同樣預測1000個類,但在inference時移除)。

5.使用開源的實現方案

上文咱們學習了優秀的經典網絡,如今來說一講如何使用它們。
看了論文,理解做者的思路以後,此時就應該去將論文中的方法復現一遍,而本身去實現一遍費時費力也不必定能達到做者的效果,由於構建神經網絡中藥涉及的細節忒多,做者在論文中也不可能所有羅列,所以咱們須要去尋找做者開源出來的代碼(若是有的話)。

找開源代碼,直接在Github上搜索對應的相關詞,找到適合的代碼,就將工程下載到本地便可。(關於如何使用github下載源碼請百度哦)

6.遷移學習(transfer learning)

從頭構建一個神經網絡,初始化參數進行訓練,每每費時費力不討好,而若直接使用別人已經訓練好的優秀模型來作預訓練,則可能事半攻倍。

如何進行遷移學習?
(1)在數據集A上訓練一個神經網絡(好比訓練了貓狗分類的)
(2)將以上訓練好的神經網絡用在B數據集上訓練(好比X光照片分類)
- 若B數據集size小,則可只從新訓練最後一層的參數
- 若B數據集size大,則可從新訓練後面幾層的參數(數據集越大,從新訓練的層數能夠越多)
- 若B數據集size很是大,則可從新訓練整個神經網絡的全部參數(將原訓練好的神經網絡的參數做爲初始參數,即經過A數據集進行預訓練初始參數pre-train the weight of NN)
以上過程叫作fine-tuning

而數據集A訓練的神經網絡咱們每每會去拿一些開源的優秀的神經網絡框架(注意在github下載源碼的同事也把權重下載下來)

爲何進行遷移學習?
在原數據集上學到的邊緣特徵,有助於在新數據集中有更好的算法表現(好比結構信息,圖像形狀信息等其中有些信息可能會有用)

何時進行遷移學習?
(1)taskA,B必須有相同的input,好比都是image或者都是音頻
(2)當對於你想要解決的問題數據集很小的時候,則先用大量數據作預訓練,而後用少許的目標數據作遷移學習。
(3)A數據的low level特徵對學習B數據有幫助的時候

7.數據加強(data augmentation)

訓練神經網絡每每須要大量的數據,而現實中數據的獲取老是難之又難,所以須要用到data augmentation來應用一些技術擴大之後的數據集。

對於圖像有如下幾種數據加強的方式:

經常使用的方式
(1)Mirroring鏡像翻轉
image_1cf98f8rh1tsc6mu10rugfm1fv09.png-129.3kB

(2)Random Cropping隨機裁剪
image_1cf98gtve13cd199l18dn1d0kis3m.png-159.4kB
這並非一個完美的數據加強方式,由於你隨機裁剪的部分可能裏面並無目標圖像,從而誤導模型學習。但對於大量數據而言,這點噪音還能夠接受。

(3)Rotation旋轉
(4)Shearing扭曲
(5)local warping局部彎曲

color shifting
image_1cf98r493cjt1rnp1kn0p3c1q3b1j.png-266kB

RGB的採樣方式:PCA(主成分分析法/PCA顏色加強)

8.論文與比賽中表現好的小技巧

若是在基準數據上有好的表現,則每每很容易發論文,因此學者們都經常致力於在基準數據上下功夫,構建模型,可是這些東東在業務實踐上有時並不可觀。爲了在基準數據上表現良好,或者競賽中表現優異,有如下tips:
(1)集成模型:獨立訓練多個模型,而後平均他們的結果進行集成(多個模型計算量太大,不適合於生產)
(2)Multi-crop:讓同一個模型跑在不一樣版本的測試集上(好比數據加強後的不一樣形式的數據),而後平均結果。
經常使用的有10-crop,將圖片以中心點折起來,分別從左上角開始截取圖片,好比以下,總共會獲得10張圖片:
image_1cf9a057813873dj1utmdj5128k2g.png-99.5kB 要作的是,讓分類器對這10張圖片都作預測,而後選取平均值。(但一樣增大了計算量) (3)使用開源框架: - 文獻中發表的神經網絡框架 - 已被實現的開源代碼 - 使用與訓練好的模型,在你的數據集上fine-tuning