在機器學習中,有很多的問題並沒有解析形式的解,或者有解析形式的解但是計算量很大(譬如,超定問題的最小二乘解),對於此類問題,通常我們會選擇采用一種迭代的優化方式進行求解。
這些常用的優化算法包括:梯度下降法(Gradient Descent),共軛梯度法(Conjugate Gradient),Momentum算法及其變體,牛頓法和擬牛頓法(包括L-BFGS),AdaGrad,Adadelta,RMSprop,Adam及其變體,Nadam。
-
梯度下降法(Gradient Descent)
想象在一個山峰上,在不考慮其他因素的情況下,如何行走才能最快的下到山腳?當然是選擇最陡峭的地方,這也是梯度下降法的核心思想:它通過每次在當前梯度方向(最陡峭的方向)向前“邁”一步,來逐漸逼近函數的最小值。
在第 $ n $ 次迭代中,參數 $ \theta _{n}=\theta _{n-1}+\Delta \theta $, 將損失函數在 $ \theta _{n-1} $ 處進行一階泰勒展: $$ L(\theta_{n})=L(\theta_{n-1}+\Delta \theta )\approx L(\theta_{n-1})+{L}'(\theta _{n-1})\Delta \theta $$
為了使 $ L(\theta_{n})<L(\theta_{n-1})L(\theta_{n})<L(\theta_{n-1}) $ ,可取 $ \Delta \theta =-\alpha {L}'(\theta _{n-1})\Delta \theta =-\alpha {L}'(\theta _{n-1}) $,即得到梯度下降的迭代公式: \[\theta_{n}: =\theta _{n-1}-\alpha {L}'(\theta _{n-1})\]
梯度下降法根據每次求解損失函數 $ L $ 帶入的樣本數,可以分為:全量梯度下降(計算所有樣本的損失),批量梯度下降(每次計算一個batch樣本的損失)和隨機梯度下降(每次隨機選取一個樣本計算損失)。
PS:現在所說的SGD(隨機梯度下降)多指Mini-batch-Gradient-Descent(批量梯度下降),后文用 $ g_{n} $ 來代替 $ {L}'(\theta _{n}) $
SGD的優缺點:
優點:操作簡單,計算量小,在損失函數是凸函數的情況下能夠保證收斂到一個較好的全局最優解。
缺點: α是個定值(在最原始的版本),它的選取直接決定了解的好壞,過小會導致收斂太慢,過大會導致震盪而無法收斂到最優解;對於非凸問題,只能收斂到局部最優,並且沒有任何擺脫局部最優的能力(一旦梯度為0就不會再有任何變化)
PS:對於非凸的優化問題,我們可以將其轉化為對偶問題,對偶函數一定是凹函數,但是這樣求出來的解並不等價於原函數的解,只是原函數的一個確下界。

-
Momentum
SGD中,每次的步長一致,並且方向都是當前梯度的方向,這會收斂的不穩定性:無論在什么位置,總是以相同的“步子”向前邁。
Momentum的思想就是模擬物體運動的慣性:當我們跑步時轉彎,我們最終的前進方向是由我們之前的方向和轉彎的方向共同決定的。Momentum在每次更新時,保留一部分上次的更新方向:$$ \Delta \theta _{n}=\rho \Delta \theta _{n-1}+g_{n-1} $$ $$ \theta _{n}:=\theta _{n-1}-\alpha g_{n-1} $$
這里 $ \rho $ 值決定了保留多少上次更新方向的信息,值為0~1,初始時可以取0.5,隨着迭代逐漸增大; $ \alpha $ 為學習率,同SGD.

優點:一定程度上緩解了SDG收斂不穩定的問題,並且有一定的擺脫局部最優的能力(當梯度為0時,仍可能按照上次迭代的方向沖出局部最優點),直觀上理解,它可以讓每次迭代的“掉頭方向不是哪個大”。左圖為SDG,右圖為Momentum。
缺點:這里又多了另外一個超參數 $ \rho $ 需要設置,它的選取同樣會影響到結果。
-
Nesterov Momentum
Nesterov Momentum又叫做Nesterov Accelerated Gradient(NAG),是基於Momentum的加速算法。
通過上述,我們知道,在每次更新的時候,都在 $ \rho \Delta \theta _{n-1}+{L}'(\theta _{n})\rho \Delta _{n-1}+{L}'(\theta _{n}) $ 走 $ \alpha $ 這么遠,那么我們為什么不直接走到這個位置,然后從這個位置的梯度再走一次呢?為此,引出NAG的迭代公式: $$ \Delta \theta _{n}=\rho \Delta \theta _{n-1}+g(\theta _{n-1}-\alpha \Delta \theta _{n-1}) $$ $$ \theta _{n}:=\theta _{n-1}-\alpha \Delta \theta _{n} $$
我們可以這樣理解,每次走之前,我們先用一個棍子往前探一探,這根棍子探到的位置就是 $ L(\theta _{n-1}-\alpha \Delta \theta _{n-1})$ ,然后我們求解此處的梯度:如果梯度大,我們邁一大步,反之,邁一小步。如果我們將上式改寫一下: $$ \Delta \theta _{n}=\rho \Delta \theta _{n-1}+g_{n-1}+\rho(g_{n-1}-g_{n-2}) $$ $$ \theta _{n}:=\theta _{n-1}-\alpha \Delta \theta _{n} $$
如果這次的梯度比上次大,那么我們有理由認為梯度還會繼續變大!於是,當前就邁一大步,因為使用了二階導數的信息(二階導數>0即一階導單調遞增,也即 $ {g}'_{n-1}>g'_{n-2} $ ,因此可以加快收斂。圖片來自Hinton在Coursera上DL課程的slides。

藍色的線代表原始的Momentum更新方向,在NAG中,我們先求解得到了這個方向,也即棕色的線,然后求解此處的梯度(紅色的線),從而得到最終的前進方向。
-
共軛梯度法(Conjugate Gradient)
同樣的,CG也在選取前進方向上,對SGD做了改動。它對性能有很大的提升,但是不適用高維數據,求解共軛的計算量過大。這里推薦一個專門講解CG的painless conjugate gradient,講的很細致。
與上述算法對前進方向進行選擇和調整不同,后面這些算法主要研究沿着梯度方向走多遠的問題,即如何選擇合適的學習率α。
-
Adagrad
即adaptive gradient,自適應梯度法。它通過記錄每次迭代過程中的前進方向和距離,從而使得針對不同問題,有一套自適應調整學習率的方法:

可以看到,隨着迭代的增加,我們的學習率是在逐漸變小的,這在“直觀上”是正確的:當我們越接近最優解時,函數的“坡度”會越平緩,我們也必須走的更慢來保證不會穿過最優解。這個變小的幅度只跟當前問題的函數梯度有關, $ \epsilon $ 是為了防止除0,一般取值為 $ 10^{-7} $ 。
優點:解決了SGD中學習率不能自適應調整的問題 。 缺點:學習率單調遞減,在迭代后期可能導致學習率變得特別小而導致收斂及其緩慢。同樣的,我們還需要手動設置初始 $ \alpha $ .
-
Adagrad-like
在《No More Pesky Learning Rates》一文中,提到另外一種利用了二階導信息的類adagrad算法。它是由Schaul於2012年提出的,使用了如下形式的更新公式:

Hn 是二階梯度函數的Hession矩陣,這里只是用了前t個梯度來放縮學習率。
它是由LecCun提出來的一種逼近Hession矩陣的更新方式的變體,原始版本為:
$$ \Delta \theta =\frac{1}{\left | diag(H_{n}) \right |+\epsilon }g_{n-1} $$ $$ \theta _{n}:=\theta _{n-1}-\Delta \theta _{n} $$
優點:緩解了Adagrad中學習率單調遞減的問題 缺點:Hession矩陣的計算必須采用較好的近似解, $ t $ 也成為了新的超參數需要手動設置,即我們需要保留參數前多少個梯度值用來縮放學習率。
-
Adadelta
Adadelta在《ADADELTA: An Adaptive Learning Rate Method 》一文中提出,它解決了Adagrad所面臨的問題。定義:

則更新的迭代公式為:

這里 $ \rho $ 為小於1的正數,隨着迭代次數的增加,同一個 $ E[g^{2}]_{i} $ 會因為累乘一個小於1的數而逐漸減小,即使用了一種自適應的方式,讓距離當前越遠的梯度的縮減學習率的比重越小。分子是為了單位的統一性,其實上述的算法中,左右的單位是不一致的,為了構造一致的單位,我們可以模擬牛頓法(一階導\二階導),它的單位是一致的,而分子就是最終推導出的結果,具體參考上面那篇文章。這樣,也解決了Adagrad初始學習率需要人為設定的問題。
優點:完全自適應全局學習率,加速效果好
缺點:后期容易在小范圍內產生震盪
-
RMSprop
其實它就是Adadelta,這里的RMS就是Adadelta中定義的RMS,也有人說它是一個特例, $ \rho =0.5 $ 的Adadelta, α仍然依賴全局學習率。
-
Adam
Adam是Momentum和Adaprop的結合體,我們先看它的更新公式:
它利用誤差函數的一階矩估計和二階矩估計來約束全局學習率。
優點:結合Momentum和Adaprop,穩定性好,同時相比於Adagrad,不用存儲全局所有的梯度,適合處理大規模數據 。
一說,adam是世界上最好的優化算法,不知道用啥時,用它就對了。
詳見《Adam: A Method for Stochastic Optimization》
-
Adamax
它是Adam的一個變體,簡化了二階矩估計的取值:

-
Nadam和NadaMax
Nadam是帶有NAG的adam:
每次迭代的 $ \phi $ 都是不同的,如果參考Adamax的方式對二階矩估計作出修改,我們可以得到NadaMax,詳見:http://cs229.stanford.edu/proj2015/054_report.pdf
-
牛頓法
牛頓法不僅使用了一階導信息,同時還利用了二階導來更新參數,其形式化的公式如下:

回顧之前的 $ \theta _{n}=\theta _{n-1}+\Delta \theta $ ,我們將損失函數在 θn-1 處進行二階泰勒展開:

要使 $ L(\theta _{n})<L(\theta _{n-1}) $ ,我們需要極小化
,對其求導,令導數為零,可以得到:

也即牛頓法的迭代公式,拓展到高維數據,二階導變為Hession矩陣,上式變為:
![]()
直觀上,我們可以這樣理解:我們要求一個函數的極值,假設只有一個全局最優值,我們需要求得其導數為 $ 0 $ 的地方,我們把下圖想成是損失函數的導數的圖像 $ f(x) $ ,那么:

我們一直這樣做切線,最終 $ x_{n} $ 將逼近與 f'(x)的0點,對於原函數而言,即


牛頓法具有二階收斂性,每一輪迭代會讓誤差的數量級呈平方衰減。即在某一迭代中誤差的數量級為0.01,則下一次迭代誤差為0.0001,再下一次為0.00000001。收斂速度快,但是大規模數據時,Hession矩陣的計算與存儲將是性能的瓶頸所在。
為此提出了一些算法,用來近似逼近這個Hession矩陣,最著名的有L-BFGS,優於BFGS,可適用於並行計算從而大大提高效率,詳見:Large-scale L-BFGS using MapReduce
有人會問,既然有這么多方法,為什么很多論文里面還是用的SGD?需要注意的是,其他的方法在計算性能和收斂方面確實優秀很多,有的甚至不用人為干涉,它會自適應的調整參數,但是,在良好的調參情況下,SGD收斂到的最優解一般是最好的。
參考:https://blog.csdn.net/qsczse943062710/article/details/76763739
