在
(上)中,我們介紹了對餵送資料所做的變化處理(Mini-batch),以及對損失函示的表示所做的變化處理(加入 l-p 處罰項)。接下來,我們將會對設定學習率(learning rate)(本篇)和參數更新方法(下)所做的變化處理來做介紹。現在,我們就來看看如何調整學習率:
學習率在最佳化領域中又可被稱為 step size 或 step length,也就是當次迭代參數更新的步進量。在標準的梯度下降學習法中,學習率在整個訓練過程保持固定的。然而,對於整個最佳化的歷程而言,固定的學習率往往會造成問題,尤其我們可以預見當最佳化演算法搜尋一段時間,逐漸接近一個最小值以及周鄰的平坦區域時,仍舊不變的學習率可能會造成麻煩。
因為曲度(curvature)不同而造成最陡梯度演算法震盪。圖中為橢圓形的損失函數。長軸為曲度最大的區域,並且對應海森矩陣(Hessian Matrix)的最大特徵值,而短軸則為曲度最小的區域,對應到最小特徵值。因為最大曲度方向,維持最陡梯度,因此即使使用梯度做為總步進量,也會造成震盪。
關於固定學習率的另外一個問題,則是給予每一個參數同樣的學習率。通常這個問題來自於參數的維度過高,而資料在參數空間裡呈稀疏分佈的問題,以至於有些參數更新的頻率並沒有很高。
欲對不同參數產生不同的 學習率,可以對梯度計算取 L2 範數或指數加權的移動平均值,再由這些值來決定每個參數學習率的變更。
現在就這兩個主要問題分別講述目前在深度學習領域中常用的解決方案。
學習率排程(Schedule learning rate)
排程學習率的方法可以根據演算法執行的迭代次數來做排程,又可被稱為時間基礎的調降學習率。在這個方法中,學習率會是迭代的數目的函示,並隨著迭代數目的增加而線性或非線性的方式調降學習率。有時不會用函式映射的方式來單調減少學習率,反而使用查詢表找出對應的學習率,但大致的趨勢都是隨著迭代數目的增加而單調減少學習率。
另一個學習率排程方法則是利用當次迭代和初始損失函式差來決定是否要增加學習率。若損失函式差為負的,表示演算法是往降低算失函式的方向前進,所以我們應該要增加學習率。倘若損失函式差為正的話,則表示震盪可能的發生,則我們需要調降學習率。
前者避免訓練已經進行一段時間,在接近最小值,處於較為平坦區域時使用較大的學習率而造成錯過最小值,大幅度震盪的效果。這個方法不會把損失函示曲面考慮在內,放心地或天真地認為演算法在時機成熟處,自會在最佳值的鄰近處徘徊,因此一味的下降。當然,也有人提出循環式的學習率調整排程(Cyclical learning rates),在這類的方法學習率將會週期性的增加和縮小。而改變學習率的方法包括了使用三角形法,和使用 cosine 三角函式來降低學習率,到達最小值時重設學習率為初始值。
循環式的學習率調整排程之所以可行,是基於一個假設。該假設認為比起一個擁有陡峭斜坡的最小值(sharp minimum),一個具有平坦坡面的最小值(flat minimum)更不易泛化(generalization)。而循環式的學習率調整排程,放棄以往單調下降的方式來調整學習率,雖然學習率上升,短期內會造成損失函式值升高,然而長期來看有助於達成長程目標,也就是較快速地穿越鞍點緩區,降落在平坦區域的最小值,進而最佳泛化。然而,這類的方法因為可調參數的數量較多,又沒有直接考慮損失曲面,所以並沒有很廣泛地使用。若有興趣的讀者,可以在延伸閱讀一中找到相關文章。
後者藉著考慮了損失函式的曲面的複雜而改進了前者,然而卻僅考慮了在最佳化歷程中的起始點,因此遠遠不足以捕捉損失函示的局部改變。比如說,曲度較大的區域,損失函式值總是變化的比梯度要快,在這樣的情況中,學習率需要隨之縮小才不至於錯過重要區域(critical region)。
上圖是三角形循環式學習率調整排程,中圖為加入固定差距的三角形循環式學習率調整排程,下圖為加入指數衰退的三角形循環式學習率調整排程法
圖片來源:延伸閱讀[1]
為了能捕捉上述的微妙的曲面差異,就有人利用了近似於物理的動量觀念。引入過去的梯度運算歷史,而達到與調整學習率同樣效果的目的。
為了解決不同的參數需要不同學習率的問題,另外一種方法,則是動態改變學習率(Adaptive learning rate)。在實現上是利用指數衰退加權平均(Exponentially Weighted Average)來計算梯度變異數(Variance),以達到對每一參數動態調整學習率。
我們會先就指數衰退加權平均來做簡單介紹,然後會進到幾種動態改變學習率的方法。在動態改變學習率之後,在下篇將會介紹動量學習法和目前相當受歡迎的 Adam 演算法。
指數衰退加權平均(Exponentially Weighted Average)
指數權重移動平均值是以指數衰退加權的方式來計算移動平均(Moving Average)。由於這個計算值會考慮被測量物的軌跡,並企圖將過去的軌跡納入此次的運算中,而造成平滑的估算。
若想從數學式去理解它,就是利用一個值介於零與一之間的可調參數( hyper-parameter) 來對過去梯度量做加權,我們稱呼這個可調參數為指數衰退權重。而之所以被稱為指數衰退權重,因為這個權重值會給予歷史久遠的梯度值幾乎等於零的權重,而其他較為新的歷程則依據迭代數目做指數衰退的加權計算。如此一來,我們不需要記錄所有迭代的更新歷史,而只需一個變數即可,充分節省了記憶體空間。
應用指數權重移動平均值來計算梯度平均,擁有下列的特性:當使用靠近 1 的梯度權重值,會取用從前較多的迭代數目來計算移動平均,計算曲線也較為平滑,如受到過去物理慣性的影響,軌跡較少小幅度震盪,即能夠強健抵抗雜訊。若是靠近 0 的梯度權重值,則計算參數梯度的移動平均近似於無動量的計算,也就是軌跡較易有震盪的情形,較難抵抗雜訊但能夠快速反應參數變化的情形。
然而,是哪些歷史會被遺忘,有一個簡單的公式來計算。每一個移動平均可以近似於(1 - 指數衰退權重)的倒數。也就是當你的指數衰退權重為 0.1 時,移動平均可以記住約一個迭代的梯度。而當指數衰退權重為 0.9 時, 移動平均可以記住約十個迭代的梯度。
使用指數權重移動平均值來計算過去的氣溫。左上圖為未取加權平均的每一天的氣溫觀察值。右上圖紅線和右下圖黃線則為使用較低權重值所計算而成的移動平均。左下圖綠線則為使用較高權重值所計算而成的移動平均。
更深入的介紹可以參考列在參考資料中,由吳恩達教授關於 Exponentially Weighted Average 的課程。接著,就讓我們來看看如何應用指數衰退加權平均於動態調整學習率。
動態調整學習率(Adaptive learning rate)
以自然語言領域中所使用的 embedding 查詢矩陣參數,來說明巨大參數更新時所遭遇的問題。在這個查詢矩陣中,每一個字彙都可以對應到一個長度由使用者自訂的向量。由於字彙的數目是沒有限制的,字彙的頻率又相差甚巨,讀者可以想像 embedding 查詢矩陣參數,有極大的字彙維度但極稀疏的更新。稀疏更新的結果造成稀疏梯度,以及在不同參數間,擁有大梯度變異數(Variance)。
最佳化的專家們為了解決這個問題,希望透過估算第二統計動差(moment)來作為調節學習率的量。第二統計動差與梯度的變異數(variance)成正比的,有時被稱為未減去平均值的變異數(uncentered variance)「註一」。倘若某參數梯度的第二統計動差較小時,就會給予較大的幅度調降其學習率,而當另一參數梯度的第二統計動差較大時,該參數的學習率會做小幅度的調降,如此一來達到動態調整學席率的結果。
而根據該如何估算梯度的第二統計動差又可以分為兩個方法:一是將全梯度改變歷程都包括在估算梯度第二統計動差,以及利用前面所述的指數衰退權重平均來「忘記」較舊的歷程,而專注於離當次迭代較為相近的歷程。前者,我們會討論 Adagrad 和它的小兄弟們,後者則會以 RMSProp 為例,同樣也不會遺漏該方法的變異版本。
Adagrad
若以定性的方法來描述 Adagrad 所使用的公式,則是增加一個梯度變異累積變數來記錄梯度的第二統計動差。而這個梯度變異累積變數則會先取方根(現在為正比於標準差)後再以倒數的方式調整當次迭代的學習率。Adagrad 需要使用者給予一個初始學習率,在最佳化的過程中在使用前面所述的梯度變異累積變數來調降初始學習率。若有一參數,其更新頻率較低(如,字彙出現頻率較低),導致梯度變異小時,則增加學習率,好大步前進。相反的,當另一參數更新頻率教高(如,字彙出現頻率較高),也就是梯度變異較大時,則調降會學習率,採取小碎步的方式來度過。
在這裡有個數學細節,為了避免梯度無變化,也就是靠近梯度為零的區域,造成梯度累積變數的值極小且極為靠近零,接著導致梯度調整為無限大的值(零的倒數),所以需要一個極小的常數值來使計算的數值穩定。
Adagrad 已經成功地應用在巨量參數的模型,如訓練
GloVe embedding。然而,這個方法仍有它的弱點。首先
Adagrad 使用全歷史來計算梯度第二統計動差,而當迭代數成長時,會造成學習率接近於零,導致學習停滯的狀況。其次,
Adagrad 對初始值敏感。若初始值的梯度過大,則
Adagrad 會在初始時就調降初始學習率到一個極小值,而造成無效率的學習。為了這些情況,有些最佳化演算法專家則提出了
Adagrad 的弟弟版本,
Adadelta。
Adadelta
拆開 Adadelta 的名字來看,字首(Ada)是繼承 Adagrad 採用梯度第二統計動差來調節學習率,但以指數衰退加權移動平均來計算。如前所述,指數衰退加權移動平均會「忘記」過久的歷史。另一個修正的重點,可由字尾的 delta 來記憶,即是增加了一個參數更新估算值來替代初始學習率。這個值其實就是梯度變化的移動平均值再取方根值,該值也和使用移動平均估算的動量值成正比。關於動量,會在下中詳細提及。
RMSprop
RMSprop 如同 Adadelta 為了避免使用所有的梯度歷史而採用指數衰退權重平均來計算梯度平方歷史,比起 Adagrad,和動量相似 RMSprop 還多了一個指數衰退權重的可調函數( hyper-parameter)。其他的細節與 Adagrad 幾乎都相同,這裡就不贅述。但,當我們準備要和 RMSprop 離別前,簡短地提到 Rprop。
Rprop
Rprop 是一個只考慮梯度正負號,而不考慮梯度大小的學習演算法。而這樣做的理由是,函式的梯度經常不能提供有效的資訊,甚至再乘上學習率後經常造成步進量消失或爆炸。為了解決這個方法 Rprop 在更新參數時只取梯度的正負號來當作更新的方向,步進量則完全由學習率控制。然而,Rprop 必須要用使用所有的資料來計算正負號(full batch),為了能保留 Rprop 對隨機梯度的抵抗性以及保留迷你批次的計算效率和探索能力,就開發了 RMSprop。
Rprop 之所以不適合使用在隨機或迷你批次梯次下降法,是因為這類型的下降法需要多次更新,而每次更新都只有取部分資料點平均,在只有考慮正負號來更新學習率的 Rprop 會造成參數大幅更新的情形。 更多關於 Rprop 可以參考延伸閱讀二。
在瞭解如何使用指數衰退移動平均來達到動態調整後,接著我們來仔細看看如何對參數更新方法所做的變化處理來改善梯度下降法。在這個類別下,主要會提及利用指數衰退係數來實現動量學習法。
註釋:
[註一]
Moment 翻作
統計動差是來自於
國家教育研究院 ,同時也有人翻譯成「矩」。
Moment 在統計上的定義為變數的 n 次方期望值。這裡的 n 是次方變數,代表所求的統計動差為第 n 統計動差(the n-th order moment)。若 n 為一,則為第一統計動差,也就是平均值。而 n 為二,則為第二統計動差,也就是變數的平方期望值,或未減去平均值的變異數(uncentered variance)。
參考資料:
- A Learning-rate Schedule for Stochastic Gradient Methods to Matrix Factorization (英,paper)
- Adadelta: An Adaptive Learning Rate Method (英,paper)
延伸閱讀:
- “Setting the learning rate of your neural network.”(英):在這篇由 Jeremy Jordan 所寫的文章中,詳細解釋循環式的學習率調整排程(Cyclical learning rates)和 warm restart 學習率的方法。在學習率調整排程的小節,作者先介紹了如何在每一個週期使用三角形法來增加和減少學習率,並以圖解的方式瞭解公式。隨後,介紹了另一個 warm restart 學習率的方法。在這個 warm restart 的方法中,每個週期包含了一個使用 consine 函式來調降學習率,當達到使用者設定的最小學習率值時,做 “hard restart”,也就是將學習率重設為初始值。使用重設方法的隨機梯度下降法被簡稱為 SGDR,取自於 Stochastic Gradient Descent with Warm Restarts。採取循環式的學習率調整排程,除了如前述能有較佳的泛化能力,也有學者在每一個週期都對訓練中的模型分別存成不同的模型,在預測時則用 ensemble 的方法集合所有的模型來做預測。
- RProp(英):該文介紹 Rprop 演算法。該演算法源自於 1993 年的論文:“A direct adaptive method for faster backpropagation learning: the RPROP algorithm”。在這篇貼文中,作者利用圖解釋在標準梯度下降法中,使用學習率來調整梯度的作法可能會損失重要的資訊。比如說,在平坦區域中梯度的值通常都非常微小,若再乘上學習率可以說演算法根本動不了。在更新參數時,若只取梯度的正負號來決定更新的方向,步進的量則完全由學習率決定。但,為了達到動態調整學習率的效果,每一個參數的梯度正負號會用來決定學習率的大小。若該參數此次迭代的梯度正負號與上一個迭代相同,則增加學習率。若不相同的話,表示接近一個重要區域(critical region)則減少學習率。實際上使用的公式,該文亦有提供。在文章的最後,提到了一切實作的細節以及使用 PyTorch 完成的原始碼可供參考。