Caffe學(xué)習(xí)筆記4:特殊的層及solver最優(yōu)化求解

今天總結(jié)一下搜到的一些知識:
感謝

http://blog.csdn.net/roslei/article/details/52807699
http://blog.csdn.net/u013066730/article/details/53764155
http://blog.csdn.net/qq_26898461/article/details/50445392

卷積神經(jīng)網(wǎng)絡(luò)(CNN)中的一些特殊層

Batch Normalization

意義: 網(wǎng)絡(luò)訓(xùn)練時,用來加速收斂速度
提醒: 已經(jīng)將BN集成為一個layer了,使用時需要和scale層一起使用
訓(xùn)練的時候,將BN層的use_global_stats設(shè)置為false; 測試的時候?qū)?use_global_stats設(shè)置為true,不然訓(xùn)練的時候會報“NAN”或者模型不
收斂 – 師兄的經(jīng)驗,我還沒試驗過

用法: 詳見 [殘差神經(jīng)網(wǎng)絡(luò)](https://github.com/KaimingHe/deep-
residual-networks/blob/master/prototxt/ResNet-50-deploy.prototxt)的
使用

Dropout

意義: 防止模型過擬合;訓(xùn)練模型時,隨機(jī)讓網(wǎng)絡(luò)某些隱含層節(jié)點的    
權(quán)重不工作(不工作的那些節(jié)點可以暫時認(rèn)為不是網(wǎng)絡(luò)結(jié)構(gòu)的一部
分,但是它的權(quán)重得保留下來,只是暫時不更新而已,因為下次樣本
輸入時它可能又得工作了)
用法:
        layer { 
        name: “drop7” 
        type: “Dropout” 
        bottom: “fc7-conv” 
        top: “fc7-conv” 
        dropout_param { 
        dropout_ratio: 0.5 
        } 
        }

ReLU

 意義: 激活函數(shù)的一種;對于給定的一個輸入值x,如果x > 0,
 ReLU層的輸出為x,如果x < 0,ReLU層的輸出為0。
 提醒: 可選參數(shù)negative_slope,此參數(shù)使得x < 0時,ReLU層的輸
 出為negative_slope * x;目前已經(jīng)有了ReLU的進(jìn)化版 – [PReLU]
 (https://arxiv.org/abs/1502.01852)
 用法:
 layer { 
 name: “relu1” 
 type: “ReLU” 
 bottom: “conv1” 
 top: “conv1” 
 relu_param{ 
 negative_slope: [默認(rèn):0] 
 } 
 }

PReLU

 意義: ReLu的進(jìn)化版;。
提醒: 在負(fù)半軸的輸出乘以一個系數(shù),而這個系數(shù)是可學(xué)習(xí)的(你可
以為其指定學(xué)習(xí)率),其中value是系數(shù)的初始值,channel_shared
指定是否在各個通道間共享這個系數(shù)。 據(jù)說有的實驗更快更好地收
斂,但有的實驗準(zhǔn)確率卻有所下降 - 具體效果還是得以具體實驗為準(zhǔn)
(自己沒有用過,不加評論 
-用法:
 layer { 
 name: “relu1” 
 type: “PReLU” 
 bottom: “conv1” 
 top: “conv1” 
 param { 
 lr_mult: 1 
 decay_mult: 0 
 } 
 prelu_param { 
 filler: { 
 value: 0.33 #: 默認(rèn)為0.25 
 } 
channel_shared: false 
} 
}

Solver最優(yōu)化方法

Solver的流程:

  1. 設(shè)計好需要優(yōu)化的對象,以及用于學(xué)習(xí)的訓(xùn)練網(wǎng)絡(luò)和用于評估的測試網(wǎng)絡(luò)。(通過調(diào)用另外一個配置文件prototxt來進(jìn)行)
  2. 通過forward和backward迭代的進(jìn)行優(yōu)化來跟新參數(shù)。
  3. 定期的評價測試網(wǎng)絡(luò)。 (可設(shè)定多少次訓(xùn)練后,進(jìn)行一次測試)
  4. 在優(yōu)化過程中顯示模型和solver的狀態(tài)

在每一次的迭代過程中,solver做了這幾步工作:
1、調(diào)用forward算法來計算最終的輸出值,以及對應(yīng)的loss
2、調(diào)用backward算法來計算每層的梯度
3、根據(jù)選用的slover方法,利用梯度進(jìn)行參數(shù)更新
4、記錄并保存每次迭代的學(xué)習(xí)率、快照,以及對應(yīng)的狀態(tài)。

net: "examples/mnist/lenet_train_test.prototxt"
test_iter: 100
test_interval: 500
base_lr: 0.01
momentum: 0.9
type: SGD
weight_decay: 0.0005
lr_policy: "inv"
gamma: 0.0001
power: 0.75
display: 100
max_iter: 20000
snapshot: 5000
snapshot_prefix: "examples/mnist/lenet"
solver_mode: CPU

接下來,我們對每一行進(jìn)行詳細(xì)解譯:

net: "examples/mnist/lenet_train_test.prototxt"

設(shè)置深度網(wǎng)絡(luò)模型。每一個模型就是一個net,需要在一個專門的配置文件中對net進(jìn)行配置,每個net由許多的layer所組成。注意的是:文件的路徑要從caffe的根目錄開始,其它的所有配置都是這樣。

也可用train_net和test_net來對訓(xùn)練模型和測試模型分別設(shè)定。例如:

train_net: "examples/hdf5_classification/logreg_auto_train.prototxt"
test_net: "examples/hdf5_classification/logreg_auto_test.prototxt"

接下來第二行:

test_iter: 100

這個要與test layer中的batch_size結(jié)合起來理解。mnist數(shù)據(jù)中測試樣本總數(shù)為10000,一次性執(zhí)行全部數(shù)據(jù)效率很低,因此我們將測試數(shù)據(jù)分成幾個批次來執(zhí)行,每個批次的數(shù)量就是batch_size。假設(shè)我們設(shè)置batch_size為100,則需要迭代100次才能將10000個數(shù)據(jù)全部執(zhí)行完。因此test_iter設(shè)置為100。執(zhí)行完一次全部數(shù)據(jù),稱之為一個epoch

test_interval: 500

測試間隔。也就是每訓(xùn)練500次,才進(jìn)行一次測試。

base_lr: 0.01
lr_policy: "inv"
gamma: 0.0001
power: 0.75

這四行可以放在一起理解,用于學(xué)習(xí)率的設(shè)置。只要是梯度下降法來求解優(yōu)化,都會有一個學(xué)習(xí)率,也叫步長。base_lr用于設(shè)置基礎(chǔ)學(xué)習(xí)率,在迭代的過程中,可以對基礎(chǔ)學(xué)習(xí)率進(jìn)行調(diào)整。怎么樣進(jìn)行調(diào)整,就是調(diào)整的策略,由lr_policy來設(shè)置。

lr_policy可以設(shè)置為下面這些值,相應(yīng)的學(xué)習(xí)率的計算為:

  • fixed:   保持base_lr不變.
  • step:    如果設(shè)置為step,則還需要設(shè)置一個stepsize, 返回 base_lr * gamma ^ (floor(iter / stepsize)),其中iter表示當(dāng)前的迭代次數(shù)
  • exp:   返回base_lr * gamma ^ iter, iter為當(dāng)前迭代次數(shù)
  • inv:   如果設(shè)置為inv,還需要設(shè)置一個power, 返回base_lr * (1 + gamma * iter) ^ (- power)
  • multistep: 如果設(shè)置為multistep,則還需要設(shè)置一個stepvalue。這個參數(shù)和step很相似,step是均勻等間隔變化,而multistep則是根據(jù) stepvalue值變化
  • poly:    學(xué)習(xí)率進(jìn)行多項式誤差, 返回 base_lr (1 - iter/max_iter) ^ (power)
  • sigmoid: 學(xué)習(xí)率進(jìn)行sigmod衰減,返回 base_lr ( 1/(1 + exp(-gamma * (iter - stepsize))))
    multistep示例:
base_lr: 0.01
momentum: 0.9
weight_decay: 0.0005
# The learning rate policy
lr_policy: "multistep"
gamma: 0.9
stepvalue: 5000
stepvalue: 7000
stepvalue: 8000
stepvalue: 9000
stepvalue: 9500

接下來的參數(shù):

momentum :0.9

上一次梯度更新的權(quán)重

type: SGD

優(yōu)化算法選擇。這一行可以省掉,因為默認(rèn)值就是SGD??偣灿辛N方法可選擇,在本文的開頭已介紹。

weight_decay: 0.0005

權(quán)重衰減項,防止過擬合的一個參數(shù)。

display: 100

每訓(xùn)練100次,在屏幕上顯示一次。如果設(shè)置為0,則不顯示。

max_iter: 20000

最大迭代次數(shù)。這個數(shù)設(shè)置太小,會導(dǎo)致沒有收斂,精確度很低。設(shè)置太大,會導(dǎo)致震蕩,浪費時間。

snapshot: 5000snapshot_prefix: "examples/mnist/lenet"

快照。將訓(xùn)練出來的model和solver狀態(tài)進(jìn)行保存,snapshot用于設(shè)置訓(xùn)練多少次后進(jìn)行保存,默認(rèn)為0,不保存。snapshot_prefix設(shè)置保存路徑。
還可以設(shè)置snapshot_diff,是否保存梯度值,默認(rèn)為false,不保存。
也可以設(shè)置snapshot_format,保存的類型。有兩種選擇:HDF5 和BINARYPROTO ,默認(rèn)為BINARYPROTO

solver_mode: CPU

設(shè)置運行模式。默認(rèn)為GPU,如果你沒有GPU,則需要改成CPU,否則會出錯。

注意:以上的所有參數(shù)都是可選參數(shù),都有默認(rèn)值。根據(jù)solver方法(type)的不同,還有一些其它的參數(shù),在此不一一列舉。

caffe總共提供了六種優(yōu)化方法:

  • Stochastic Gradient Descent (type: "SGD")
  • AdaDelta (type: "AdaDelta")
  • Adaptive Gradient (type: "AdaGrad")
  • Adam (type: "Adam")
  • Nesterov’s Accelerated Gradient (type: "Nesterov") and
    RMSprop (type: "RMSProp")

1、Stochastic gradient descent(SGD)
隨機(jī)梯度下降(Stochastic gradient descent)是在梯度下降法(gradient descent)的基礎(chǔ)上發(fā)展起來的,梯度下降法也叫最速下降法,具體原理在網(wǎng)易公開課《機(jī)器學(xué)習(xí)》中,吳恩達(dá)教授已經(jīng)講解得非常詳細(xì)。SGD在通過負(fù)梯度

和上一次的權(quán)重更新值Vt
的線性組合來更新W,迭代公式如下:


如果v(t)初始值為0,v(t+1)的方向就與梯度的負(fù)方向相同,那么會加速優(yōu)化,又由于u<1,所以在n多次后可近似看成v1 的 n次方,那么v(t+1)也會變化很小,那時也正是梯度變化很小的時候,所以這種方式還是很有用的。 其中,
是負(fù)梯度的學(xué)習(xí)率(base_lr),
是上一次梯度值的權(quán)重(momentum),用來加權(quán)之前梯度方向?qū)ΜF(xiàn)在梯度下降方向的影響。這兩個參數(shù)需要通過tuning來得到最好的結(jié)果,一般是根據(jù)經(jīng)驗設(shè)定的。如果你不知道如何設(shè)定這些參數(shù),可以參考相關(guān)的論文。
深度學(xué)習(xí)中使用SGD,比較好的初始化參數(shù)的策略是把學(xué)習(xí)率設(shè)為0.01左右(base_lr: 0.01),在訓(xùn)練的過程中,如果loss開始出現(xiàn)穩(wěn)定水平時,對學(xué)習(xí)率乘以一個常數(shù)因子(gamma),這樣的過程重復(fù)多次。
對于momentum,一般取值在0.5--0.99之間。通常設(shè)為0.9,momentum可以讓使用SGD的深度學(xué)習(xí)方法更加穩(wěn)定以及快速。
關(guān)于更多的momentum,請參看Hinton的《A Practical Guide to Training Restricted Boltzmann Machines》。
實例:

base_lr: 0.01   
lr_policy: "step"  
gamma: 0.1     
stepsize: 1000    
max_iter: 3500   
momentum: 0.9  

lr_policy設(shè)置為step,則學(xué)習(xí)率的變化規(guī)則為 base_lr * gamma ^ (floor(iter / stepsize))
即前1000次迭代,學(xué)習(xí)率為0.01; 第1001-2000次迭代,學(xué)習(xí)率為0.001; 第2001-3000次迭代,學(xué)習(xí)率為0.0001,第3001-3500次迭代,學(xué)習(xí)率為10-5

上面的設(shè)置只能作為一種指導(dǎo),它們不能保證在任何情況下都能得到最佳的結(jié)果,有時候這種方法甚至不work。如果學(xué)習(xí)的時候出現(xiàn)diverge(比如,你一開始就發(fā)現(xiàn)非常大或者NaN或者inf的loss值或者輸出),此時你需要降低base_lr的值(比如,0.001),然后重新訓(xùn)練,這樣的過程重復(fù)幾次直到你找到可以work的base_lr。
2、AdaDelta
AdaDelta是一種”魯棒的學(xué)習(xí)率方法“,是基于梯度的優(yōu)化方法(like SGD)。
具體的介紹文獻(xiàn):
M. Zeiler ADADELTA: AN ADAPTIVE LEARNING RATE METHOD. arXiv preprint, 2012.
示例:

net: "examples/mnist/lenet_train_test.prototxt"  
test_iter: 100  
test_interval: 500  
base_lr: 1.0  
lr_policy: "fixed"  
momentum: 0.95  
weight_decay: 0.0005  
display: 100  
max_iter: 10000  
snapshot: 5000  
snapshot_prefix: "examples/mnist/lenet_adadelta"  
solver_mode: GPU  
type: "AdaDelta"  
delta: 1e-6  

從最后兩行可看出,設(shè)置solver type為Adadelta時,需要設(shè)置delta的值。
3、AdaGrad
自適應(yīng)梯度(adaptive gradient)是基于梯度的優(yōu)化方法(like SGD)
具體的介紹文獻(xiàn):
Duchi, E. Hazan, and Y. Singer. Adaptive Subgradient Methods for Online Learning and Stochastic Optimization. The Journal of Machine Learning Research, 2011.
示例:

net: "examples/mnist/mnist_autoencoder.prototxt"  
test_state: { stage: 'test-on-train' }  
test_iter: 500  
test_state: { stage: 'test-on-test' }  
test_iter: 100  
test_interval: 500  
test_compute_loss: true  
base_lr: 0.01  
lr_policy: "fixed"  
display: 100  
max_iter: 65000  
weight_decay: 0.0005  
snapshot: 10000  
snapshot_prefix: "examples/mnist/mnist_autoencoder_adagrad_train"  
# solver mode: CPU or GPU  
solver_mode: GPU  
type: "AdaGrad"  

4、Adam
是一種基于梯度的優(yōu)化方法(like SGD)。
具體的介紹文獻(xiàn):
D. Kingma, J. Ba. Adam: A Method for Stochastic Optimization. International Conference for Learning Representations, 2015.
5、NAG
Nesterov 的加速梯度法(Nesterov’s accelerated gradient)作為凸優(yōu)化中最理想的方法,其收斂速度非???。
具體的介紹文獻(xiàn):
I. Sutskever, J. Martens, G. Dahl, and G. Hinton. On the Importance of Initialization and Momentum in Deep Learning. Proceedings of the 30th International Conference on Machine Learning, 2013.
示例:

net: "examples/mnist/mnist_autoencoder.prototxt"  
test_state: { stage: 'test-on-train' }  
test_iter: 500  
test_state: { stage: 'test-on-test' }  
test_iter: 100  
test_interval: 500  
test_compute_loss: true  
base_lr: 0.01  
lr_policy: "step"  
gamma: 0.1  
stepsize: 10000  
display: 100  
max_iter: 65000  
weight_decay: 0.0005  
snapshot: 10000  
snapshot_prefix: "examples/mnist/mnist_autoencoder_nesterov_train"  
momentum: 0.95  
# solver mode: CPU or GPU  
solver_mode: GPU  
type: "Nesterov"  

6、RMSprop
RMSprop是Tieleman在一次 Coursera課程演講中提出來的,也是一種基于梯度的優(yōu)化方法(like SGD)
具體的介紹文獻(xiàn):
T. Tieleman, and G. Hinton. RMSProp: Divide the gradient by a running average of its recent magnitude. COURSERA: Neural Networks for Machine Learning.Technical report, 2012.
示例:

net: "examples/mnist/lenet_train_test.prototxt"  
test_iter: 100  
test_interval: 500  
base_lr: 1.0  
lr_policy: "fixed"  
momentum: 0.95  
weight_decay: 0.0005  
display: 100  
max_iter: 10000  
snapshot: 5000  
snapshot_prefix: "examples/mnist/lenet_adadelta"  
solver_mode: GPU  
type: "RMSProp"  
rms_decay: 0.98  

最后兩行,需要設(shè)置rms_decay值。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容