隨機梯度降低法(SGD)是訓練深度學習模型最經常使用的優化方法。在前期文章中咱們講了梯度是如何計算的,主要採用BP算法,或者說利用鏈式法則。可是深度學習模型是複雜多樣的,你不大可能每次都要本身使用鏈式法則去計算梯度,而後採用硬編程的方式實現。算法
而目前的深度學習框架其都是實現了自動求梯度的功能,你只關注模型架構的設計,而沒必要關注模型背後的梯度是如何計算的。不過,咱們仍是想說一說自動求導是如何實現的。編程
這裏咱們會講幾種常見的方法,包括數值微分(Numerical Differentiation),符號微分(Symbolic Differentiation),前向模式(Forward Mode)和反向模式(Reverse Mode)網絡
數值微分架構
數值微分方式應該是最直接並且簡單的一種自動求導方式。從導數的定義中,咱們能夠直觀看到:框架
當h接近0時,導數是能夠近似計算出來的。能夠看到上面的計算式幾乎適用全部狀況,除非該點不可導。但是數值微分卻有兩個問題,第一個就是求出的導數可能不許確,這畢竟是近似表示,好比要求f(x)=x^2在零點附近的導數,若是h選取不當,你可能會獲得符號相反的結果,此時偏差就比較大了。第二個問題是對於參數比較多時,對深度學習模型來講,上面的計算是不夠高效的,由於每計算一個參數的導數,你都須要從新計算f(x+h)。可是數值運算有一個特殊的用武之地就是在於能夠作梯度檢查(Gradient check),你能夠用這種不高效但簡單的方法去檢查其餘方法獲得的梯度是否正確。函數
符號模式學習
符號微分適合符號表達式的自動求導,符號微分技術普遍應用在數學軟件如Matlab、Maple及Mathematica等。符號微分的原理是基於下面的簡單求導規則:優化
當咱們將符號表達式用表達式樹表示時,能夠利用加法規則和乘法規則進行自動求導。好比咱們要求符號表達式f(x)=2x+x^2,能夠展開成以下圖的表達式樹:spa
利用求導規則,能夠求出:設計
基於表達式樹和求導規則,咱們能夠獲得最終的導數。有一點要注意的是,符號微分不必定會獲得簡化的導數,由於計算機可能並不能進行智能的簡化。因此,若是表達式樹結構較複雜時,獲得的導數表達式會至關複雜,也許出現表達式爆炸現象。
前向模式
前向模式最簡單明瞭,其基於的是二元數(dual numbers)。咱們先來說解一下二元數,其基本格式以下所示:
其中a和b都是實數,而
是無窮小量,你能夠認爲其無限接近0,可是並不等於0,而且
,這是借鑑了微積分中的概念。因此,你能夠認爲
是一個接近5的數。對於二元數,其知足簡單的加法和乘法規則:
對於二元數,其更重要的一個特性是:
這意味着,咱們只須要計算出
,就能夠獲得
以及其對應的導數
。因此,一個前向計算過程能夠同時獲得函數值與其導數,這就是前向模式的原理。舉例來講,若是要計算f(x)=2x+x^2在x=2處的函數值與導數,其計算過程以下所示:
反向模式
最後要說的就是反向模式,反向模式就是咱們常說的BP算法,其基於的原理是鏈式法則。咱們僅須要一個前向過程和反向過程就能夠計算全部參數的導數或者梯度,這對於擁有大量訓練參數的神經網絡模型梯度的計算特別適合,因此經常使用的深度學習框架如Tensorflow其自動求導就是基於反向模式。方向模式具體的實現細節能夠參考以前的文章。
參考資料
1. Automatic Differentiation in Machine Learning: a Survey, https://arxiv.org/pdf/1502.05767.pdf
2. Hands-On Machine Learning with Scikit-Learn and TensorFlow, Aurélien Géron, 2017.