訓練過程--學習率與權重衰減
學習率
主要是兩個方面:學習率的初始化和學習率的更新
梯度更新的步長就是學習率
學習率初始化
1)ReLu的線性不飽和激活端着相對于Tanh的雙飽和端(經驗規則0.1),肯定要降量級。
2)b的學習率一般為w的兩倍;
例如Caffe和Alex給的Model基礎都是0.001(W)/0.002(b)。
至于為什麼Bias的學習率是2倍,猜測是更快抑制Wx加權結果,加速學習。
3)總的來說是用一個一般的學習率開始,然後逐漸的減小它。
4)一個建議值是0.1,适用于很多NN的問題,一般傾向于小一點。
5)找出學習率最高且Loss值仍在下降的值來确定最佳初始學習率。
6)learning rate設置為0.01或者原來loss的1/5或者1/10。
學習率更新/學習率退火
1)随步數衰減
每進行幾個周期就根據一些因素降低學習率。典型的值是每過5個周期就将學習率減少一半,或者每20個周期減少到之前的0.1。這些數值的設定是嚴重依賴具體問題和模型的選擇的。在實踐中經驗做法是:使用固定的學習率訓練的同時觀察驗證集錯誤率,每當驗證集錯誤率停止下降,就乘以一個常數(比如0.5)來降低學習率。
2)指數衰減
數學公式是α=α0e−kt,其中α0,k是超參數,t是叠代次數(也可以使用周期作為單位)。
3)1/t衰減的數學公式是α=α0/(1+kt),其中α0,k是超參數,t是叠代次數。
實踐中,随步數衰減的随機失活(dropout)更受歡迎,因為它使用的超參數(衰減系數和以周期為時間單位的步數)比k更有解釋性。
4)理論上大的參數、深的網絡在訓練時需要更少的叠代次數,但是并不是參數越大越好,參數越大使得權重更新緩慢,優化速度下降。
例如:當訓練的精确度沒有提升時,learn rate更新為原來的1/10,learn rate最多變化三次,且整個訓練叠代過程最多不超過74epochs(370K iterations)。
5)learning rate設置為0.01或者原來loss的1/5或者1/10。将LR除以2或5後繼續跑。
6)一個對于調度學習率的建議:如果在驗證集上性能不再增加就讓學習率除以2或者5,然後繼續,學習率會一直變得很小,到最後就可以停止訓練了。
7)很多人用的一個設計學習率的原則就是監測一個比率(每次更新梯度的norm除以當前weight的norm),如果這個比率在10-3附近,如果小于這個值,學習會很慢,如果大于這個值,那麼學習很不穩定,由此會帶來失敗。
8)在SGD方法中,需要構建一個合适的學習率退火方案,來得到一個良好的收斂最小值。人們會認為,像Adam這樣的自适應學習率方法,對不同的學習率更具有魯棒性,因為這些方法能自我更新學習率。但是,即使對于這些方法,好的學習率和最佳的學習率也可能有很大的差别(Andrej KarpathyVerified account說最佳學習率是3e-4)
在調整學習率退火方案和動量參數後,該SGD方法的性能與Adam有得一拼,而且收斂速度更快。另一方面,我們可能認為Adam方法中學習率的自适應性可能模仿了學習速率退火,但是一個明确的退火方案仍然是有幫助的。
9)以前網上有看到過,說是最好按3倍來調整,也就是0.00001、0.00003、0.0001、0.0003、0.001、0.003、0.01、0.03、0.1、0.3……然後确定範圍之後再微調。
學習率調節與loss/acc的關系
1)找出學習率最高且Loss值仍在下降的值來确定最佳當前學習率。
2)在一開始的時候,我們可以将其設大一點,這樣就可以使weights快一點發生改變,從而讓你看出cost曲線的走向(上升or下降),進一步地你就可以決定增大還是減小learning rate。
3)如何自動調節學習率
一個簡單有效的做法就是,當validation accuracy滿足 no-improvement-in-n規則時,本來我們是要early stopping的,但是我們可以不stop,而是讓learning rate減半,之後讓程序繼續跑。
下一次validation accuracy又滿足no-improvement-in-n規則時,我們同樣再将learning rate減半(此時變為原始learni rate的四分之一)…繼續這個過程,直到learning rate變為原來的1/1024再終止程序。(1/1024還是1/512還是其他可以根據實際确定)。【PS:也可以選擇每一次将learning rate除以10,而不是除以2.】
4)經驗法則,很多時候跑不到一個好結果,可能是沒有充分下降,learning rate收縮得過快的話,可能還沒到底就幾乎不動了,收縮過慢的話,可能沒有耐心等待學習率降到一個比較低的數就停止了。用最常用的指數下降法的話,很容易發生以上兩種現象。
我現在一般使用固定學習率,如果觀察到loss已經下降不動,隻在一個區間内抖動的話,就停止學習,将學習率除以10繼續重複這個過程。從0.01開始,一般搞到1e-6就差不多啦。
權重衰減weight decay
在機器學習或者模式識别中,會出現overfitting,而當網絡逐漸overfitting時網絡權值逐漸變大,因此,為了避免出現overfitting,會給誤差函數添加一個懲罰項,常用的懲罰項是所有權重的平方乘以一個衰減常量之和。其用來懲罰大的權值。
regularization controlled by weight_decay.
weight decay(權值衰減)的使用既不是為了提高收斂精确度,也不是為了提高收斂速度,其最終目的是防止過拟合。
在損失函數中,weight decay是放在正則項(regularization)前面的一個系數,正則項一般指示模型的複雜度,所以weight decay的作用是調節模型複雜度對損失函數的影響,若weight decay很大,則複雜的模型損失函數的值也就大。
在設置上,Weight Decay是一個L2 penalty,是對參數取值平方和的懲罰。
權值衰減懲罰項使得權值收斂到較小的絕對值,而懲罰大的權值。因為大的權值會使得系統出現過拟合,降低其泛化性能。
權重衰減的數值設置
1)一般,Weight Decay=0.001。更多的,base_lr與weight_decay相差大概是兩到三個數量級。
2)我通過對淺層寬模型設置2-3倍默認的Weight Decay往往效果是最好的。太大了實際會嚴重幹擾第一個Learning Rate階段的精度。太小了(也就是很多論文的默認設置)會距離收斂最優情形有差距。 CIFAR100 Top-1 84.36%是在Weight Decay=0.001上獲得的。也就是說,在實踐裡我比其他人更喜歡加大Weight Decay。
3)實際工程實踐中,大家還是更傾向于使用權重衰減,因為它包含的超參數少一些,計算簡單一些,可解釋性稍微高一點。
權重衰減的規範化參數L1和L2
權值衰減歸一化系數λ的理解
為防止過度拟合,為訓練準則增加權重衰減項,L2歸一化為訓練準則增加λ∑iθ2i項,L1增加λ∑i|θi|。
L2對比較大的值懲罰比較大,對應高斯先驗,L1将沒有太大用的參數變成0,即變稀疏,對應Laplace密度先驗。
權重衰減、L2和高斯假設的理解
然而我們有大量的論文去考察參數的取值,有三點發現:1. 不是高斯分布。2. 取值可以量子化,即存在大量可壓縮空間3. 因為Relu, BN的存在使得其有界。
那麼根據Loss function的設置求導之後,我們得到一個公式:W( t+ 1) = W ( t ) − lr ∗ delta(W)− lr ∗ wd ∗ W ( t )也就是說,實際上我們可以把它化簡為W(t)首先以(1- lr ∗ wd )的比例等比例收縮,然後再根據學習率、梯度方向進行一次調整。
這個一收縮不要緊,我們現在做CNN已經不用Sigmoid+AveragePooling了,我們用的是Relu+MaxPooling,也就是說這一收縮,可能有的幹脆就從激發變成了不激發。可有可無的激發也就消失掉了,有點像DropOut,當然如果這個Neuron真有用也可以回頭再靠梯度把它學成激發狀态。所以說有了這個東西會規避過拟合。現在很少有流行模型使用DropOut了吧?竊以為,道理就在這。最後,假設W隻能取0和1兩個值,那麼L1-Penalty和L2-Penalty其實是等價的。實際上的W取值,是處于我說的這種極端情況和高斯分布之間的,所以按找傳統統計裡L2-Penalty的思路去思考Weight Decay是不對的。現在CNN裡面有很多paper在濫用高斯假設,慎讀。
base_lr與weight_decay
1)base_lr與weight_decay相差大概是兩到三個數量級
例如:base_lr=0.01;weight_decay=0.0002
2)
最重要的是要關注學習率。一些研究人員(比如Alex Krizhevsky)使用的方法是,監視更新範數和權值範數之間的比率。比率取值大約為10¯³。如果取值過小,那麼學習會變得非常慢;如果取值過大,那麼學習将會非常不穩定甚至失敗。
梯度更新的步長就是學習率
以前網上有看到過,說是最好按3倍來調整,也就是0.00001、0.00003、0.0001、0.0003、0.001、0.003、0.01、0.03、0.1、0.3……然後确定範圍之後再微調。
如果α取值過大,可能會導緻叠代不收斂,從而發散。所以,一開始α的取值也要比較小心才行。
随着叠代次數的增加,一般需要慢慢減小α,因為這樣能得到一個更好的結果。至于怎麼減小α,也是有很多種策略,可以每次叠代都更新α的值,如α = 0.96, 也可以 α=α, 也可以每叠代幾次更新一次α的值,方法很多,什麼方式更好呢?實驗吧……這跟數據有很大關系。
關于正則化參數λ的取值,因為才疏學淺,了解得不多,所以不便多說。不過一般來說λ不會取太小,我的感覺是0.001和1之間吧,也可以每次叠代都更新λ的值。比如一開始取比較小的值,然後随着叠代次數的增加,慢慢增加λ。
總結下,學習速率α越大,收斂越快,正則化參數λ越大,收斂越慢。收斂速度太快,可能一下子就越過極值點,導緻發散;太慢則可能需要叠代非常多次,導緻時間成本非常高。所以,α和λ取到一個合适的值,還是非常重要的。
3)其實梯度下降算法,在使用的時候無非是要考慮到2個方面,一個是方向,一個是步長,方向決定你是否走在了優化的道路上還是優化道路的負方向,步長是決定你要走多久才能到最優的地方。對于第一個問題很好解決,就是求梯度,梯度的負方向就是了。難的是求步長,如果步子太小,則需要很長的時間才能走到目的地,如果步子過大可能在目的地的周圍來走震蕩。所以重點在于如何選擇步長。
4)early-stop,其實也是很成熟的方法了,大概思路是在訓練的過程中,使用驗證集周期性的來測試當前計算出來的參數,在驗證集上測試當前參數對驗證集的效果,如果效果可以,就保存起來,當很長一段時間都是此效果的話那麼就叠代停止,該組參數就認為是不錯的參數。這個方法叫做交叉驗證,但是我看到有的地方寫的是交叉驗證用于超參的選擇,而這個地方我不是選取的超參,所以不知道到底用對了沒有。
帶随機數的超參數調整
深度神經網絡涉及很多的超參數,如學習率大小、L2正則化系數、動量大小、批量大小、隐層神經元數目、層數、學習率衰減率等。
1)随機搜索
由于你事先并不知道哪些超參數對你的問題更重要,因此随機搜索通常是比網格搜索(grid search)更有效的調參策略。
2)對數空間搜索
對于隐層神經元數目和層數,可以直接從均勻分布采樣進行搜索。而對于學習率、L2正則化系數、和動量,在對數空間搜索更加有效。例如:
import random
learning_rate = 10 ** random.uniform(-5, -1) # From 1e-5 to 1e-1
weight_decay = 10 ** random.uniform(-7, -1) # From 1e-7 to 1e-1
momentum = 1 - 10 ** random.uniform(-3, -1) # From 0.9 to 0.999
選擇正則化的參數
選擇參數λ的目标是希望模型的訓練誤差和泛化能力都很強。
具體的做法:
1)參考前人的經驗。例如Hinton大哥的那篇A Practical Guide to Training RestrictedBoltzmann Machines等等。
2)就是在訓練之前,我們大概計算下這時候的loss項的值是多少?Ω(w)的值是多少?然後針對他們的比例來确定我們的λ,這種啟發式的方法會縮小我們的搜索空間。
3)另外一種最常見的方法就是交叉驗證Cross validation了。先把我們的訓練數據庫分成幾份,然後取一部分做訓練集,一部分做測試集,然後選擇不同的λ用這個訓練集來訓練N個模型,然後用這個測試集來測試我們的模型,取N模型裡面的測試誤差最小對應的λ來作為我們最終的λ。λ的搜索空間我們盡量廣點,所以一般對λ的搜索空間的選擇一般就是2的多少次方了,從-10到10啊什麼的。
fineturn時的學習率設置
1) 使用多個而不是單一學習率
差分學習率(Differential Learning rates),改變前面網絡層。
大部分已有網絡(如Resnet、VGG和Inception等)都是在ImageNet數據集訓練的,因此我們要根據所用數據集與ImageNet圖像的相似性,來适當改變網絡權重。在修改這些權重時,我們通常要對模型的最後幾層進行修改,因為這些層被用于檢測基本特征(如邊緣和輪廓),不同數據集有着不同基本特征。
在實際中,一般将學習率的縮小倍數設置為10倍。例如:在網絡中從前往後的不同層分别設置為0.001,0.01,0.1。
超大批量訓練的trick
包含以下兩種技術手段:
1)線性縮放(Krizhevsky 于 2014 年提出):如果我們将 batch size 由 B 增加至 kB,我們亦需要将學習率由η增加至 kη(其中 k 為倍數)。
2)預熱模式(Goyal 等人于 2017 年提出):如果我們使用高學習率(η),則應以較小的η作為起點,而後在前幾次 epochs 中逐步将其遞增至較大η。
我來說兩句