小夕曾經收到過一個提問:“小夕,我的模型總是在前幾次迭代後很快收斂了,陷入到了一個區域性最優點,怎麼也跳不出來,怎麼辦?”
本文不是單純對這個問題的回答,不是羅列工程tricks,而是希望從理論層面上對產生類似疑問的人有所啟發。
真的結束於最優點嗎?
我們知道,在區域性最優點附近,各個維度的導數都接近0,而我們訓練模型最常用的梯度下降法又是基於導數與步長的乘積去更新模型引數的,因此一旦陷入了區域性最優點,就像掉進了一口井,你是無法直著跳出去的,你只有連續不間斷的依託四周的井壁努力向上爬才有可能爬出去。更何況梯度下降法的每一步對梯度正確的估計都在試圖讓你墜入井底,因此勢必要對梯度“估計錯很多次”才可能僥倖逃出去。那麼從數學上看,什麼才是區域性最優點呢?
這個問題看似很白痴,很多人會說“區域性最優點不就是在loss曲面上某個一階導數為0的點嘛”。這就不準確啦,比如下面這個馬鞍形狀的中間的那個點:
(圖片來自《deep learning》)
顯然這個點也是(一階)導數為0,但是肯定不是最優點。事實上,這個點就是我們常說的鞍點。
顯然,只用一階導數是難以區分最優點和鞍點的。
我們想一下,最優點和鞍點的區別不就在於其在各個維度是否都是最低點嘛~只要某個一階導數為0的點在某個維度上是最高點而不是最低點,那它就是鞍點。而區分最高點和最低點當然就是用二階導數(斜率從負變正的過程當然就是“下凸”,即斜率的導數大於0,即二階導數大於0。反之則為“上凹”,二階導數小於0)。也就是說,若某個一階導數為0的點在至少一個方向上的二階導數小於0,那它就是鞍點啦。
那麼二階導數大於0和小於0的概率各是多少呢?由於我們並沒有先驗知識,因此按照最大熵原理,我們認為二階導數大於和小於0的概率均為0.5!
那麼對於一個有n個引數的機器學習/深度學習模型,“loss曲面”即位於n+1維空間(loss值為縱軸,n個引數為n個橫軸)。在這個空間裡,如果我們通過梯度下降法一路下滑終於滑到了一個各方向導數均為0的點,那麼它為區域性最優點的概率即,為鞍點的概率為,顯然,當模型引數稍微一多,即n稍微一大,就會發現這個點為鞍點的概率會遠大於區域性最優點!
好吧我再囉嗦的舉個栗子,已經反應過來的同學可以跳過這個栗子:
假設我們的模型有100個引數(實際深度學習模型中一般會遠大於100),那麼某一階導數為0的點為區域性最優點的概率為約為,而為鞍點的概率則為。就算我們的模型在訓練時使用了特別厲害的“超級梯度下降法”,它可以每走一步都恰好踩在一個一階導數為0的點上,那麼從數學期望上來看,我們需要走步才行。而實際的projects中,哪怕資料集規模為千萬級,我們分了100萬個batches,然後要迭代100次,那也僅僅是走了步,你真的覺得運氣可以辣麼好的走到區域性最優點上去嗎?所以實際中,當我們的深度學習模型收斂時,幾乎沒有必要認為它收斂到了一個區域性最優點,這完全等同於杞人憂天。
也就是說,如果最後模型確實在梯度下降法的指引下收斂到了一個導數為0的點,那這個點幾乎可以肯定就是一個鞍點。
如果我們的模型真的收斂到鞍點上了,會很可怕嗎?
這就又回到了文章開頭的那副馬鞍狀的圖。
顯然,站在馬鞍中央的時候,雖然很難翻過兩邊的山坡,但是往前或者往後隨便走一步就能摔下馬鞍!而在文章《batch size》中小夕講過,我們預設使用的mini-batch梯度下降法本身就是有噪聲的梯度估計,哪怕我們位於梯度為0的點,也經常在某個mini-batch下的估計把它估計偏了,導致往前或者往後挪了一步摔下馬鞍,也就是mini-batch的梯度下降法使得模型很容易逃離特徵空間中的鞍點。
那麼問題來了,既然區域性最優點很難踩到,鞍點也很容易逃離出去,那麼為什麼我們的模型看起來是收斂了呢?
初學者可能會說 “誒誒,會不會是學習率太大了,導致在“鞍點”附近震盪?” 首先,鞍點不像最優點那樣容易震盪,而且哪怕你不斷的減小學習率繼續讓模型收斂,你這時計算output層或者後幾層的梯度向量的長度時會發現它依然離0很遙遠!(這句話是有實驗支撐的,不過那篇論文我找不到惹,也忘了名字了。熱心的觀眾幫忙補充一下哦)
難道,踩到的鞍點太多,最後恰好收斂到一個跳不下去的鞍點身上了?
雖然高維空間中的鞍點數量遠遠大於最優點,但是鞍點的數量在整個空間中又是微不足道的:按前面的假設,假設在某個維度上隨機一跳有10%的概率踩到導數為0的點,那麼我們在101維的空間中的一步恰好踩到這個點上的概率為,也就是說在101維空間裡隨機亂跳的時候,有的可能性踩到鞍點身上。因此,即使有難以逃離的鞍點,那麼被我們正好踩到的概率也是非常小的。
所以更令人信服的是,在高維空間裡(深度學習問題上)真正可怕的不是區域性最優也不是鞍點問題,而是一些特殊地形。比如大面積的平坦區域:
(圖片來自《deep learning》)
在平坦區域,雖然導數不為0但是卻不大。雖然是在不斷下降但是路程卻非常長。對於優化演算法來說,它需要走很多很多步才有可能走過這一片平坦區域。甚至在這段地形的二階導數過於特殊的情況下,一階優化演算法走無窮多步也走不出去(設想一下,如果終點在一米外,但是你第一次走0.5米,後續每一步都是前一步的一半長度,那麼你永遠也走不到面前的一米終點處)。
所以相比於栽到最優點和鞍點上,優化演算法更有可能載到這種類似平坦區的地形中(如果這個平坦區又是“高原地帶”,即loss值很高的地帶,那麼恭喜你悲劇了)。更糟糕的是,由於高維地形難以視覺化,還有很多更復雜的未知地形會導致假收斂,一旦陷入到這些危險地形中,幾乎是無解的。
所以說,在深度學習中,與其擔憂模型陷入區域性最優點怎麼跳出來,更不如去好好考慮:
如何去設計一個儘量沒有“平坦區”等危險地形的loss空間,即著手於loss函式的設計以及深度學習模型的設計;
儘量讓模型的初始化點遠離空間中的危險地帶,讓最優化遊戲開始於簡單模式,即著手於模型引數的初始化策略;
讓最優化過程更智慧一點,該加速衝時加速衝,該大膽跳躍時就大膽跳,該慢慢踱步時慢慢走,對危險地形有一定的判斷力,如梯度截斷策略;
開外掛,本來下一步要走向死亡的,結果被外掛給拽回了安全區,如batch normalization策略等。