梯度下降法簡單來說就是一種尋找目標函數最小化的方法。張戎:深度學習中的優化演算法在深度學習中,經常有人會拿下面這幅圖來比較各種優化演算法的性質,包括傳統的 SGD,Momentum SGD,AdaGrad,RMSProp 和 Adam 等。不過光看圖可能無法理解其中的精妙之處,本文將會從數學的基礎知識出發,初步介紹深度學習中的一些優化演算法,最後進行一些簡單的案例分析。 數學基礎知識回顧 一元函數的導數與 Taylor 級數在微積分中,函數 在點 上的導數定義為: 它在幾何上指的就是函數 在 上的切線方向。通常來說,為了計算某個函數 的最大值或者最小值,通常都會計算它的導數 ,然後求解方程 就可以得到函數的臨界點,進一步判斷這些臨界點是否是最大值或者最小值。但是臨界點並不一定是全局最大值或者全局最小值,甚至不是局部的最大值或者局部最小值。例如:函數 ,它的導數是 ,因此 是它的臨界點。但 則不是這個函數的局部最大值或者局部最小值點,因為 且 。從 Taylor 級數的角度來看, 在 附近的 Taylor 級數是對於臨界點 而言,它滿足條件 。當 時,可以得到 是 的局部最小值;當 時,可以得到 是 的局部最大值。而對於上面的例子 而言,臨界點 的二階導數則是 ,因此使用上面的方法則無法判斷臨界點 是否是局部極值。多元函數的梯度和 Taylor 級數對於多元函數 而言,同樣可以計算它們的「導數」,也就是偏導數和梯度,i.e. 它的梯度可以定義為: 而多元函數 在點 上的 Taylor 級數是:其中 表示 Hessian 矩陣。如果 是臨界點,並且 Hessian 矩陣是正定矩陣的時候, 在 處達到局部極小值。梯度下降法從數學上的角度來看,梯度的方向是函數增長速度最快的方向,那麼梯度的反方向就是函數減少最快的方向。那麼,如果想計算一個函數的最小值,就可以使用梯度下降法的思想來做。假設希望求解目標函數 的最小值,可以從一個初始點 開始,基於學習率 構建一個迭代過程:當 時,其中 ,一旦達到收斂條件的話,迭代就結束。從梯度下降法的迭代公式來看,下一個點的選擇與當前點的位置和它的梯度相關。反之,如果要計算函數 的最大值,沿著梯度的反方向前進即可,也就是說:其中 。整體來看,無論是計算函數的最大值或者最小值,都需要構建一個迭代關係 ,那就是: 也就是說對於所有的 ,都滿足迭代關係 。所以,在以上的兩個方法中,我們可以寫出函數 的表達式為: 深度學習中的優化演算法 在本文中,假設 是每個樣本的損失函數, 表示一個關於輸入 和參數 的函數,並且 表示 所對應的目標值。 案例分析 案例1: 針對這個函數 而言,從數學上我們可以輕易地得到最小值點就是 。不過在這裡我們可以驗證隨機梯度下降法的效果。首先計算函數 的梯度為:其次,給定一個隨機的初始點 ,通過梯度可以得到迭代公式為:其中 表示學習率, 表示迭代次數。因此,可以計算出具體的公式為:於是可以得到: 意思就是說,使用隨機梯度下降法我們可以得到函數 的最小值是 。案例2: 不過,隨機梯度下降法也有著自身的侷限性。針對很多高維非凸函數而言,鞍點的數量其實遠遠大於局部極小值(極大值)的數量。因此,如何快速的逃離鞍點就是深度學習中大家所研究的問題之一。而比較簡單的鞍點就是馬鞍面函數 中的 點。而函數 在 上並沒有最小值,因為 。 同時,函數 的偏導數是:而 在點 上則滿足以下幾個性質:也就是說, 這一點的 Hessian 矩陣並不是正定矩陣。隨機梯度下降法:如果初始點是 ,那麼隨機梯度下降法(SGD)就可以寫成:對於所有的 ,有 其中 是學習率。使用動量的隨機梯度下降法:如果初始點是 ,初始速度是 ,學習率是 ,動量參數是 ,那麼使用動量的隨機梯度下降法就可以寫成: ,AdaGrad 演算法:如果初始點是 ,學習率是 , 是小常數,那麼 AdaGrad 演算法就可以寫成: ,其中 是學習率, 是一個小常數。Case 1: 當 時,如果使用隨機梯度下降法,就可以得到 , 因此, 。 通過隨機梯度下降法(SGD)在初始值為 的前提下並不能計算出函數 的最小值,而是會停止在 鞍點這個地方,最終無法逃離鞍點。同理,如果使用基於動量的 SGD 演算法,就要看初始速度的設置了,如果初始的速度為 ,那麼最終都會收斂到 這個點上。不過,如果 ,那麼就可以在一定次數的迭代之後逃離 。根據同樣的分析思路,在本文中所寫的 AdaGrad,RMSProp,Adam 演算法中,如果初始點是 並且演算法參數都是默認的話,使用這些方法同樣無法逃離鞍點 ,也就是說最終都會收斂到 上。Case 2: 在這種情況下,可以考慮在 的基礎上給縱坐標加上一個微小的擾動。不妨假設初始點為 。下面計算各個演算法在這個初始值下的收斂效果。在實際的應用中,需要迭代的次數越少越好。於是,通過計算 的值,就可以進一步判斷哪個演算法(SGD,Momentum SGD,AdaGrad,RMSProp,Adam)更加容易逃離鞍點。隨機梯度下降法:通常情況下, 可以設置為 。從隨機梯度下降法的公式來看,就可以得到如下迭代公式:其實, ,i.e. 使用梯度下降法同樣可以找到函數 的最小值。但是,如果 ,則 需要滿足條件:換言之,需要迭代 次左右纔能夠使得 。 AdaGrad 演算法:通常來說,在 AdaGrad 演算法中,演算法的參數默認值是 和 。由於初始值 ,所以計算可以得到:最後通過寫程序就可以證明,在 AdaGrad 的默認參數下,只需要 次左右的迭代就可以實現 。RMSProp 演算法:在這種情況下,為了簡單起見,可以令衰減速率 ,那麼同樣可以寫出迭代公式為: ,有在 RMSProp 裡面,一般來說小常數 , 。通過直接計算可以知道,在這種情況和參數設置下,在迭代了 輪左右的時候,就會出現 的情況。整體來說,在初始值為 的情況下,無論是 SGD,Momentum SGD,AdaGrad 演算法,還是 RMSProp 演算法,都會逃離鞍點 。只不過 AdaGrad 和 RMSProp 演算法的逃離速度比 SGD 快了許多。 10種常用梯度提升優化演算法整理這裡枚舉了流行的深度學習框架中常見的Gradient Descent演算法,包括不限於Tensorflow、pyTorch、Caffe、Keras。可以作為回頭查看的一個資料。 Gradient Descent Optimizer是幹啥的?主要通過以下方式對gradient descent起作用: 修改learning rate;比如RMSprop; 修改?L/?w;通常使用梯度的移動平均值; 兩者都有。比如Adam和AMSGrad。 這裡簡單說明一下learning rate schedulers和Gradient Descent Optimizer的差異: gradient descent optimizer通過將學習速率乘以一個梯度的factor來進行調整; learning rate schedulers通常是將學習速率乘以一個常數或者時間函數的一個因子; optimizer名稱、發表年份、是否修改lr和gradientNotation t-time step w-需要被更新的權重/參數 α-learning rate學習率 ?L/?w-需要被最小化的損失函數L的梯度 目錄: Stochastic Gradient Descent Momentum NAG AdaGrad RMSprop Adadelta Adam AdaMax Nadam AMSGrad 直觀解釋 1.Stochastic Gradient Descent使用當前梯度?L/?w乘以學習率α來更新當前權重w。 2.MomentumMomentum使用V即歷史和現在的梯度的exponential moving average來替代當前梯度來更新權重。V初始化為0,β通常取值0.9。 詳見論文鏈接:[(PDF) Some methods of speeding up the convergence of iteration methods](https://www.researchgate.net/publication/243648538_Some_methods_of_speeding_up_the_convergence_of_iteration_methods)3.Nesterov Accelerated Gradient (NAG)與Momentum類似,但使用的V為投影梯度(projected gradients)的exponential moving average。V初始化為0,β通常取值0.9。 第二個等式中的最後一項是投影梯度。具體過程為: 使用先前的V更新權重w,得到w*; 使用w*進行前向傳播; 獲取投影梯度 ?L/?w*; 相應計算V和W; 詳見論文鏈接:[On the importance of initialization and momentum in deep learning](On the importance of initialization and momentum in deep learning)4.AdaGrad(Adaptive gradient)自適應梯度。通過將learning rate除以S的平方根進行更新。S指的是歷史和當前的梯度的平方的累加。Gradient部分與SGD中保持一樣。S初始化為0,加 確保分母不為0。α通常取值0.01,通常取值10??。 詳見論文鏈接: [http://jmlr.org/papers/v12/duchi11a.html]5.RMSprop(Root mean square prop)RMSProp是對AdaGrad的一種改進。使用梯度的exponential moving average而不是使用累計的平方梯度和。S初始化為0, = 0.001, =0.9, =10?? 詳見論文鏈接:http://www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf6.AdaDelta(Adaptive delta)AdaDelta是對AdaGrad的另一種改進。Delta表示當前權重w與新更新權重w之間的差異。AdaDelta和RMSprop之間的區別在於,AdaDelta使用Delta平方的exponential moving average替代learning rate。D和S初始化為0, =0.95, =10?? 詳見論文鏈接:[1212.5701 ADADELTA: An Adaptive Learning Rate Method](ADADELTA: An Adaptive Learning Rate Method)7.Adam(Adaptive Moment Estimation)Adam是對Momentum和RMPprop的一個結合。 梯度部分像Momentum裏一樣使用V即梯度的exponential moving average來替代當前梯度來更新權重。 學習率部分像RMSprop裏一樣用學習率除以S(即梯度的exponential moving average)來進行學習。V和S都初始化為0, = 0.001, =0.9, =0.999, =10??。 詳見論文鏈接:[1412.6980 Adam: A Method for Stochastic Optimization](Adam: A Method for Stochastic Optimization)8.AdaMax梯度部分像Momentum裏一樣使用V即梯度的exponential moving average。S為梯度 p-norm 的exponential moving average。V和S初始化為0, = 0.002, =0.9, =0.999。 詳見論文鏈接:[1412.6980 Adam: A Method for Stochastic Optimization](Adam: A Method for Stochastic Optimization)9.NadamNadam是Nesterov和Adam optimizer的首字母縮寫。 Adam Optimizer可以被寫成如下: Nadam利用Nesterov將 替換成當前 來提前更新梯度: V和S初始化為0, = 0.002, =0.9, =0.999, =10??10.AMSGradAdam的另一個變體是AMSGrad。不同的地方在於每次對S進行修正保證當前的S值始終大於前一time step的。V和S初始化為0, = 0.001, =0.9, =0.999, =10??。 11. 直觀解釋那為什麼optimizers中 gradient迭代選擇的exponential moving average,learning rate迭代選擇root mean square呢?1) gradient迭代為什麼選擇的exponential moving average?我們要進行權重迭代時,我們唯一能用的值就是當前的梯度值。但是僅使用當前的梯度是不夠的,我們希望能利用到之前的梯度來更好的指導梯度下降的方向。所以需要對歷史和當前的梯度進行「組合」。試想最簡單的方法就是直接平均,但這樣意味著每一個梯度都有相同的權重。這不太符合直觀感覺,我們希望更近的梯度值獲取更高的權重。而exponential moving average正好可以做到。2) learning rate迭代為什麼選擇root mean square?迭代learning rate的目的是為了能適應梯度。當梯度值很大時,我們希望更新是小小的,否則當前的權重就會產生很大改變。為了產生這樣效果,將學習率learning rate除以當前的梯度,就能得到一個「適應」好的學習率的值。Learning rate應該始終為正,為了確保它使始終是正的,我們對梯度進行求絕對值或平方求和取平方根。我們也希望把梯度裏的思想引入到learning rate中,希望使用歷史數據來更好地引導學習率進行調整。我們將採用過去梯度的exponential moving avergae,然後取其平方根,即root mean square。 謝邀。既然你打開了這個回答,我想你一定不是為了看梯度下降的公式是什麼,畢竟百科上有梯度下降_百度百科。我猜你一定是想了解為何梯度下降會起作用,而不是純粹記憶公式。只有知道了梯度下降原理是什麼才懂得自己怎麼修改梯度下降的公式。我分三點:1.直觀理解 2. 梯度下降怎麼做(附帶推薦編程實踐) 3. 梯度下降有啥用親們不要只收藏不點贊嘛 1。直觀理解梯度下降 其實它沒啥就是讓計算機不斷猜最小值的那個點自變數x在哪,猜大了讓它小一點,猜小了讓它大一點。猜個幾萬次就猜中了。怎麼猜的根據梯度猜的。梯度是啥,導數。怎麼根據導數猜的?高中老師教過當前這個點導數大於0證明它周圍單調增,最小值點肯定比當前猜的這個點小,那我下次就猜小一點(因為我想找最小值點在哪)。導數小於0同理。沒看懂?沒關係看下面的。 想像下:按照上面那個圖的特點,假設這個圖放大1萬倍,大到你不能一眼看到最小值。那麼要你找最小值對應的自變數x,你怎麼找??記住我們目的是為了找自變數x,記住我們目的是為了找x你將可能會在電腦屏幕看到原先那個圖的局部,按照它們單調性來分主要有這三種情況 當你遇到情況1:單調下降,導數為負(梯度為負),要想找到函數的最小值所對應的自變數的值(曲線最低點對應x的值)怎麼走?當然是水平向右滑啦,也就是讓x增大,此時隨著x增大,函數值是減小(下降)的(梯度下降含義懂了吧哈哈就這個意思)當你遇到情況2:單調上升,導數為正(梯度為正),要想找到函數的自變數的值(曲線最低點對應x的值)怎麼走?當然是水平向左滑啦,也就是讓x減小,此時隨著x減小,函數值減小的(也就是梯度下降)。綜上所述: 梯度下降:兩個意思,1.根據梯度(導數)的符號來判斷最小值點x在哪; 2. 讓函數值下降(變小)。 梯度就是導數(對於多維就是偏導數) 梯度下降作用是找到函數的最小值所對應的自變數的值(曲線最低點對應x的值)。記住我們目的是為了找x. 2。梯度下降怎麼做的? 梯度下降它是一個函數f(x)找它的最小值所在的那個點 的一種方法。 怎麼找呢?它原理就是猜,按照一定規則的猜。怎麼猜的? 高中知識告訴我們 函數單調遞增。增大 函數值也會變大。我們想找最小值那麼最小值那個點 肯定比在當前這個點 小。那麼我們讓 小一點。 然後計算 。 同理,只不過得讓 大一點。 直到f(x)==0,因為鍋底很平坦導數是0.此時就找到了最小值所在的那個點 。買大買小,按照一定規則猜。梯度下降就是按照導數來猜最小值所在的那個點x在哪。 參考專欄《適合初學者的機器學習神經網路理論到實踐》裡面這幾個文章。歡迎點贊,和關注 @Ai醬 。 Ai醬:適合初學者的神經網路理論到實踐(1):單個神經元+隨機梯度下降學習邏輯與規則?zhuanlan.zhihu.com 4。梯度下降有啥用? 機器學習和神經網路,還有各種數學建模問題。最終不是有個目標函數|損失函數|代價函數|誤差函數,不管叫啥函數反正他們都一樣。反正就是求他最小值點x。不是求最小值點?加個負號不就好了。注意是最小值點而不是最小值。為啥?因為機器學習和神經網路等等他們損失函數|代價函數|誤差函數最小值肯定是0啊。我們想要的是當誤差最小時,最優自變數|權重|參數是啥。不同問題叫法不一樣,但是一樣的是他們都是想找自變數而不是函數值。最後大家如果想看看更詳細的回答可以看看司南牧:{高中生能看懂的}梯度下降是個啥??zhuanlan.zhihu.com初學者機器學習資料分享Q羣(718566626)Ai醬:{高中生能看懂的}再見香農,決策樹的本質是什麼Ai醬:[易懂]如何理解論文中的那些評估方法性能指標概念名詞{召回率 ROC AUC 交叉驗證}從本質如何理解機器學習計算機生態圈是怎麼樣的?你長大後才意識到的,對於15歲以前的小孩子,哪些能力、技能和品質是含金量最高的?計算機領域近幾年會不會飽和? 每一個機器學習模型都有一個損失函數,學習的目的,就是將損失函數最小化。然而,並非所有函數都能一下子就找到最小值,甚至都沒有最小值。(比如 )所以,很多機器學習模型都以凸函數作為損失函數,因為凸函數保證了其有最小值。 凸函數介紹: 凸函數的定義:如果函數 在某段區間上的任意兩個點,都有 ,則稱其在某段區間上凸函數。學過高等數學的人可能會有疑惑,這不是凹函數的定義嗎?沒錯,我們所說的凸函數對應的是英文中的Convex Function。而某些教材(比如同濟大學高等數學)把這種函數稱為凹函數,而把Concave Function 稱為凸函數。定義與機器學習中的定義完全相反。可以理解成:凸函數就是在某段區間只有一個低谷的函數。假設,一個凸函數是一元函數形式,那麼它的函數值畫出來,應該是這樣的: 也就是 直線永遠高於曲線 如果是像下圖這樣,有好幾個低谷的部分,那麼每個低谷為局部最小值,而最低的那個低谷則稱為全局最小值。 而二維的話,最小值則是碗狀的: 梯度下降法 現在我們瞭解了凸函數的定義,如果損失函數是凸函數,那麼學習的目標自然就是尋找某個凸函數的最小值。用來尋找凸函數最小值的最常用方法,就是梯度下降法。這種方法從直觀來理解是很容易的。以一元函數為例。假設我們的目標函數是一個一元凸函數。我們可以用如下步驟來獲得其最小值(已知損失函數是 ): 隨機取一個值 ; 算出對應的 ; 計算 處損失函數 的導數; 從 開始,沿著該處導數的方向增加 ,取值為 ,也就是說: 的值為 在 出的斜率; 重複循環2-4步,直到達到退出條件(比如設定循環N次後停止) 對應三維的情況,可以想像在一個小球在碗中,讓小球沿著當時所在點的切線方向(此時的切線方向是一個二維向量)向前走一步,直到走到碗底為止。 梯度下降中的超參數設置 上面的梯度下降中提到了一個參數 ,它又稱為步長。這種演算法是需要人為設置的,而非用來學習的參數,所以叫做超參數。步長是梯度下降演算法中最重要的超參數,設置時需要精心考慮。比如,像下圖左邊,如果步長太大,始終落不到最低點。 而如果改成右側那樣的小步長就可以找到最低點了(但如果太小,收斂速度可能會很慢)。 梯度下降的問題 如果目標函數有多個極小值點(很多個低谷),那麼如果開始位置不理想,很可能導致最終卡在一個局部極小值。比如下圖的例子。這是梯度下降演算法的一大挑戰。 所以,人們提出了很多梯度下降的變體,比如: 使用隨機梯度下降(Stochastic Gradient Descent, SGD)增加方差,來避免陷入局部極小值 加入衝量(Momentum),來衝出局部極小值 在加入了衝量的梯度下降中,再加入Nesterov項,避免沖的過快 使用Adagrad演算法,改變學習率,讓前期避免掉入局部極小值的同時,保證後期的穩定收斂 RMSprop 有一張圖完美地展示了這些演算法的下降過程: 這篇回答節選自我的專欄《機器學習中的數學:微積分與最優化》,和大家一起談談梯度下降法。梯度下降法的思路非常清晰明瞭,且實現過程也比較簡單,是求解無約束最優化問題中的一種最常用、最基礎的迭代方法。 1.梯度概念回顧 在梯度下降法當中,顧名思義,梯度是其中最為重要的核心工具和武器。因此,我們有必要回顧一下關於梯度的一些重要概念和特性:首先,多元函數 在點 ?處的梯度 是一個 維向量: ;其次,多元函數 在點 ?處的梯度向量與該函數過點 ?處的等位線的切線向量相互正交;最重要的是,沿著梯度 向量方向,函數 的值的增長速度最快,相對應的,沿著負梯度,也就是 向量的方向,函數 的值下降的最快。 2.類比盲人下山的例子 為了形象的描述這個演算法的思想和過程,我們舉一個盲人下山的例子:利用迭代法,在一個多元函數上去探索極小值的過程,我們可以把他想像成一個盲人下山的過程,盲人看不到整個山的全貌,不清楚全局,擁有的能力只是去感知他所站立位置四周的坡度,而他的目標卻是要下到山的最低點。假設盲人站在山的任意一個位置點,開始下山的過程,首先他感知一下自己四周的山坡,選擇坡度最陡峭的一個方向,然後沿著這個方向走一小步,到達一個新的位置點,然後不斷重複上面的「感知坡度」-「選擇最陡峭的方向」-「走一小步」的過程,不斷更新自己的位置點。最終什麼時候停下來呢?那應該是在盲人身處某個點的時候發現四周坡度已經很「平」了,他就判斷自己下到了山底,此時就能停下來了。 3.梯度下降法的演算法思路 那麼,有了上面的思維過程打基礎,我們再來實際理解梯度下降法就不難了:我們從隨機的初始點 ?開始迭代,這就好比那個盲人站在了山上的任意一個位置點上。函數的極小值點在哪,最終該往哪走?我們也不知道,我們就好比那個盲人什麼也看不到一樣。但是,我們也可以利用梯度這個工具來找到 ?鄰域內具體哪個方向上函數的下降速度最快,即 負梯度向量的方向,我們沿著他來微小的更新我們取值點的位置,就好比盲人沿著最陡峭的方向走了一小步。我們就不停的重複「計算梯度」-「沿著負梯度的方向」-「更新位置值」的過程,直到突然間我們發現,梯度已經很小了,小於我們預設的閾值,此時的位置點就認定為我們找到的函數的局部極小值點,這就好比盲人發現四周的坡度已經很平了。梯度下降法的背後,其實還是離不開多元函數的一階泰勒展開以及函數的線性近似的思想:就拿簡單的二元函數來說, 在點 ?處的一階泰勒展開式為: ,這個泰勒近似是在 ?的小的鄰域範圍內近似效果較好,因此迭代的步子不能邁得過大,太大的話 ?處的梯度的精度就失效了。那麼進一步的,從點 ?處迭代到下一個點 ?,二者之間的迭代關係具體是怎樣的呢?很顯然,按照我們前面所說的,我們是按照負梯度 的向量方向,從點 ?走到了點 ?,那麼向量 ?的方向就和 ?處的梯度方向正好反向,在表達式上滿足下面的關係: )?我們對表達式稍作調整,就有: 。此時,進一步進行整理,迭代的關係初見雛形: 。最後,我們令: ?,整個迭代的關係就簡化成了如下的形式: ?。我們把他一般化,就有了最終的迭代公式: ?。此時,距離問題的徹底解決似乎還有一道坎沒有跨過,那就是這個 ?,他是什麼?他應該確定為多少?這都是一個未知的問題。這個 ?,我們稱之為學習率,他是迭代步長與梯度向量模的比值,我們一般把學習率設置為一個比較小的固定常數。這樣,一方面能夠滿足迭代精度的要求,另一方面還可以動態調整迭代的步長,當坡度陡峭、梯度值較大時,我們的步長相應變大,快速下山,而當我們快要接近山底,坡度變得平緩,梯度變小的時候,步長也相應變小,以免一大步跨過極小值點的情況發生。 4.梯度下降法的代碼實現 通過上面的理論知識的講解,我們對梯度下降法的原理應該已經掌握的比較透徹了。那麼接下來我們實際動手,用python語言來實際操練一下這個極值點迭代求取的常用演算法:我們舉一個例子 ?,下面就來求這個簡單的二元函數的極小值點。在這個實際的例子中,我們令初始的迭代點為 ,學習率 ,如果梯度的模長小於閾值 時則停止迭代。我們按照梯度下降法的基本思路來尋找函數的極小值點:代碼片段:from matplotlib import pyplot as plt import numpy as np from mpl_toolkits.mplot3d import Axes3D fig = plt.figure() ax = Axes3D(fig) def f(p): return 0.2 * p[0] ** 2 + p[1] ** 2 def numerical_gradient(f, P): h = 1e-6 x = P[0] y = P[1] dx = (f(np.array([x + h / 2, y])) - f(np.array([x - h / 2, y]))) / h dy = (f(np.array([x, y + h / 2])) - f(np.array([x, y - h / 2]))) / h return np.array([dx, dy]) def gradient_descent(cur_p, lambda_=0.1, epsilon=0.0001, max_iters=10000): for i in range(max_iters): grad_cur = numerical_gradient(f, cur_p) if np.linalg.norm(grad_cur, ord=2) &< epsilon: break cur_p = cur_p - grad_cur * lambda_ ax.scatter(cur_p[0], cur_p[1], f(cur_p), color=r) print(局部極小值為:{}.format(cur_p)) return cur_p x1 = np.arange(-4, 4, 0.01) x2 = np.arange(-4, 4, 0.01) x1, x2 = np.meshgrid(x1, x2) ax.plot_surface(x1, x2, f(np.array([x1, x2])), color=y, alpha=0.3) p0 = np.array([3, 4]) gradient_descent(p0) plt.show() 運行結果:局部極小值為:[2.40866325e-04 5.16743037e-19] 從結果圖中我們發現,在原函數的圖像上,一連串的紅點表示從初始點開始,不斷的向極小值點迭代逼近。之前我們曾經提到過,函數 在具體某個點 ?處的等位線的切線向量是和該點處的梯度向量相互正交的,我們利用之前學過的知識,在 平面上繪製函數的等位線圖,並且將各個迭代的取值點也投影到 平面上,來實際驗證一下迭代點的軌跡與等位線的相互關係:代碼片段:from matplotlib import pyplot as plt import numpy as np def f(p): return 0.2*p[0]**2 + p[1] ** 2 def numerical_gradient(f, P): h = 1e-6 x = P[0] y = P[1] dx = (f(np.array([x+h/2, y]))-f(np.array([x-h/2, y])))/h dy = (f(np.array([x, y+h/2]))-f(np.array([x, y-h/2])))/h return np.array([dx, dy]) def gradient_descent(cur_p, lambda_=0.1, epsilon=0.0001, max_iters=10000): for i in range(max_iters): grad_cur = numerical_gradient(f, cur_p) if np.linalg.norm(grad_cur, ord=2) &< epsilon: break cur_p = cur_p - grad_cur * lambda_ plt.plot(cur_p[0],cur_p[1], ko, markersize=3) return cur_p x1 = np.arange(-5, 5, 0.01) x2 = np.arange(-5, 5, 0.01) x1, x2 = np.meshgrid(x1, x2) C = plt.contour(x1, x2, f(np.array([x1, x2])), 60) plt.clabel(C, inline=True, fontsize=12) p0 = np.array([3, 4]) gradient_descent(p0) plt.show() 運行結果: 從等位線圖上來看,迭代點的軌跡在各個等位線上滿足與等位線的相互正交關係。 5.關於演算法的補充討論 梯度下降法整個思路非常易於理解,實現起來比較簡單,但是他的性能並不是最優的,最主要的原因是他基於一階泰勒展開的函數近似,為了保證其梯度的有效性,因此每次迭代的步長都比較小,使得收斂的速度比較慢,要迭代多輪才能收斂到極值點附近。因此,後續有很多的演算法對梯度下降法都進行了一些改良,提升了他的性能。 此內容節選自我的專欄《機器學習中的數學:微積分與最優化》,如有興趣,歡迎訂閱! 機器學習中的數學:微積分與最優化_專欄?gitbook.cn-------------------------------------------------------------------------------------------當然還有《機器學習中的數學》系列專欄,歡迎大家閱讀,配合食用,效果更佳~機器學習中的數學:概率統計_專欄?gitbook.cn機器學習中的數學:線性代數_專欄?gitbook.cn機器學習中的數學:概率圖與隨機過程_專欄?gitbook.cn有訂閱的問題可諮詢微信:zhangyumeng0422 推薦閱讀:
梯度下降法簡單來說就是一種尋找目標函數最小化的方法。
張戎:深度學習中的優化演算法
在深度學習中,經常有人會拿下面這幅圖來比較各種優化演算法的性質,包括傳統的 SGD,Momentum SGD,AdaGrad,RMSProp 和 Adam 等。不過光看圖可能無法理解其中的精妙之處,本文將會從數學的基礎知識出發,初步介紹深度學習中的一些優化演算法,最後進行一些簡單的案例分析。
一元函數的導數與 Taylor 級數
在微積分中,函數 在點 上的導數定義為: 它在幾何上指的就是函數 在 上的切線方向。
通常來說,為了計算某個函數 的最大值或者最小值,通常都會計算它的導數 ,然後求解方程 就可以得到函數的臨界點,進一步判斷這些臨界點是否是最大值或者最小值。但是臨界點並不一定是全局最大值或者全局最小值,甚至不是局部的最大值或者局部最小值。
例如:函數 ,它的導數是 ,因此 是它的臨界點。但 則不是這個函數的局部最大值或者局部最小值點,因為 且 。
從 Taylor 級數的角度來看, 在 附近的 Taylor 級數是
對於臨界點 而言,它滿足條件 。當 時,可以得到 是 的局部最小值;當 時,可以得到 是 的局部最大值。而對於上面的例子 而言,臨界點 的二階導數則是 ,因此使用上面的方法則無法判斷臨界點 是否是局部極值。
多元函數的梯度和 Taylor 級數
對於多元函數 而言,同樣可以計算它們的「導數」,也就是偏導數和梯度,i.e. 它的梯度可以定義為:
而多元函數 在點 上的 Taylor 級數是:
其中 表示 Hessian 矩陣。如果 是臨界點,並且 Hessian 矩陣是正定矩陣的時候, 在 處達到局部極小值。
梯度下降法
從數學上的角度來看,梯度的方向是函數增長速度最快的方向,那麼梯度的反方向就是函數減少最快的方向。那麼,如果想計算一個函數的最小值,就可以使用梯度下降法的思想來做。假設希望求解目標函數 的最小值,可以從一個初始點 開始,基於學習率 構建一個迭代過程:當 時,
其中 ,一旦達到收斂條件的話,迭代就結束。從梯度下降法的迭代公式來看,下一個點的選擇與當前點的位置和它的梯度相關。反之,如果要計算函數 的最大值,沿著梯度的反方向前進即可,也就是說:
其中 。整體來看,無論是計算函數的最大值或者最小值,都需要構建一個迭代關係 ,那就是:
也就是說對於所有的 ,都滿足迭代關係 。所以,在以上的兩個方法中,我們可以寫出函數 的表達式為:
在本文中,假設 是每個樣本的損失函數, 表示一個關於輸入 和參數 的函數,並且 表示 所對應的目標值。
案例1:
針對這個函數 而言,從數學上我們可以輕易地得到最小值點就是 。不過在這裡我們可以驗證隨機梯度下降法的效果。首先計算函數 的梯度為:
其次,給定一個隨機的初始點 ,通過梯度可以得到迭代公式為:
其中 表示學習率, 表示迭代次數。因此,可以計算出具體的公式為:
於是可以得到:
意思就是說,使用隨機梯度下降法我們可以得到函數 的最小值是 。
案例2:
不過,隨機梯度下降法也有著自身的侷限性。針對很多高維非凸函數而言,鞍點的數量其實遠遠大於局部極小值(極大值)的數量。因此,如何快速的逃離鞍點就是深度學習中大家所研究的問題之一。而比較簡單的鞍點就是馬鞍面函數 中的 點。而函數 在 上並沒有最小值,因為 。 同時,函數 的偏導數是:
而 在點 上則滿足以下幾個性質:
也就是說, 這一點的 Hessian 矩陣並不是正定矩陣。
隨機梯度下降法:如果初始點是 ,那麼隨機梯度下降法(SGD)就可以寫成:對於所有的 ,有
其中 是學習率。
使用動量的隨機梯度下降法:如果初始點是 ,初始速度是 ,學習率是 ,動量參數是 ,那麼使用動量的隨機梯度下降法就可以寫成: ,
AdaGrad 演算法:如果初始點是 ,學習率是 , 是小常數,那麼 AdaGrad 演算法就可以寫成: ,
其中 是學習率, 是一個小常數。
Case 1:
當 時,如果使用隨機梯度下降法,就可以得到 ,
因此, 。 通過隨機梯度下降法(SGD)在初始值為 的前提下並不能計算出函數 的最小值,而是會停止在 鞍點這個地方,最終無法逃離鞍點。
同理,如果使用基於動量的 SGD 演算法,就要看初始速度的設置了,如果初始的速度為 ,那麼最終都會收斂到 這個點上。不過,如果 ,那麼就可以在一定次數的迭代之後逃離 。
根據同樣的分析思路,在本文中所寫的 AdaGrad,RMSProp,Adam 演算法中,如果初始點是 並且演算法參數都是默認的話,使用這些方法同樣無法逃離鞍點 ,也就是說最終都會收斂到 上。
Case 2:
在這種情況下,可以考慮在 的基礎上給縱坐標加上一個微小的擾動。不妨假設初始點為 。下面計算各個演算法在這個初始值下的收斂效果。在實際的應用中,需要迭代的次數越少越好。於是,通過計算 的值,就可以進一步判斷哪個演算法(SGD,Momentum SGD,AdaGrad,RMSProp,Adam)更加容易逃離鞍點。
隨機梯度下降法:通常情況下, 可以設置為 。從隨機梯度下降法的公式來看,就可以得到如下迭代公式:
其實, ,i.e. 使用梯度下降法同樣可以找到函數 的最小值。但是,如果 ,則 需要滿足條件:
換言之,需要迭代 次左右纔能夠使得 。
AdaGrad 演算法:通常來說,在 AdaGrad 演算法中,演算法的參數默認值是 和 。由於初始值 ,所以計算可以得到:
最後通過寫程序就可以證明,在 AdaGrad 的默認參數下,只需要 次左右的迭代就可以實現 。
RMSProp 演算法:
在這種情況下,為了簡單起見,可以令衰減速率 ,那麼同樣可以寫出迭代公式為: ,有
在 RMSProp 裡面,一般來說小常數 , 。通過直接計算可以知道,在這種情況和參數設置下,在迭代了 輪左右的時候,就會出現 的情況。
整體來說,在初始值為 的情況下,無論是 SGD,Momentum SGD,AdaGrad 演算法,還是 RMSProp 演算法,都會逃離鞍點 。只不過 AdaGrad 和 RMSProp 演算法的逃離速度比 SGD 快了許多。
10種常用梯度提升優化演算法整理
這裡枚舉了流行的深度學習框架中常見的Gradient Descent演算法,包括不限於Tensorflow、pyTorch、Caffe、Keras。可以作為回頭查看的一個資料。
Gradient Descent Optimizer是幹啥的?
這裡簡單說明一下learning rate schedulers和Gradient Descent Optimizer的差異:
Notation
目錄:
1.Stochastic Gradient Descent
使用當前梯度?L/?w乘以學習率α來更新當前權重w。
2.Momentum
Momentum使用V即歷史和現在的梯度的exponential moving average來替代當前梯度來更新權重。V初始化為0,β通常取值0.9。
詳見論文鏈接:[(PDF) Some methods of speeding up the convergence of iteration methods](https://www.researchgate.net/publication/243648538_Some_methods_of_speeding_up_the_convergence_of_iteration_methods)
3.Nesterov Accelerated Gradient (NAG)
與Momentum類似,但使用的V為投影梯度(projected gradients)的exponential moving average。V初始化為0,β通常取值0.9。
第二個等式中的最後一項是投影梯度。具體過程為:
詳見論文鏈接:[On the importance of initialization and momentum in deep learning](On the importance of initialization and momentum in deep learning)
4.AdaGrad(Adaptive gradient)
自適應梯度。通過將learning rate除以S的平方根進行更新。S指的是歷史和當前的梯度的平方的累加。Gradient部分與SGD中保持一樣。S初始化為0,加 確保分母不為0。α通常取值0.01,通常取值10??。
詳見論文鏈接: [http://jmlr.org/papers/v12/duchi11a.html]
5.RMSprop(Root mean square prop)
RMSProp是對AdaGrad的一種改進。使用梯度的exponential moving average而不是使用累計的平方梯度和。S初始化為0, = 0.001, =0.9, =10??
詳見論文鏈接:http://www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf
6.AdaDelta(Adaptive delta)
AdaDelta是對AdaGrad的另一種改進。Delta表示當前權重w與新更新權重w之間的差異。
AdaDelta和RMSprop之間的區別在於,AdaDelta使用Delta平方的exponential moving average替代learning rate。D和S初始化為0, =0.95, =10??
詳見論文鏈接:[1212.5701 ADADELTA: An Adaptive Learning Rate Method](ADADELTA: An Adaptive Learning Rate Method)
7.Adam(Adaptive Moment Estimation)
Adam是對Momentum和RMPprop的一個結合。
詳見論文鏈接:[1412.6980 Adam: A Method for Stochastic Optimization](Adam: A Method for Stochastic Optimization)
8.AdaMax
梯度部分像Momentum裏一樣使用V即梯度的exponential moving average。S為梯度 p-norm 的exponential moving average。V和S初始化為0, = 0.002, =0.9, =0.999。
9.Nadam
Nadam是Nesterov和Adam optimizer的首字母縮寫。
Adam Optimizer可以被寫成如下:
Nadam利用Nesterov將 替換成當前 來提前更新梯度:
V和S初始化為0, = 0.002, =0.9, =0.999, =10??
10.AMSGrad
Adam的另一個變體是AMSGrad。不同的地方在於每次對S進行修正保證當前的S值始終大於前一time step的。V和S初始化為0, = 0.001, =0.9, =0.999, =10??。
11. 直觀解釋
那為什麼optimizers中 gradient迭代選擇的exponential moving average,learning rate迭代選擇root mean square呢?
1) gradient迭代為什麼選擇的exponential moving average?
我們要進行權重迭代時,我們唯一能用的值就是當前的梯度值。但是僅使用當前的梯度是不夠的,我們希望能利用到之前的梯度來更好的指導梯度下降的方向。
所以需要對歷史和當前的梯度進行「組合」。試想最簡單的方法就是直接平均,但這樣意味著每一個梯度都有相同的權重。這不太符合直觀感覺,我們希望更近的梯度值獲取更高的權重。而exponential moving average正好可以做到。
2) learning rate迭代為什麼選擇root mean square?
迭代learning rate的目的是為了能適應梯度。當梯度值很大時,我們希望更新是小小的,否則當前的權重就會產生很大改變。
為了產生這樣效果,將學習率learning rate除以當前的梯度,就能得到一個「適應」好的學習率的值。Learning rate應該始終為正,為了確保它使始終是正的,我們對梯度進行求絕對值或平方求和取平方根。
我們也希望把梯度裏的思想引入到learning rate中,希望使用歷史數據來更好地引導學習率進行調整。我們將採用過去梯度的exponential moving avergae,然後取其平方根,即root mean square。
謝邀。既然你打開了這個回答,我想你一定不是為了看梯度下降的公式是什麼,畢竟百科上有梯度下降_百度百科。我猜你一定是想了解為何梯度下降會起作用,而不是純粹記憶公式。只有知道了梯度下降原理是什麼才懂得自己怎麼修改梯度下降的公式。我分三點:1.直觀理解 2. 梯度下降怎麼做(附帶推薦編程實踐) 3. 梯度下降有啥用
親們不要只收藏不點贊嘛
其實它沒啥就是讓計算機不斷猜最小值的那個點自變數x在哪,猜大了讓它小一點,猜小了讓它大一點。猜個幾萬次就猜中了。怎麼猜的根據梯度猜的。梯度是啥,導數。怎麼根據導數猜的?高中老師教過當前這個點導數大於0證明它周圍單調增,最小值點肯定比當前猜的這個點小,那我下次就猜小一點(因為我想找最小值點在哪)。導數小於0同理。沒看懂?沒關係看下面的。
想像下:
按照上面那個圖的特點,假設這個圖放大1萬倍,大到你不能一眼看到最小值。那麼要你找最小值對應的自變數x,你怎麼找??記住我們目的是為了找自變數x,記住我們目的是為了找x
你將可能會在電腦屏幕看到原先那個圖的局部,按照它們單調性來分主要有這三種情況
當你遇到情況1:單調下降,導數為負(梯度為負),要想找到函數的最小值所對應的自變數的值(曲線最低點對應x的值)怎麼走?當然是水平向右滑啦,也就是讓x增大,此時隨著x增大,函數值是減小(下降)的(梯度下降含義懂了吧哈哈就這個意思)
當你遇到情況2:單調上升,導數為正(梯度為正),要想找到函數的自變數的值(曲線最低點對應x的值)怎麼走?當然是水平向左滑啦,也就是讓x減小,此時隨著x減小,函數值減小的(也就是梯度下降)。
綜上所述:
Ai醬:適合初學者的神經網路理論到實踐(1):單個神經元+隨機梯度下降學習邏輯與規則?zhuanlan.zhihu.com
機器學習和神經網路,還有各種數學建模問題。最終不是有個目標函數|損失函數|代價函數|誤差函數,不管叫啥函數反正他們都一樣。反正就是求他最小值點x。不是求最小值點?加個負號不就好了。
注意是最小值點而不是最小值。
為啥?因為機器學習和神經網路等等他們損失函數|代價函數|誤差函數最小值肯定是0啊。
我們想要的是當誤差最小時,最優自變數|權重|參數是啥。不同問題叫法不一樣,但是一樣的是他們都是想找自變數而不是函數值。
最後大家如果想看看更詳細的回答可以看看
初學者機器學習資料分享Q羣(718566626)
Ai醬:{高中生能看懂的}再見香農,決策樹的本質是什麼
Ai醬:[易懂]如何理解論文中的那些評估方法性能指標概念名詞{召回率 ROC AUC 交叉驗證}
從本質如何理解機器學習
計算機生態圈是怎麼樣的?
你長大後才意識到的,對於15歲以前的小孩子,哪些能力、技能和品質是含金量最高的?
計算機領域近幾年會不會飽和?
每一個機器學習模型都有一個損失函數,學習的目的,就是將損失函數最小化。
然而,並非所有函數都能一下子就找到最小值,甚至都沒有最小值。(比如 )
所以,很多機器學習模型都以凸函數作為損失函數,因為凸函數保證了其有最小值。
凸函數的定義:如果函數 在某段區間上的任意兩個點,都有 ,則稱其在某段區間上凸函數。
學過高等數學的人可能會有疑惑,這不是凹函數的定義嗎?沒錯,我們所說的凸函數對應的是英文中的Convex Function。而某些教材(比如同濟大學高等數學)把這種函數稱為凹函數,而把Concave Function 稱為凸函數。定義與機器學習中的定義完全相反。可以理解成:凸函數就是在某段區間只有一個低谷的函數。
假設,一個凸函數是一元函數形式,那麼它的函數值畫出來,應該是這樣的:
也就是 直線永遠高於曲線
如果是像下圖這樣,有好幾個低谷的部分,那麼每個低谷為局部最小值,而最低的那個低谷則稱為全局最小值。
而二維的話,最小值則是碗狀的:
現在我們瞭解了凸函數的定義,如果損失函數是凸函數,那麼學習的目標自然就是尋找某個凸函數的最小值。
用來尋找凸函數最小值的最常用方法,就是梯度下降法。
這種方法從直觀來理解是很容易的。以一元函數為例。假設我們的目標函數是一個一元凸函數。
我們可以用如下步驟來獲得其最小值(已知損失函數是 ):
對應三維的情況,可以想像在一個小球在碗中,讓小球沿著當時所在點的切線方向(此時的切線方向是一個二維向量)向前走一步,直到走到碗底為止。
上面的梯度下降中提到了一個參數 ,它又稱為步長。這種演算法是需要人為設置的,而非用來學習的參數,所以叫做超參數。步長是梯度下降演算法中最重要的超參數,設置時需要精心考慮。
比如,像下圖左邊,如果步長太大,始終落不到最低點。 而如果改成右側那樣的小步長就可以找到最低點了(但如果太小,收斂速度可能會很慢)。
如果目標函數有多個極小值點(很多個低谷),那麼如果開始位置不理想,很可能導致最終卡在一個局部極小值。比如下圖的例子。
這是梯度下降演算法的一大挑戰。
所以,人們提出了很多梯度下降的變體,比如:
有一張圖完美地展示了這些演算法的下降過程:
這篇回答節選自我的專欄《機器學習中的數學:微積分與最優化》,和大家一起談談梯度下降法。
梯度下降法的思路非常清晰明瞭,且實現過程也比較簡單,是求解無約束最優化問題中的一種最常用、最基礎的迭代方法。
在梯度下降法當中,顧名思義,梯度是其中最為重要的核心工具和武器。因此,我們有必要回顧一下關於梯度的一些重要概念和特性:
首先,多元函數 在點 ?處的梯度 是一個 維向量: ;
其次,多元函數 在點 ?處的梯度向量與該函數過點 ?處的等位線的切線向量相互正交;
最重要的是,沿著梯度 向量方向,函數 的值的增長速度最快,相對應的,沿著負梯度,也就是 向量的方向,函數 的值下降的最快。
為了形象的描述這個演算法的思想和過程,我們舉一個盲人下山的例子:
利用迭代法,在一個多元函數上去探索極小值的過程,我們可以把他想像成一個盲人下山的過程,盲人看不到整個山的全貌,不清楚全局,擁有的能力只是去感知他所站立位置四周的坡度,而他的目標卻是要下到山的最低點。
假設盲人站在山的任意一個位置點,開始下山的過程,首先他感知一下自己四周的山坡,選擇坡度最陡峭的一個方向,然後沿著這個方向走一小步,到達一個新的位置點,然後不斷重複上面的「感知坡度」-「選擇最陡峭的方向」-「走一小步」的過程,不斷更新自己的位置點。
最終什麼時候停下來呢?那應該是在盲人身處某個點的時候發現四周坡度已經很「平」了,他就判斷自己下到了山底,此時就能停下來了。
那麼,有了上面的思維過程打基礎,我們再來實際理解梯度下降法就不難了:
我們從隨機的初始點 ?開始迭代,這就好比那個盲人站在了山上的任意一個位置點上。函數的極小值點在哪,最終該往哪走?我們也不知道,我們就好比那個盲人什麼也看不到一樣。
但是,我們也可以利用梯度這個工具來找到 ?鄰域內具體哪個方向上函數的下降速度最快,即 負梯度向量的方向,我們沿著他來微小的更新我們取值點的位置,就好比盲人沿著最陡峭的方向走了一小步。
我們就不停的重複「計算梯度」-「沿著負梯度的方向」-「更新位置值」的過程,直到突然間我們發現,梯度已經很小了,小於我們預設的閾值,此時的位置點就認定為我們找到的函數的局部極小值點,這就好比盲人發現四周的坡度已經很平了。
梯度下降法的背後,其實還是離不開多元函數的一階泰勒展開以及函數的線性近似的思想:
就拿簡單的二元函數來說, 在點 ?處的一階泰勒展開式為: ,這個泰勒近似是在 ?的小的鄰域範圍內近似效果較好,因此迭代的步子不能邁得過大,太大的話 ?處的梯度的精度就失效了。
那麼進一步的,從點 ?處迭代到下一個點 ?,二者之間的迭代關係具體是怎樣的呢?
很顯然,按照我們前面所說的,我們是按照負梯度 的向量方向,從點 ?走到了點 ?,那麼向量 ?的方向就和 ?處的梯度方向正好反向,在表達式上滿足下面的關係:
)?
我們對表達式稍作調整,就有: 。
此時,進一步進行整理,迭代的關係初見雛形: 。
最後,我們令: ?,整個迭代的關係就簡化成了如下的形式:
?。
我們把他一般化,就有了最終的迭代公式: ?。
此時,距離問題的徹底解決似乎還有一道坎沒有跨過,那就是這個 ?,他是什麼?他應該確定為多少?這都是一個未知的問題。
這個 ?,我們稱之為學習率,他是迭代步長與梯度向量模的比值,我們一般把學習率設置為一個比較小的固定常數。
這樣,一方面能夠滿足迭代精度的要求,另一方面還可以動態調整迭代的步長,當坡度陡峭、梯度值較大時,我們的步長相應變大,快速下山,而當我們快要接近山底,坡度變得平緩,梯度變小的時候,步長也相應變小,以免一大步跨過極小值點的情況發生。
通過上面的理論知識的講解,我們對梯度下降法的原理應該已經掌握的比較透徹了。那麼接下來我們實際動手,用python語言來實際操練一下這個極值點迭代求取的常用演算法:
我們舉一個例子 ?,下面就來求這個簡單的二元函數的極小值點。
在這個實際的例子中,我們令初始的迭代點為 ,學習率 ,如果梯度的模長小於閾值 時則停止迭代。我們按照梯度下降法的基本思路來尋找函數的極小值點:
代碼片段:
from matplotlib import pyplot as plt import numpy as np from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure() ax = Axes3D(fig)
def f(p): return 0.2 * p[0] ** 2 + p[1] ** 2
def numerical_gradient(f, P): h = 1e-6 x = P[0] y = P[1] dx = (f(np.array([x + h / 2, y])) - f(np.array([x - h / 2, y]))) / h dy = (f(np.array([x, y + h / 2])) - f(np.array([x, y - h / 2]))) / h return np.array([dx, dy])
def gradient_descent(cur_p, lambda_=0.1, epsilon=0.0001, max_iters=10000): for i in range(max_iters): grad_cur = numerical_gradient(f, cur_p) if np.linalg.norm(grad_cur, ord=2) &< epsilon: break cur_p = cur_p - grad_cur * lambda_ ax.scatter(cur_p[0], cur_p[1], f(cur_p), color=r) print(局部極小值為:{}.format(cur_p)) return cur_p x1 = np.arange(-4, 4, 0.01) x2 = np.arange(-4, 4, 0.01) x1, x2 = np.meshgrid(x1, x2) ax.plot_surface(x1, x2, f(np.array([x1, x2])), color=y, alpha=0.3) p0 = np.array([3, 4]) gradient_descent(p0) plt.show()
運行結果:
局部極小值為:[2.40866325e-04 5.16743037e-19]
之前我們曾經提到過,函數 在具體某個點 ?處的等位線的切線向量是和該點處的梯度向量相互正交的,我們利用之前學過的知識,在 平面上繪製函數的等位線圖,並且將各個迭代的取值點也投影到 平面上,來實際驗證一下迭代點的軌跡與等位線的相互關係:
from matplotlib import pyplot as plt import numpy as np
def f(p): return 0.2*p[0]**2 + p[1] ** 2
def numerical_gradient(f, P): h = 1e-6 x = P[0] y = P[1] dx = (f(np.array([x+h/2, y]))-f(np.array([x-h/2, y])))/h dy = (f(np.array([x, y+h/2]))-f(np.array([x, y-h/2])))/h return np.array([dx, dy])
def gradient_descent(cur_p, lambda_=0.1, epsilon=0.0001, max_iters=10000):
for i in range(max_iters): grad_cur = numerical_gradient(f, cur_p) if np.linalg.norm(grad_cur, ord=2) &< epsilon: break cur_p = cur_p - grad_cur * lambda_ plt.plot(cur_p[0],cur_p[1], ko, markersize=3) return cur_p x1 = np.arange(-5, 5, 0.01) x2 = np.arange(-5, 5, 0.01) x1, x2 = np.meshgrid(x1, x2) C = plt.contour(x1, x2, f(np.array([x1, x2])), 60) plt.clabel(C, inline=True, fontsize=12) p0 = np.array([3, 4]) gradient_descent(p0) plt.show()
梯度下降法整個思路非常易於理解,實現起來比較簡單,但是他的性能並不是最優的,最主要的原因是他基於一階泰勒展開的函數近似,為了保證其梯度的有效性,因此每次迭代的步長都比較小,使得收斂的速度比較慢,要迭代多輪才能收斂到極值點附近。因此,後續有很多的演算法對梯度下降法都進行了一些改良,提升了他的性能。
機器學習中的數學:微積分與最優化_專欄?gitbook.cn
-------------------------------------------------------------------------------------------
當然還有《機器學習中的數學》系列專欄,歡迎大家閱讀,配合食用,效果更佳~
有訂閱的問題可諮詢微信:zhangyumeng0422