1. 程式人生 > >訓練過程--學習率與權重衰減

訓練過程--學習率與權重衰減

學習率

  主要是兩個方面:學習率的初始化和學習率的更新

  梯度更新的步長就是學習率

學習率初始化

  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 Karpathy‏Verified 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

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 中逐步將其遞增至較大η。