《神經網路的梯度推導與程式碼驗證》之FNN(DNN)的前向傳播和反向梯度推導

SumwaiLiu發表於2020-09-02

《神經網路的梯度推導與程式碼驗證》之數學基礎篇:矩陣微分與求導中,我們總結了一些用於推導神經網路反向梯度求導的重要的數學技巧。此外,通過一個簡單的demo,我們初步瞭解了使用矩陣求導來批量求神經網路引數的做法。在本篇章,我們將專門針對DNN/FNN這種網路結構進行前向傳播介紹和反向梯度推導。更多相關內容請見《神經網路的梯度推導與程式碼驗證》系列介紹

 

注意:

目錄

 


 

2.1 FNN(DNN)的前向傳播

下面是兩張DNN的示意圖:

 

 

我們用$w_{24}^{3}$來表示第2層的第4個神經元與第三層第2個神經元之間的引數。

 

我們用$b_{3}^{2}$表示第2層的第3個神經元的偏置。用$a_{1}^{3}$表示第3層的第1個神經元的輸出(注意是經過啟用函式後的)。

 

上圖的從第一層到第二層的引數計算公式如下:

$a_{1}^{2} = \sigma\left( {w_{11}^{2}x_{1} + w_{12}^{2}x_{2} + w_{13}^{2}x_{3} + b_{1}^{2}} \right)$

$a_{2}^{2} = \sigma\left( {w_{21}^{2}x_{1} + w_{22}^{2}x_{2} + w_{23}^{2}x_{3} + b_{2}^{2}} \right)$

$a_{3}^{2} = \sigma\left( {w_{31}^{2}x_{1} + w_{32}^{2}x_{2} + w_{33}^{2}x_{3} + b_{3}^{2}} \right)$

$a_{4}^{2} = \sigma\left( {w_{41}^{2}x_{1} + w_{42}^{2}x_{2} + w_{43}^{2}x_{3} + b_{4}^{2}} \right)$

其中$\sigma\left( ~ \right)$表示啟用函式。

 

將上圖寫成矩陣的編排方式就是下面這樣:

$\left\lbrack \begin{array}{l} \begin{array}{l} a_{1}^{2} \\ a_{2}^{2} \\ \end{array} \\ a_{3}^{2} \\ a_{4}^{2} \\ \end{array} \right\rbrack = \sigma\left( {\left\lbrack \begin{array}{lll} \begin{array}{l} w_{11}^{2} \\ w_{21}^{2} \\ \end{array} & \begin{array}{l} w_{12}^{2} \\ w_{22}^{2} \\ \end{array} & \begin{array}{l} w_{13}^{2} \\ w_{23}^{2} \\ \end{array} \\ w_{31}^{2} & w_{32}^{2} & w_{33}^{2} \\ w_{41}^{2} & w_{42}^{2} & w_{43}^{2} \\ \end{array} \right\rbrack\left\lbrack \begin{array}{l} x_{1} \\ x_{2} \\ x_{3} \\ \end{array} \right\rbrack + \left\lbrack \begin{array}{l} \begin{array}{l} b_{1}^{2} \\ b_{2}^{2} \\ \end{array} \\ b_{3}^{2} \\ b_{4}^{2} \\ \end{array} \right\rbrack} \right)$

$\boldsymbol{a}^{2} = \sigma\left( {\boldsymbol{W}^{2}\boldsymbol{x} + \boldsymbol{b}^{2}} \right)$

同理得到第二層到第三層的計算公式:

$\boldsymbol{a}^{3} = \sigma\left( {\boldsymbol{W}^{3}\boldsymbol{a}^{2} + \boldsymbol{b}^{3}} \right)$

於是總結下來,DNN的層間關係如下:

$\boldsymbol{a}^{\boldsymbol{l}} = \sigma\left( {\boldsymbol{W}^{l}\boldsymbol{a}^{l - 1} + \boldsymbol{b}^{l}} \right)$

所以DNN的前向傳播邏輯如下:

輸入:總層數L,所有隱藏層和輸出層對應的引數矩陣$\boldsymbol{W}$,偏置向量$\boldsymbol{b}$和輸入向量$\boldsymbol{x}$

輸出:$\boldsymbol{a}^{L}$

1) 初始化$\boldsymbol{a}^{1} = \boldsymbol{x}$

2) for $l = 2$ to L,計算:$\boldsymbol{a}^{l} = \sigma\left( {\boldsymbol{W}^{l}\boldsymbol{a}^{l - 1} + \boldsymbol{b}^{l}} \right)$

最後的結果即為輸出$\boldsymbol{a}^{L}$

 


 

2.2 FNN(DNN)的反向梯度求導

在進行DNN反向傳播演算法前,我們需要選擇一個損失函式,來度量訓練樣本計算出的輸出和真實的訓練樣本輸出之間的損失。這裡用mse作為損失函式,則每一條樣本的loss計算公式如下:

$l = \frac{1}{2}\left\| {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right\|_{2}^{2} = \frac{1}{2}\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{T}\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)$

其中,$\boldsymbol{y}$就是樣本標籤$\boldsymbol{y}\_\boldsymbol{t}\boldsymbol{u}\boldsymbol{r}\boldsymbol{e}$,而$\boldsymbol{a}^{\boldsymbol{L}}$就是預測值$\boldsymbol{y}\_\boldsymbol{p}\boldsymbol{r}\boldsymbol{e}\boldsymbol{d}\boldsymbol{i}\boldsymbol{c}\boldsymbol{t}$。

預測值$\boldsymbol{a}^{\boldsymbol{L}}$和輸入$\boldsymbol{x}$滿足$\boldsymbol{a}^{\boldsymbol{L}} = \boldsymbol{D}\boldsymbol{N}\boldsymbol{N}\left( {\boldsymbol{x};\boldsymbol{W},\boldsymbol{b}} \right)$,這就是2.1中提到的DNN的前向傳播過程,這麼看來,所謂前向傳播,不過是一個複雜的函式罷了。

 

於是寫得再全一點,某條樣本$\boldsymbol{a}^{\boldsymbol{L}} = \boldsymbol{D}\boldsymbol{N}\boldsymbol{N}\left( {\boldsymbol{x};\boldsymbol{W},\boldsymbol{b}} \right)$根據mse計算出來的loss就是下面這樣:

$l\left( {\boldsymbol{x},\boldsymbol{y},\boldsymbol{W},\boldsymbol{b}} \right) = \frac{1}{2}\left\| {\boldsymbol{D}\boldsymbol{N}\boldsymbol{N}\left\| {\boldsymbol{x};\boldsymbol{W},\boldsymbol{b}} \right\| - \boldsymbol{y}} \right\|_{2}^{2} = \frac{1}{2}\left( {\boldsymbol{D}\boldsymbol{N}\boldsymbol{N}\left( {\boldsymbol{x};\boldsymbol{W},\boldsymbol{b}} \right) - \boldsymbol{y}} \right)^{T}\left( {\boldsymbol{D}\boldsymbol{N}\boldsymbol{N}\left( {\boldsymbol{x};\boldsymbol{W},\boldsymbol{b}} \right) - \boldsymbol{y}} \right)$

 

鋪墊了這麼多接下來正式開始求梯度。

我們先求$\frac{\partial l}{\partial\boldsymbol{a}^{\boldsymbol{L}}}$,

$dl = \frac{1}{2}\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{T}d\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right) + \frac{1}{2}d\left( \left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{T} \right)\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right) = \frac{1}{2}\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{T}d\boldsymbol{a}^{\boldsymbol{L}} + \frac{1}{2}d\left( \left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{T} \right)\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)$

對$\frac{1}{2}\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)d\left( \left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{T} \right)$使用跡技巧,有:

$\frac{1}{2}d\left( \left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{T} \right)\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right) = \frac{1}{2}tr\left( {d\left( \left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{T} \right)\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)} \right) = \frac{1}{2}tr\left( {\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{\boldsymbol{T}}d\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)} \right) = \frac{1}{2}tr\left( {\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{\boldsymbol{T}}d\boldsymbol{a}^{\boldsymbol{L}}} \right) = \frac{1}{2}\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{\boldsymbol{T}}d\boldsymbol{a}^{\boldsymbol{L}}$

所以有:

$dl = \frac{1}{2}\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{T}d\boldsymbol{a}^{\boldsymbol{L}} + \frac{1}{2}\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{\boldsymbol{T}}d\boldsymbol{a}^{\boldsymbol{L}} = \left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right)^{\boldsymbol{T}}d\boldsymbol{a}^{\boldsymbol{L}}$

$\frac{\partial l}{\partial\boldsymbol{a}^{\boldsymbol{L}}} = \boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}$

我們令$\boldsymbol{z}^{L} = \boldsymbol{W}^{\boldsymbol{L}}\boldsymbol{a}^{\boldsymbol{L} - 1} + \boldsymbol{b}^{\boldsymbol{L}}$

可求得$\frac{\partial l}{\partial\boldsymbol{z}^{\boldsymbol{L}}} = \left( \frac{\partial\boldsymbol{a}^{\boldsymbol{L}}}{\partial\boldsymbol{a}^{\boldsymbol{L}}} \right)^{T}\frac{\partial l}{\partial\boldsymbol{a}^{\boldsymbol{L}}}$

因為$d\boldsymbol{a}^{\boldsymbol{L}} = d\sigma\left( \boldsymbol{z}^{L} \right) = \sigma^{'}\left( \boldsymbol{z}^{L} \right) \odot d\boldsymbol{z}^{L} = diag\left( {\sigma^{'}\left( \boldsymbol{z}^{L} \right)} \right)d\boldsymbol{z}^{L}$

所以$\frac{\partial l}{\partial\boldsymbol{z}^{\boldsymbol{L}}} = diag\left( {\sigma^{'}\left( \boldsymbol{z}^{L} \right)} \right)\left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right) = \left( {\boldsymbol{a}^{\boldsymbol{L}} - \boldsymbol{y}} \right) \odot \sigma^{'}\left( \boldsymbol{z}^{L} \right)$

有了$\frac{\partial l}{\partial\boldsymbol{z}^{\boldsymbol{L}}}$,那麼求L層的$\boldsymbol{W}^{\boldsymbol{L}}$和$\boldsymbol{b}^{\boldsymbol{L}}$的梯度就非常容易了,根據標量對線性變換的求導結論,直接得到:

$\frac{\partial l}{\partial\boldsymbol{W}^{\boldsymbol{L}}} = \frac{\partial l}{\partial\boldsymbol{z}^{\boldsymbol{L}}}\left( \boldsymbol{a}^{\boldsymbol{L} - 1} \right)^{T}$

$\frac{\partial l}{\partial\boldsymbol{b}^{\boldsymbol{L}}} = \frac{\partial l}{\partial\boldsymbol{z}^{\boldsymbol{L}}}$

這樣第L層的所有引數的梯度就得到了。

為了方便起見,今後用$\delta^{l}$表示$\frac{\partial l}{\partial\boldsymbol{z}^{\boldsymbol{l}}}$。

有上面求L層引數的梯度的思路,可以發現,如果我們想求出第$l$層的引數的梯度,我們可以先求出$\delta^{l}$然後直接套用標量對線性變換的求導結論就可以快速求得結果了。因此,這裡我們用數學歸納法,第L層的$\delta^{L}$我們已經求出來了,假設第$l+1$層的$\delta^{l + 1}$已求出來,那我們如何求$\delta^{l}$呢?

 

根據鏈式法則,有$\frac{\partial l}{\partial\boldsymbol{z}^{\boldsymbol{l}}} = \left( \frac{\partial\boldsymbol{z}^{\boldsymbol{l} + 1}}{\partial\boldsymbol{z}^{\boldsymbol{l}}} \right)^{T}\frac{\partial l}{\partial\boldsymbol{z}^{\boldsymbol{l} + 1}}$

現在問題轉到求$\frac{\partial\boldsymbol{z}^{\boldsymbol{l} + 1}}{\partial\boldsymbol{z}^{\boldsymbol{l}}}$上。

我們注意到有$\boldsymbol{z}^{l + 1} = \boldsymbol{W}^{l + 1}\sigma\left( \boldsymbol{z}^{\boldsymbol{l}} \right) + \boldsymbol{b}^{l + 1}$成立,

所以$d\boldsymbol{z}^{l + 1} = \boldsymbol{W}^{l + 1}d\sigma\left( \boldsymbol{z}^{\boldsymbol{l}} \right) = \boldsymbol{W}^{l + 1}\left( {\sigma^{'}\left( \boldsymbol{z}^{l} \right) \odot d\boldsymbol{z}^{l}} \right) = \boldsymbol{W}^{l + 1}diag\left( {\sigma^{'}\left( \boldsymbol{z}^{\boldsymbol{l}} \right)} \right)d\boldsymbol{z}^{\boldsymbol{l}}$

所以$\frac{\partial\boldsymbol{z}^{l + 1}}{\partial\boldsymbol{z}^{l}} = \boldsymbol{W}^{l + 1}diag\left( {\sigma^{'}\left( \boldsymbol{z}^{\boldsymbol{l}} \right)} \right)$

於是通過$\delta^{l + 1}$,我們可以求得:

$\delta^{l} = diag\left( {\sigma^{'}\left( \boldsymbol{z}^{\boldsymbol{l}} \right)} \right)\left( \boldsymbol{W}^{l + 1} \right)^{T}\delta^{l + 1} = \left( \boldsymbol{W}^{l + 1} \right)^{T}\delta^{l + 1} \odot \sigma^{'}\left( \boldsymbol{z}^{\boldsymbol{l}} \right)$

同理,根據$\delta^{l + 1}$可以秒求出$\boldsymbol{W}^{l} = \delta^{l}\left( \boldsymbol{a}^{\boldsymbol{l} - 1} \right)^{T}$,$\boldsymbol{b}^{\boldsymbol{l}} = \delta^{l}$

 


 

2.3 總結

在求神經網路某一層的引數的梯度時,先求出$\delta^{l}$是一種比較合理的策略,因為藉助標量對線性變換的求導結論可以快速通過$\delta^{l}$求得引數的梯度;通過推匯出$\delta^{l}$與$\delta^{l+1}$的關係,可以將這種求引數梯度的模式推廣到其他層上。

 

同時我們也可以發現,對引數梯度造成影響的因素主要有以下幾個:

  • 損失函式的選取,它決定了最初的$\frac{\partial l}{\partial\boldsymbol{a}^{\boldsymbol{L}}}$
  • 啟用函式的選取,它決定了層間$\delta^{l} = \boldsymbol{W}^{\boldsymbol{l} + 1}diag\left( {\sigma^{'}\left( \boldsymbol{z}^{\boldsymbol{l}} \right)} \right)\delta^{l + 1}$的遞推計算
  • 神經網路的引數,例如每一層的神經元個數影響了$\boldsymbol{W}$的尺寸;而整體深度則影響了神經網路隱藏層(尤其是靠前的隱藏層)的梯度穩定性(靠前的隱藏層可能會發生梯度消失或梯度爆炸)。
  • 神經網路的結構,因為顯然它會直接影響反向梯度的推導方式(在LSTM的反向梯度推導中大家會有更深的體會)。

 


 

參考資料

(歡迎轉載,轉載請註明出處。歡迎留言或溝通交流: lxwalyw@gmail.com)

 

 

 

 

 

相關文章