MetAI
反向傳播算法 Back-propagation
Back-propagation(BP)是目前深度學習大多數 NN (Neural Network) 模型更新梯度的方式,在本文中,會從 NN 的 Forward、Backword 逐一介紹推導。
在本章中,您可以認識到:
基礎 NN 的運算方式
Back-propagation (DNN版本)
Gradient Problem
你想得到的模型基本上都是用 BP 的方式在更新梯度,基本原理是一樣的,只是隨著模型設計上的不同,導致梯度會往不同的方向前進,本文只介紹 DNN 的更新方式,之後再來寫 RNN 的更新方式。
先回想一下 NN 中 forward 方式:
輸入向量,經過 NN 模型輸出預測值,接著預測值與 Label 計算 Loss,這個 Loss 表達的是模型與真實之間的距離,我們當然希望這個 Loss 愈小愈好,可以搭配下面 Notation 中的圖來理解。
Input Vector → NN → Prediction ↔ Label
可以想像成 NN 中的權重得到這個 Loss,現在我們想知道這些權重對於 Loss 的影響程度,也就是 Gradient,參數與 Gradient 影響著 Loss 的大小,BP 的核心理念就是產生這個 Gradient 方式與更新方式。
Notation
在開始之前,先來介紹一下推導中會使用到的數學符號,這裡以 3 層 NN 為例子:

Fig.1 因為 Medium 的限制,顯示上無法把上標和下標擺在同一個位置。
W¹₁₁:Fig.1 以 3 層 NN(Layer1, Layer2, Output layer)為例,W₁₁¹ 中上標 w¹ 表示 Layer1,下標 W₁₁ 表示 Layer1 的第一個 Neuron 連結到 Input layer 的第一個 Input。
z¹₁:上標 z¹ 表示 Layer1,下標 z₁ 表示 Layer1 的第一個 Neuron,z¹₁ 表示第一層 activation function 的輸入 (z¹₁=x₁w¹₁₁+x₂w¹₁₂)。
a¹₁:上下標意義與 z¹₁ 同義,差別這個是 activation function 的輸出 (a¹₁=f(z¹₁))。
以上是 3 層 NN 的運作方式,若是更深且更多 Neuron 的 NN 模型想當然爾也容易想像。
Operation
接下來介紹 BP 中會使用到的原理與公式:

Fig.2
Chain rule:中文又稱連鎖率,可以說是 BP 的核心,主要是在探討複合函數 𝑔○𝑓(𝑥), 𝑓(𝑔(𝑡), h(𝑡)) 中,透過微分,了解變數對於輸出的影響程度。
Loss function:量測模型預測與標籤之間的距離公式,為了後面推導方便,這裡使用最簡單的 MSE,其中分母多乘上 2 的目的是為了微分方便。
Sigmoid function:這是其中一種常用的 activation function。
Derivative:這裡以 sigmoid 的微分為例子,這也是為了後面推導方便。
Back-Propagation
這裡一樣以 3 層迴歸 NN 為例子,這邊用 w¹₁₁ 的梯度下降為範例,其餘參數的更新方式依樣畫葫蘆,只是乘多乘少而已,順序關係可以歸納為以下:
𝑥 → 𝑧→ 𝑎→ 𝑧 → 𝑎 → ….
𝑥 與 𝑧 之間的關係是權重,𝑧 與 𝑎 之間的關係是 activation function 的輸入與輸出。

Fig.3
以 Fig.3 而言,我們現在想要知道 w¹₁₁ 的 Gradient(上圖右上紅虛框),然後使用這個 Gradient 搭配 Learning rate 進行 Gradient Descent(整個式子),而在 NN 中,紅色箭頭表示 w¹₁₁ 之後會影響到的路徑,這些路徑給了我們一點方向,w¹₁₁ 只能透過這些路徑影響 Loss,也就是說,Loss 也只能透過這些路徑影響 w¹₁₁,我們有了這個想法後,使用 chain rule 來把這些路徑展開。

Fig.4
Fig.4 是計算 w¹₁₁ 的 Gradient,這裡將式子分成 3 個部分 (1., 2., 3.) 討論, 1~3 的順序關係可以想成從 output layer 慢慢往 Input layer 移動:
對於 z³₁ 的微分:因為是迴歸問題,所以 z³₁ 就是輸出值,而對 MSE 中的輸出值進行微分得到上式。
這個部分會看到 ∑ 這個符號,這是因為 w¹₁₁ 會影響到兩條路徑,可以搭配 Fig.3 來看,分別影響到 Layer2 的第一個 Neuron 和第二個 Neuron,而這裡以上面的 Neuron a²₁ 為例子進行微分,微分後發現其實就是 Layer3 的權重 w³₁₁。
接下來是對 z²₁ 進行微分,z 與 a 之間的關係就是 activation function,對 z 微分就是對 activation function 進行微分。
介紹到這裡,以上面的規則,相信讀者已經可以套用到其餘所有的權重 w,這裡作者將其餘的推導結果全部列出來:

Fig.5
相信各位一定會觀察到這些權重的 Gradient 展開式有不少重複計算的地方 ,以 Fig.6 為例,同時連結到 Layer1 的第一個 Neuron 的權重有兩個,而這兩個的 Gradient 就有 87% 相似的地方,不同只有最後的 x₁ 與 x₂,我們可以利用這個關係,歸納之後計算 Gradient 的規則:

Fig.6 Gradient Problem。我們有了 Gradient 的公式後,接下來探討 NN 中常見的問題,Gradient Vanishing 與 Exploding:

Fig.7
拿 w¹₁₁ 來討論影響 Gradient 的因素,分成 3 個部分:
(Prediction-Label):預測值減掉標籤值,基本上這一項對於 Gradient 不會有太大的影響,他只會出現在第一項,之後就不會再出現了。
w:即網路權重,這個取決於你的初始化權重,常見的初始化策略例如:Normal、Uniform、Truncated_norm 等等,有許多論文在探討初始化方式,這時的 w 是由上一次更新後的 w 所決定,所以只要在初始化時設定的妥當,就不會有什麼問題,而且之後若正常更新,這個 w 是可以自由變化的,不會受限於最大最小值。
σ’(z):即 activation function 的微分,這項是為什麼會發生 Gradient Vanishing 的原因,若 activation function 是 sigmoid,則微分後如 Fig.7 右下圖,微分後的上限只有 0.25,以這 3 層 NN 而言,對於 w¹₁₁ 的 Gradient 我就需要乘上 2 個 σ’(z)(0.2⁵²=0.0625),整個 Gradient 就被強制減少將近 9 成 5 的值,何況是動輒多層的 NN,那計算後的 Gradient 一定更小,這也是為什麼會使用 Sigmoid function 發生 Gradient vanishing 的原因。

Fig.8
到這裡,相信各位已經理解梯度消失的原因,而目前梯度消失解決方式有幾個:
Activation function 改用 Relu (微分後只有0,1,不容易發生梯度消失)
搭配 ResNet 和 Batch normalization(BN) 服用
NN 不要那麼深
試試看其餘機器學習方法(視任務而定)
在 2019/1 有發表一篇論文探討透過特殊的初始化策略可以建立一個超深的 NN 模型,捨棄傳統的 NN 在中間穿插 BN 的方式,透過名為 `Fixup` 的初始化方式來達成,有興趣的可以看看。
到這裡,我們了解到 Gradient Vanishing 發生的原因,那 Gradient Exploding 呢? 在 DNN 中,Gradient Exploding 會發生的原因通常是初始化權重 w 設置的不好,這會導致越靠近 Input layer 的權重變化越大,進而發生 Gradient Exploding 的現象,目前鮮少有人討論 Gradient Exploding,因為這個問題可以用比較粗暴的方式來解決,如下:
tf.clip_by_value(gradient, 1, -1)
上式用白話來講,若 gradient 大於 1,就令為 1,若小於 -1,就令為 -1,透過這簡單的想法防止梯度爆炸。
Conclusion
在本文中主要介紹 NN 的 BP 的原理,以這個方向延伸出許多研究如何使梯度更自然的更新,盡量讓梯度不受到函數的限制。當然 DNN 是所有 NN 中最基礎的模型,之後還有 RNN、CNN 的延伸,之後會找時間來寫 BPTT。