本文的思路如下:

偏微分 -> 梯度下降 -> 矩陣求導 -> 反向傳播

1 梯度下降

1.1 偏微分

下圖是一個

z=\cos(x)+\sin(y)

的函式影象,假設有一個點

p_1(x_1, y_1)

,求在p1點處關於x的偏微分

{\partial z\over \partial x}|_{x=x_1}

的思路如下:

從梯度下降到反向傳播

圖1 z函式3D影象

取一個平行於

\vec{x}、\vec{z}

的平面a要求這個平面過p1,與函式相交於上圖中的綠色曲線

畫出平面a的正檢視,視角沿著上圖中的視角箭頭,得到下圖(注意座標值)。

從梯度下降到反向傳播

圖2 z函式2D投影

3。 在上述影象中求解曲線在p1點處的導數,即我們要求的

{\partial z\over\partial x}|_{x={x_1}}

透過圖2,在p1處的導數<0;在p2處的導數>0。從而:

沿著x增大的方向,下坡方向,那麼導數<0;如果要到達谷底,需要

x-\alpha{\partial z\over\partial x}

沿著x增大的方向,上坡方向,那麼導數>0;如果要到達谷底,需要

x-\alpha{\partial z\over\partial x}

即:無論在哪裡,偏導數值相反方向,都是到達谷底的方向。

其中

\alpha

應為一個小數,偏導數只是指明瞭谷底的方向,但是要是邁步過大,容易直接跨過谷底到達另一個山坡位置

1.2 梯度下降

總結偏微分的原理,得到梯度下降公式如下:

\theta_i = \theta_i -\alpha{\partial J(\theta_0,\cdots,\theta_n)\over \partial\theta_i}, for\ i=0\ to\ n

其中

\alpha

控制步伐大小,不斷重複上述更新,直到擬合,即到達圖3的山谷位置,過程如下圖所示:

從梯度下降到反向傳播

圖3 梯度更新過程

即:梯度更新的演算法核心在於求目標函式關於變數

\theta

偏微分

2 反向傳播演算法

2.1 矩陣乘法求導

常見的矩陣乘法有兩種,一種是數學上的乘法,另一種是對應位置相乘,例如:

數學上的乘法,這裡我們記為

\cdot

,例如:

\begin{bmatrix} a_{11}&a_{12}\\ a_{21}&a_{22}\\ \end{bmatrix}\cdot\begin{bmatrix} b_{11}&b_{12}\\ b_{21}&b_{22}\\ \end{bmatrix}=\begin{bmatrix} a_{11}b_{11}+a_{12}b_{21}&a_{11}b_{12}+a_{12}b_{22}\\ a_{21}b_{11}+a_{22}b_{21}&a_{21}b_{12}+a_{22}b_{22}\\ \end{bmatrix}\\

2。 numpy中的預設乘法,為對應位置相乘,這裡我們記為

\cdot *

,例如:

\begin{bmatrix} a_{11}&a_{12}\\ a_{21}&a_{22}\\ \end{bmatrix}\cdot*\begin{bmatrix} b_{11}&b_{12}\\ b_{21}&b_{22}\\ \end{bmatrix}=\begin{bmatrix} a_{11}b_{11}&a_{12}b_{12}\\ a_{21}b_{21}&a_{22}b_{22}\\ \end{bmatrix}\\

2.1.1 數學中的乘法( #FormatImgID_22# )求導

假設有如下計算矩陣:

\begin{bmatrix} x_{11}&x_{12}\\ x_{21}&x_{22}\\ x_{31}&x_{32}\\ \end{bmatrix}\cdot\begin{bmatrix} a_{11}&a_{12}&a_{13}\\ a_{21}&a_{22}&a_{23}\\ \end{bmatrix}=\begin{bmatrix} z_{11}&z_{12}&z_{13}\\ z_{21}&z_{22}&z_{23}\\ z_{31}&z_{32}&z_{33}\\ \end{bmatrix}\\

且上述運算只是鏈式計算中的一環,即有

J=f(Z)

,如果對z矩陣的每個元素求偏導,那麼組合起來的矩陣一定是和z矩陣一樣,即有:

{\partial J\over\partial Z}=\Delta=\begin{bmatrix} \delta_{11}&\delta_{12}&\delta_{13}\\ \delta_{21}&\delta_{22}&\delta_{23}\\ \delta_{31}&\delta_{32}&\delta_{33}\\ \end{bmatrix}\\

在此基礎上求解:

\partial J\over\partial X

由於:

\begin{align} x_{11}a_{11}+x_{12}a_{21}&=z_{11}\\ x_{11}a_{12}+x_{12}a_{22}&=z_{12}\\ x_{11}a_{13}+x_{12}a_{23}&=z_{13}\\ \cdots \end{align}\\

所以:

{\partial J\over\partial x_{11}} ={\partial J\over\partial z_{11}}\cdot{\partial z_{11}\over\partial x_{11}} +{\partial J\over\partial z_{12}}\cdot{\partial z_{12}\over\partial x_{11}} +{\partial J\over\partial z_{13}}\cdot{\partial z_{11}\over\partial x_{13}} =\delta_{11}a_{11}+\delta_{12}a_{12}+\delta_{13}a_{13}\\

於是:

{\partial J\over\partial X}=\begin{bmatrix} \delta_{11}a_{11}+\delta_{12}a_{12}+\delta_{13}a_{13} & \delta_{11}a_{21}+\delta_{12}a_{22}+\delta_{13}a_{23}\\ \delta_{21}a_{11}+\delta_{22}a_{12}+\delta_{23}a_{13} & \delta_{21}a_{21}+\delta_{22}a_{22}+\delta_{23}a_{23}\\ \delta_{31}a_{11}+\delta_{32}a_{12}+\delta_{33}a_{13} & \delta_{21}a_{21}+\delta_{22}a_{22}+\delta_{23}a_{23}\\ \end{bmatrix}=\Delta\cdot A^T\\

也就是說:

{\partial Z\over\partial X}=A^T\\

透過同樣的推導方式可得到如下結論:

如果:

Z=K_1 Y,Y= XK_2\\

那麼(要注意左乘和右乘的區別):

{\partial Z\over \partial X}=K_1^T\cdot numpy.oneslike(Z)\cdot K_2^T\\

這裡為什麼要乘以

numpy。oneslike(Z)

(numpy函式,shape和Z相同,但全為1),可以理解成上述

\Delta

作用,目的是為了保證形狀

上面是比較直觀的矩陣展開推導過程,現在用矩陣乘法公式進行求導過程。條件和上面一致,所以

X\cdot A=Z

,令

x_{ij},a_{jk},z_{ik}

分別為對應的元素,則:

z_{ik}=\sum_j x_{ij}a_{jk}\\

因此:

{\partial J\over\partial x_{ij}}=\sum_{ijk}{\partial J\over z_{ik}}\cdot {\partial z_{ik}\over \partial x_{ij}}=\sum_k \delta_{ik}\cdot {\partial z_{ik}\over \partial x_{ij}}=\sum_k \delta_{ik}\cdot \sum_ja_{jk}=\sum_k\delta_{ik}\cdot a_{jk}\\

所以:

{\partial J\over\partial X}=\Delta\cdot A^T\\

同理:

{\partial J\over\partial a_{jk}}=\sum_i \delta_{ik}\cdot x_{ij}\\

所以:

{\partial J\over \partial A}=X^T\cdot \Delta\\

從上面展開式發現:

{dZ\over dx_{ij}}=\sum_j a_{jk}\\ {dZ\over da_{jk}}=\sum_i x_{ij}\\

所以:

{dZ\over dX}=numpy.oneslike(Z)\cdot A^T\\ {dZ\over dA}=X^T\cdot numpy.oneslike(Z)\\

這也就是矩陣鏈式求導使用

numpy。oneslike

的原因

2.1.2 numpy中的預設乘法,對應位置相乘( #FormatImgID_43# )求導

假設有一個運算:

\begin{bmatrix} z_{11}&z_{12}\\ z_{21}&z_{22}\\ \end{bmatrix}\cdot *\begin{bmatrix} \sigma_{11}&\sigma_{12}\\ \sigma_{21}&\sigma_{22}\\ \end{bmatrix}=\begin{bmatrix} a_{11}&a_{12}\\ a_{21}&a_{22}\\ \end{bmatrix}\\

且上述運算只是鏈式計算中的一環,即有

J=f(A)

,如果對 a 矩陣的每個元素求偏導,那麼組合起來的矩陣一定是和z矩陣一樣shape,即有:

{\partial J\over\partial A} =\Delta=\begin{bmatrix}  \delta_{11}&\delta_{12}\\  \delta_{21}&\delta_{22}\\  \end{bmatrix}\\

在此基礎上求解:

{\partial J\over \partial Z}

由於:

\begin{align} z_{11}\sigma_{11}=a_{11}\\ z_{12}\sigma_{12}=a_{12}\\ \cdots\\ \end{align}\\

所以:

{\partial J\over \partial z_{11}} ={\partial J\over\partial a_{11}}\cdot{\partial a_{11}\over\partial z_{11}} =\delta_{11}\cdot\sigma_{11}\\

於是:

{\partial J\over\partial Z} =\begin{bmatrix} \delta_{11}\cdot\sigma_{11}&\delta_{12}\cdot\sigma_{12}\\ \delta_{21}\cdot\sigma_{21}&\delta_{22}\cdot\sigma_{22}\\ \end{bmatrix}=\Delta\cdot * \Sigma\\

其中

\Sigma

表示

 \sigma_{ij}

對應的矩陣,透過同樣的推導方式可以得到:

如果:

Z=K_1 Y,Y= X\cdot *K_2\\

那麼:

{\partial Z\over \partial X}=K_1^T\cdot numpy.oneslike(Z)\cdot *K_2\\

2.2 反向傳播演算法

反向傳播演算法本質是梯度更新,只不過它為了更方便計算機計算,先求出每一層的誤差並快取,然後再梯度更新

2.2.1 求每一層的誤差

\delta

假設如下神經網路結構,包含2個hidden layer,3個輸入feature,4個輸出result,啟用函式都是sigmoid,loss function使用cross entropy

從梯度下降到反向傳播

圖4 神經網路結構

分解後如圖5所示:

從梯度下降到反向傳播

圖5 神經網路引數分解圖

其中各個引數意義如下:

a^{(i)}

:表示第 i 層啟用值,其中

a^{(1)}

為網路輸入資料,

a^{(4)}

為網路輸出值

z^{(i)}

:表示第 i-1 層(上一層)網路輸出值

\theta^{(i)}

:表示第 i 層網路引數

\delta^{(i)}

:表示第 i 層網路的誤差,我們定義誤差為

\delta^{(i)}={\partial J\over\partial z^{(i)}}

g(z^{(i)})

:表示第 i 層的啟用函式

由於採用cross entropy為損失函式,所以損失函式 J 有:

J = -[y\log a^{(4)}+(1-y)\log (1-a^{(4)})]=-[y\log g(z^{(4)})+(1-y)\log (1-g(z^{(4)}))]

又因為使用啟用函式都是

\sigma={1\over e^{-x}+1}

,所以

g

上述神經網路涉及兩種運算:

1。 點積

\cdot

a^{(i-1)}\rightarrow z^{(i)}

2。 點乘

\cdot *

z^{(i)}\rightarrow a^{(i)}

因此:

\delta^{(4)} ={\partial J\over\partial z^{(4)}} ={\partial J\over\partial a^{(4)}}\cdot *{\partial a^{(4)}\over\partial z^{(4)}} ={a^{(4)}-y\over a^{(4)}\cdot*(1-a^{(4)})}\cdot *g

根據鏈式求導:

\delta^{(3)} ={\partial J\over\partial z^{(3)}} ={\partial J\over\partial z^{(4)}}\cdot{\partial z^{(4)}\over\partial a^{(3)}}\cdot *{\partial a^{(3)}\over\partial z^{(3)}} =\delta^{(4)}\cdot {\partial z^{(4)}\over\partial a^{(3)}}\cdot *g

根據2。1的矩陣求導法則,因為

z^{(4)}=\theta^{(3)}\cdot a^{(3)}

,所以:

\delta^{(3)} ={\partial J\over\partial z^{(3)}} =(\theta^{(3)})^T\cdot \delta^{(4)}\cdot *g

同理:

\delta^{(2)}=(\theta^{(2)})^T\cdot\delta^{(3)}\cdot *g

所以:

\delta^{(i)} ={\partial J\over\partial z^{(i)}} =(\theta^{(i)})^T\cdot \delta^{(i+1)}\cdot *g

2.2.2 求每一層權重的偏導數

\partial J\over\partial \theta^{(i)}

求解了每一層的誤差,接下來需要求我們需要更新的權重的梯度:

{\partial J\over\partial\theta^{(3)}} ={\partial J\over\partial z^{(4)}}\cdot{\partial z^{(4)}\over\partial \theta^{(3)}} =\delta^{(4)}\cdot {\partial z^{(4)}\over\partial\theta^{(3)}}\\

根據2。1矩陣求導公式,因為

\theta^{(3)}\cdot a^{(3)}=z^{(4)}

,所以:

{\partial J\over\partial\theta^{(3)}} =\delta^{(4)}\cdot (a^{(3)})^T\\

同理:

\begin{align} {\partial J\over\partial \theta^{(2)}} =\delta^{(3)}\cdot (a^{(2)})^T\\ {\partial J\over\partial \theta^{(1)}} =\delta^{(2)}\cdot (a^{(1)})^T\\ \end{align}\\

所以:

{\partial J\over\partial \theta^{(i)}} =\delta^{(i+1)}\cdot (a^{(i)})^T\\

從而就可以應用梯度更新公式了

2.2.3 反向傳播演算法總結

第 i 層的誤差,與對應層使用的啟用函式相關:

\delta^{(i)} ={\partial J\over\partial z^{(i)}} =(\theta^{(i)})^T\cdot \delta^{(i+1)}\cdot *g

最後一層誤差,需要結合損失函式求導得到

第 i 層的梯度:

{\partial J\over\partial \theta^{(i)}} =\delta^{(i+1)}\cdot (a^{(i)})^T\\

3 梯度爆炸和梯度消失

3.1 梯度爆炸消失對反向傳播的影響

梯度消失和梯度爆炸問題,字面上理解就是

\theta^{(i)} = \theta^{(i)} -\alpha{\partial J\over \partial\theta^{(i)}}

中的

{\partial J\over\partial \theta^{(i)}}

梯度項,接近0或者接近無窮。下面特例說明梯度消失梯度爆炸在反向傳播中的表現。

因為:

\begin{align}  &{\partial J\over\partial \theta^{(i)}} =\delta^{(i+1)}\cdot (a^{(i)})^T\\  \end{align}\\

假設網路採用線性啟用,即不採用啟用函式,即:

\delta^{(i+1)} ={\partial J\over\partial z^{(i+1)}} =(\theta^{(i+1)})^T\cdot \delta^{(i+2)}\cdot *g

令每一層為權重

\theta^{(i)}=\begin{bmatrix} k&\\ &k \end{bmatrix}

那麼:

\delta^{(i)} =\prod_{l=i}^{L-1}\theta^{(i)}\cdot \delta^{(L)} =\begin{bmatrix} k^{L-1-i}&\\ &k^{L-1-i}\\ \end{bmatrix}\cdot \delta^{(L)}\\

其中 L 表示網路層數,當網路很深時,

L-1-i\rightarrow\infty

,且

a^{(i)}

在計算梯度時,做常數處理,所以梯度的值和上一層的誤差成正相關所以:

k<1\Rightarrow \delta\rightarrow 0\Rightarrow{\partial J\over \partial\theta}\rightarrow 0\\

k> 1\Rightarrow \delta\rightarrow \infty\Rightarrow{\partial J\over \partial\theta}\rightarrow \infty\\

小結:當網路很深時,深層網路的梯度更新與輸出層誤差無關,即梯度不一定朝著梯度變小的方向更新。

3.2 梯度爆炸消失對前饋網路的影響

條件還是和上述一致,那麼:

\hat{y} =\sigma(\prod_{l=1}^L \theta^{(l)}\cdot X) =\sigma(\begin{bmatrix} k^L&\\ &k^L\\ \end{bmatrix}\cdot X)\\

當網路很深,

L\rightarrow \infty

,所以:

k<1\Rightarrow k^L\rightarrow 0 \Rightarrow\hat{y}\rightarrow 0\\

k>1\Rightarrow k^L\rightarrow \infty\Rightarrow \hat{y}\rightarrow 1\\

小結:當存在梯度爆炸或梯度消失時,網路的輸出和網路的輸入X不相關。

3.3 梯度爆炸、梯度消失原因總結

透過3。1、3。2的總結,我們發現如果權重矩陣設定不當,即:

所有權重

\Theta>I

,容易產生梯度爆炸問題

所有權重

\Theta<I

,容易產生梯度消失問題

所以權重初始化很重要,至於怎麼初始化,我們後續再講解#