著名:?本文是從 Michael Nielsen的電子書Neural Network and Deep Learning的深度學(xué)習(xí)那一章的卷積神經(jīng)網(wǎng)絡(luò)的參數(shù)優(yōu)化方法的一些總結(jié)和摘錄,并不是我自己的結(jié)論和做實(shí)驗(yàn)所得到的結(jié)果。我想Michael的實(shí)驗(yàn)結(jié)果更有說服力一些。本書在github上有中文翻譯的版本,
前言
最近卷積神經(jīng)網(wǎng)絡(luò)(CNN)很火熱,它在圖像分類領(lǐng)域的卓越表現(xiàn)引起了大家的廣泛關(guān)注。本文總結(jié)和摘錄了Michael Nielsen的那本Neural Network and Deep Learning一書中關(guān)于深度學(xué)習(xí)一章中關(guān)于提高泛化能力的一些概述和實(shí)驗(yàn)結(jié)果。力爭用數(shù)據(jù)給大家一個(gè)關(guān)于正則化,增加卷積層/全連接數(shù),棄權(quán)技術(shù),拓展訓(xùn)練集等參數(shù)優(yōu)化方法的效果。
本文并不會(huì)介紹正則化,棄權(quán)(Dropout), 池化等方法的原理,只會(huì)介紹它們在實(shí)驗(yàn)中的應(yīng)用或者起到的效果,更多的關(guān)于這些方法的解釋請自行查詢。
mnist數(shù)據(jù)集介紹
本文的實(shí)驗(yàn)是基于mnist數(shù)據(jù)集合的,mnist是一個(gè)從0到9的手寫數(shù)字集合,共有60,000張訓(xùn)練圖片,10,000張測試圖片。每張圖片大小是28*28大小。我們的實(shí)驗(yàn)就是構(gòu)建一個(gè)神經(jīng)網(wǎng)絡(luò)來高精度的分類圖片,也就是提高泛化能力。
提高泛化能力的方法
一般來說,提高泛化能力的方法主要有以下幾個(gè):
正則化
增加神經(jīng)網(wǎng)絡(luò)層數(shù)
使用正確的代價(jià)函數(shù)
使用好的權(quán)重初始化技術(shù)
人為拓展訓(xùn)練集
棄權(quán)技術(shù)
下面我們通過實(shí)驗(yàn)結(jié)果給這些參數(shù)優(yōu)化理論一個(gè)直觀的結(jié)果
1. 普通的全連接神經(jīng)網(wǎng)絡(luò)的效果
我們使用一個(gè)隱藏層,包含100個(gè)隱藏神經(jīng)元,輸入層是784,輸出層是one-hot編碼的形式,最后一層是Softmax層。訓(xùn)練過程采用對數(shù)似然代價(jià)函數(shù),60次迭代,學(xué)習(xí)速率η=0.1,隨機(jī)梯度下降的小批量數(shù)據(jù)大小為10,沒有正則化。在測試集上得到的結(jié)果是97.8%,代碼如下:
>>> import network3
>>> from network3 import Network
>>> from network3 import ConvPoolLayer, FullyConnectedLayer, SoftmaxLayer
>>> training_data, validation_data, test_data = network3.load_data_shared()
>>> mini_batch_size = 10
>>> net = Network([
FullyConnectedLayer(n_in=784, n_out=100),
SoftmaxLayer(n_in=100, n_out=10)], mini_batch_size)
>>> net.SGD(training_data, 60, mini_batch_size, 0.1,
validation_data, test_data)
2.使用卷積神經(jīng)網(wǎng)絡(luò) — 僅一個(gè)卷積層
輸入層是卷積層,5*5的局部感受野,也就是一個(gè)5*5的卷積核,一共20個(gè)特征映射。最大池化層選用2*2的大小。后面是100個(gè)隱藏神經(jīng)元的全連接層。結(jié)構(gòu)如圖所示
在這個(gè)架構(gòu)中,我們把卷積層和chihua層看做是學(xué)習(xí)輸入訓(xùn)練圖像中的局部感受野,而后的全連接層則是一個(gè)更抽象層次的學(xué)習(xí),從整個(gè)圖像整合全局信息。也是60次迭代,批量數(shù)據(jù)大小是10,學(xué)習(xí)率是0.1.代碼如下,
>>> net = Network([
ConvPoolLayer(image_shape=(mini_batch_size, 1, 28, 28),
filter_shape=(20, 1, 5, 5),
poolsize=(2, 2)),
FullyConnectedLayer(n_in=20*12*12, n_out=100),
SoftmaxLayer(n_in=100, n_out=10)], mini_batch_size)
>>> net.SGD(training_data, 60, mini_batch_size, 0.1,
validation_data, test_data)
經(jīng)過三次運(yùn)行取平均后,準(zhǔn)確率是98.78%,這是相當(dāng)大的改善。錯(cuò)誤率降低了1/3,。卷積神經(jīng)網(wǎng)絡(luò)開始顯現(xiàn)威力。
3.使用卷積神經(jīng)網(wǎng)絡(luò) — 兩個(gè)卷積層
我們接著插入第二個(gè)卷積-混合層,把它插入在之前的卷積-混合層和全連接層之間,同樣的5*5的局部感受野,2*2的池化層。
>>> net = Network([
ConvPoolLayer(image_shape=(mini_batch_size, 1, 28, 28),
filter_shape=(20, 1, 5, 5),
poolsize=(2, 2)),
ConvPoolLayer(image_shape=(mini_batch_size, 20, 12, 12),
filter_shape=(40, 20, 5, 5),
poolsize=(2, 2)),
FullyConnectedLayer(n_in=40*4*4, n_out=100),
SoftmaxLayer(n_in=100, n_out=10)], mini_batch_size)
>>> net.SGD(training_data, 60, mini_batch_size, 0.1,
validation_data, test_data)
這一次,我們擁有了99.06%的準(zhǔn)確率。
4.使用卷積神經(jīng)網(wǎng)絡(luò) — 兩個(gè)卷積層+線性修正單元(ReLU)+正則化
上面我們使用的Sigmod激活函數(shù),現(xiàn)在我們換成線性修正激活函數(shù)ReLU
f(z)=max(0,z),我們選擇60個(gè)迭代期,學(xué)習(xí)速率η=0.03, ,使用L2正則化,正則化參數(shù)λ=0.1,代碼如下
>>> from network3 import ReLU
>>> net = Network([
ConvPoolLayer(image_shape=(mini_batch_size, 1, 28, 28),
filter_shape=(20, 1, 5, 5),
poolsize=(2, 2),
activation_fn=ReLU),
ConvPoolLayer(image_shape=(mini_batch_size, 20, 12, 12),
filter_shape=(40, 20, 5, 5),
poolsize=(2, 2),
activation_fn=ReLU),
FullyConnectedLayer(n_in=40*4*4, n_out=100, activation_fn=ReLU),
SoftmaxLayer(n_in=100, n_out=10)], mini_batch_size)
>>> net.SGD(training_data, 60, mini_batch_size, 0.03,
validation_data, test_data, lmbda=0.1)
這一次,我們獲得了99.23%的準(zhǔn)確率,超過了S型激活函數(shù)的99.06%. ReLU的優(yōu)勢是max(0,z)中z取最大極限時(shí)不會(huì)飽和,不像是S函數(shù),這有助于持續(xù)學(xué)習(xí)。
5.使用卷積神經(jīng)網(wǎng)絡(luò) — 兩個(gè)卷基層+線性修正單元(ReLU)+正則化+拓展數(shù)據(jù)集
拓展訓(xùn)練集數(shù)據(jù)的一個(gè)簡單方法是將每個(gè)訓(xùn)練圖像由一個(gè)像素來代替,無論是上一個(gè)像素,下一個(gè)像素,或者左右的像素。其他的方法也有改變亮度,改變分辨率,圖片旋轉(zhuǎn),扭曲,位移等。
我們把50,000幅圖像人為拓展到250,000幅圖像。使用第4節(jié)一樣的網(wǎng)絡(luò),因?yàn)槲覀兪窃谟?xùn)練5倍的數(shù)據(jù),所以減少了過擬合的風(fēng)險(xiǎn)。
>>> expanded_training_data, _, _ = network3.load_data_shared(
"../data/mnist_expanded.pkl.gz")
>>> net = Network([
ConvPoolLayer(image_shape=(mini_batch_size, 1, 28, 28),
filter_shape=(20, 1, 5, 5),
poolsize=(2, 2),
activation_fn=ReLU),
ConvPoolLayer(image_shape=(mini_batch_size, 20, 12, 12),
filter_shape=(40, 20, 5, 5),
poolsize=(2, 2),
activation_fn=ReLU),
FullyConnectedLayer(n_in=40*4*4, n_out=100, activation_fn=ReLU),
SoftmaxLayer(n_in=100, n_out=10)], mini_batch_size)
>>> net.SGD(expanded_training_data, 60, mini_batch_size, 0.03,
validation_data, test_data, lmbda=0.1)
這次的到了99.37的訓(xùn)練正確率。
6.使用卷積神經(jīng)網(wǎng)絡(luò) — 兩個(gè)卷基層+線性修正單元(ReLU)+正則化+拓展數(shù)據(jù)集+繼續(xù)插入額外的全連接層
繼續(xù)上面的網(wǎng)絡(luò),我們拓展全連接層的規(guī)模,300個(gè)隱藏神經(jīng)元和1000個(gè)神經(jīng)元的額精度分別是99.46%和99.43%.
我們插入一個(gè)額外的全連接層
>>> net = Network([
ConvPoolLayer(image_shape=(mini_batch_size, 1, 28, 28),
filter_shape=(20, 1, 5, 5),
poolsize=(2, 2),
activation_fn=ReLU),
ConvPoolLayer(image_shape=(mini_batch_size, 20, 12, 12),
filter_shape=(40, 20, 5, 5),
poolsize=(2, 2),
activation_fn=ReLU),
FullyConnectedLayer(n_in=40*4*4, n_out=100, activation_fn=ReLU),
FullyConnectedLayer(n_in=100, n_out=100, activation_fn=ReLU),
SoftmaxLayer(n_in=100, n_out=10)], mini_batch_size)
>>> net.SGD(expanded_training_data, 60, mini_batch_size, 0.03,
validation_data, test_data, lmbda=0.1)
這次取得了99.43%的精度。拓展后的網(wǎng)絡(luò)并沒有幫助太多。
7.使用卷積神經(jīng)網(wǎng)絡(luò) — 兩個(gè)卷基層+線性修正單元(ReLU)+拓展數(shù)據(jù)集+繼續(xù)插入額外的全連接層+棄權(quán)技術(shù)
棄權(quán)的基本思想就是在訓(xùn)練網(wǎng)絡(luò)時(shí)隨機(jī)的移除單獨(dú)的激活值,使得模型對單獨(dú)的依據(jù)丟失更為強(qiáng)勁,因此不太依賴于訓(xùn)練數(shù)據(jù)的特質(zhì)。我們嘗試應(yīng)用棄權(quán)技術(shù)到最終的全連接層(不是在卷基層)。這里,減少了迭代期的數(shù)量為40個(gè),全連接層使用1000個(gè)隱藏神經(jīng)元,因?yàn)闂墮?quán)技術(shù)會(huì)丟棄一些神經(jīng)元。Dropout是一種非常有效有提高泛化能力,降低過擬合的方法!
>>> net = Network([
ConvPoolLayer(image_shape=(mini_batch_size, 1, 28, 28),
filter_shape=(20, 1, 5, 5),
poolsize=(2, 2),
activation_fn=ReLU),
ConvPoolLayer(image_shape=(mini_batch_size, 20, 12, 12),
filter_shape=(40, 20, 5, 5),
poolsize=(2, 2),
activation_fn=ReLU),
FullyConnectedLayer(
n_in=40*4*4, n_out=1000, activation_fn=ReLU, p_dropout=0.5),
FullyConnectedLayer(
n_in=1000, n_out=1000, activation_fn=ReLU, p_dropout=0.5),
SoftmaxLayer(n_in=1000, n_out=10, p_dropout=0.5)],
mini_batch_size)
>>> net.SGD(expanded_training_data, 40, mini_batch_size, 0.03,
validation_data, test_data)
使用棄權(quán)技術(shù),的到了99.60%的準(zhǔn)確率。
8.使用卷積神經(jīng)網(wǎng)絡(luò) — 兩個(gè)卷基層+線性修正單元(ReLU)+正則化+拓展數(shù)據(jù)集+繼續(xù)插入額外的全連接層+棄權(quán)技術(shù)+組合網(wǎng)絡(luò)
組合網(wǎng)絡(luò)類似于隨機(jī)森林或者adaboost的集成方法,創(chuàng)建幾個(gè)神經(jīng)網(wǎng)絡(luò),讓他們投票來決定最好的分類。我們訓(xùn)練了5個(gè)不同的神經(jīng)網(wǎng)絡(luò),每個(gè)都大到了99.60%的準(zhǔn)去率,用這5個(gè)網(wǎng)絡(luò)來進(jìn)行投票表決一個(gè)圖像的分類。
采用這個(gè)方法,達(dá)到了99.67%的準(zhǔn)確率。
總結(jié)
卷積神經(jīng)網(wǎng)絡(luò) 的一些技巧總結(jié)如下:
1. 使用卷積層極大地減小了全連接層中的參數(shù)的數(shù)目,使學(xué)習(xí)的問題更容易
2. 使用更多強(qiáng)有力的規(guī)范化技術(shù)(尤其是棄權(quán)和卷積)來減小過度擬合,
3. 使用修正線性單元而不是S型神經(jīng)元,來加速訓(xùn)練-依據(jù)經(jīng)驗(yàn),通常是3-5倍,
4. 使用GPU來計(jì)算
5. 利用充分大的數(shù)據(jù)集,避免過擬合
6. 使用正確的代價(jià)函數(shù),避免學(xué)習(xí)減速
7. 使用好的權(quán)重初始化,避免因?yàn)樯窠?jīng)元飽和引起的學(xué)習(xí)減速
評論