這一章可能是Andrew Ng講得最不清楚的一章,為什么這么說呢?這一章主要講后向傳播(Backpropagration, BP)算法,Ng花了一大半的時間在講如何計算誤差項$\delta$,如何計算$\Delta$的矩陣,以及如何用Matlab去實現后向傳播,然而最關鍵的問題——為什么要這么計算?前面計算的這些量到底代表着什么,Ng基本沒有講解,也沒有給出數學的推導的例子。所以這次內容我不打算照着公開課的內容去寫,在查閱了許多資料后,我想先從一個簡單的神經網絡的梯度推導入手,理解后向傳播算法的基本工作原理以及每個符號代表的實際意義,然后再按照課程的給出BP計算的具體步驟,這樣更有助於理解。
簡單神經網絡的后向傳播(Backpropagration, BP)算法
1. 回顧之前的前向傳播(ForwardPropagration, FP)算法
FP算法還是很簡單的,說白了就是根據前一層神經元的值,先加權然后取sigmoid函數得到后一層神經元的值,寫成數學的形式就是:
$$a^{(1)}=X$$
$$z^{(2)}=\Theta^{(1)}a^{(1)}$$
$$a^{(2)}=g(z^{(2)})$$
$$z^{(3)}=\Theta^{(2)}a^{(2)}$$
$$a^{(3)}=g(z^{(3)})$$
$$z^{(4)}=\Theta^{(3)}a^{(3)}$$
$$a^{(4)}=g(z^{(4)})$$
2. 回顧神經網絡的代價函數(不含regularization項)
$J(\Theta) = -\frac{1}{m}\left[\sum\limits_{i=1}^{m}\sum\limits_{k=1}^{K}y^{(i)}_{k}log(h_\theta(x^{(i)}))_k + (1-y^{(i)}_k)log(1-(h_\theta(x^{(i)}))_k)\right]$
3. 一個簡單神經網絡的BP推導過程
BP算法解決了什么問題?我們已經有了代價函數$J(\Theta)$,接下來我們需要利用梯度下降算法(或者其他高級優化算法)對$J(\Theta)$進行優化從而得到訓練參數$\Theta$,然而關鍵問題是,優化算法需要傳遞兩個重要的參數,一個代價函數$J(\Theta)$,另一個是代價函數的梯度$\frac{\partial J(\Theta)}{\partial \Theta}$,BP算法其實就是解決如何計算梯度的問題。
下面我們從一個簡單的例子入手考慮如何從數學上計算代價函數的梯度,考慮如下簡單的神經網絡(為方便起見,途中已經給出了前向傳播(FP)的計算過程),該神經網絡有三層神經元,對應的有兩個權重矩陣$\Theta^{(1)}$和$\Theta^{(2)}$,為計算梯度我們只需要計算兩個偏導數即可:$\frac{\partial J(\Theta)}{\partial\Theta^{(1)}}$和$\frac{\partial J(\Theta)}{\partial\Theta^{(2)}}$。

首先我們先計算第2個權重矩陣的偏導數,即$\frac{\partial}{\partial\Theta^{(2)}}J(\Theta)$。首先我們需要在$J(\Theta)$和$\Theta^{(2)}$之間建立聯系,很容易可以看到$J(\Theta)$的值取決於$h_\theta(x)$,而$h_\theta(x)=a^{(3)}$, $a^{3}$又是由$z^{(3)}$取sigmoid得到,最后$z^{(3)}=\Theta^{(2)}\times a^{(2)}$,所以他們之間的聯系可以如下表示:
![]()
按照求導的鏈式法則,我們可以先求$J(\Theta)$對$z^{(3)}$的導數,然后乘以$z^{(3)}$對$\Theta^{(2)}$的導數,即
$$\frac{\partial}{\partial\Theta^{(2)}}J(\Theta) = \frac{\partial}{\partial z^{(3)}}J(\Theta) \times \frac{\partial z^{(3)}}{\partial \Theta^{(2)}} $$
由$z^{(3)}=\Theta^{(2)}a^{(2)}$不難計算$\frac{\partial z^{(3)}}{\partial \Theta^{(2)}}=(a^{(2)})^T$,令$\frac{\partial}{\partial z^{(3)}}J(\Theta)=\delta^{(3)}$,上式可以重寫為
$$\frac{\partial}{\partial\Theta^{(2)}}J(\Theta) =\delta^{(3)} (a^{(2)})^T$$
接下來僅需要計算$\delta^{(3)}$即可,由上一章的內容我們已經知道$g'(z)=g(z)(1-g(z))$, $h_\theta(x)=a^{(3)}=g(z^{(3)})$,忽略前面的$1/m\sum\limits_{i=1}^{m}$(這里我們只對一個example推導,最后累加即可)
$$\begin{aligned}\delta^{(3)}&=\frac{\partial J(\Theta)}{z^{(3)}}\\&= (-y)\frac{1}{g(z^{(3)})}g^{'}(z^{(3)})-(1-y)\frac{1}{1-g(z^{(3)})} [1-g(z^{(3)})]'\\&=-y(1-g(z^{(3)}))+(1-y)g(z^{(3)})\\&=-y+g(z^{(3)})\\&=-y+a^{(3)}\end{aligned}$$
至此我們已經得到$J(\Theta)$對$\Theta^{(2)}$的偏導數,即
$$\frac{\partial J(\Theta)}{\partial\Theta^{(2)}}=(a^{(2)})^T\delta^{(3)}$$
$$\delta^{(3)}=a^{(3)}-y$$
接下來我們需要求$J(\Theta)$對$\Theta^{(1)}$的偏導數,$J(\Theta)$對$\Theta^{(1)}$的依賴關系如下:
![]()
根據鏈式求導法則有
$$\begin{aligned}\frac{\partial J(\Theta)}{\partial \Theta^{(1)}} &= \frac{\partial J(\Theta)}{\partial z^{(3)}} \frac{\partial z^{(3)}}{\partial a^{(2)}} \frac{\partial a^{(2)}}{\partial \Theta^{(1)}} \end{aligned}$$
我們分別計算等式右邊的三項可得:
$$ \frac{\partial J(\Theta)}{\partial z^{(3)}}=\delta^{(3)}$$
$$\frac{\partial z^{(3)}}{\partial a^{(2)}}=(\Theta^{(2)})^T$$
$$\frac{\partial a^{(2)}}{\partial \Theta^{(1)}}=\frac{\partial a^{(2)}}{\partial z^{(2)}} \frac{\partial z^{(2)}}{\partial \Theta^{(1)}}=g'(z^{(2)}) a^{(1)}$$
帶入后得
$$\frac{\partial J(\Theta)}{\partial \Theta^{(1)}}=(a^{(1)})^T \delta^{(3)} (\Theta^{(2)})^T g'(z^{(2)})$$
令$\delta^{(2)}=\delta^{(3)} (\Theta^{(2)})^Tg'(z^{(2)})$, 上式可以重寫為
$$\frac{\partial J(\Theta)}{\partial \Theta^{(1)}}=(a^{(1)})^T \delta^{(2)}$$
$$\delta^{(2)}=\delta^{(3)} (\Theta^{(2)})^T g'(z^{(2)})$$
把上面的結果放在一起,我們得到$J(\Theta)$對兩個權重矩陣的偏導數為:
$$\delta^{(3)}=a^{(3)}-y$$
$$\frac{\partial J(\Theta)}{\partial\Theta^{(2)}}=(a^{(2)})^T\delta^{(3)}$$
$$\delta^{(2)}=\delta^{(3)} (\Theta^{(2)})^T g'(z^{(2)})$$
$$\frac{\partial J(\Theta)}{\partial \Theta^{(1)}}=(a^{(1)})^T \delta^{(2)}$$
觀察上面的四個等式,我們發現
- 偏導數可以由當前層神經元向量$a^{(l)}$與下一層的誤差向量$\delta^{(l+1)}$相乘得到
- 當前層的誤差向量$\delta^{(l)}$可以由下一層的誤差向量$\delta^{(l+1)}$與權重矩陣$\Delta^{l}$的乘積得到
所以可以從后往前逐層計算誤差向量(這就是后向傳播的來源),然后通過簡單的乘法運算得到代價函數對每一層權重矩陣的偏導數。到這里算是終於明白為什么要計算誤差向量,以及為什么誤差向量之間有遞歸關系了。盡管這里的神經網絡十分簡單,推導過程也不是十分嚴謹,但是通過這個簡單的例子,基本能夠理解后向傳播算法的工作原理了。
嚴謹的后向傳播算法(計算梯度)
假設我們有$m$個訓練example,$L$層神經網絡,並且此處考慮正則項,即
$J(\Theta) = -\frac{1}{m}\left[\sum\limits_{i=1}^{m}\sum\limits_{k=1}^{K}y^{(i)}_{k}log(h_\theta(x^{(i)}))_k + (1-y^{(i)}_k)log(1-(h_\theta(x^{(i)}))_k)\right] + \frac{\lambda}{2m}\sum\limits_{l=1}^{L-1}\sum\limits_{i=1}^{s_l}\sum\limits_{j=1}^{s_{l+1}}(\Theta_{ji}^{(l)})^2$
初始化:設置$\Delta^{(l)}_{ij}=0$ (理解為對第$l$層的權重矩陣的偏導累加值)
For i = 1 : m
- 設置 $a^{(1)}=X$
- 通過前向傳播算法(FP)計算對各層的預測值$a^{(l)}$,其中$l=2,3,4,\ldots,L$
- 計算最后一層的誤差向量 $\delta^{(L)}=a^{(L)}-y$,利用后向傳播算法(BP)從后至前逐層計算誤差向量 $\delta^{(L-1)}, \delta^{(L-1)}, \ldots, \delta^{(2)}$, 計算公式為$\delta^{(l)}=(\Theta^{(l)})^T\delta^{(l+1)}.*g'(z^{(l)})$
- 更新$\Delta^{(l)}=\Delta^{(l)}+\delta^{(l+1)}(a^{(l)})^T$
end // for
計算梯度:
$$D_{ij}^{(l)}=\frac{1}{m}\Delta^{(l)}_{ij}, j=0$$
$$D_{ij}^{(l)}=\frac{1}{m}\Delta^{(l)}_{ij}+\frac{\lambda}{m}\Theta_{ij}^{(l)}, j\neq 0$$
$$\frac{\partial J(\Theta)}{\partial \Theta^{(l)}}=D^{(l)}$$
BP實際運用中的技巧
1. 將參數展開成向量
對於四層三個權重矩陣參數$\Theta^{(1)}, \Theta^{(2)}, \Theta^{(3)}$將其展開成一個參數向量,Matlab code如下:
thetaVec = [Theta1(:); Theta2(:); Theta3(:)];
2. 梯度檢查
為了保證梯度計算的正確性,可以用數值解進行檢查,根據導數的定義
$$\frac{dJ(\theta)}{d\theta} \approx \frac{J(\theta + \epsilon)-J(\theta-\epsilon)}{2\epsilon}$$
Matlab Code 如下
for i = 1 : n
thetaPlus = theta;
thetaPlus(i) = thetaPlus(i) + EPS;
thetaMinus = theta;
thetaMinus(i) = thetaMinus(i) - EPS;
gradApprox(i) = (J(thetaPlus) - J(thetaMinus)) / (2 * EPS);
end
最后檢查 gradApprox 是否約等於之前計算的梯度值即可。需要注意的是:因為近似的梯度計算代價很大,在梯度檢查后記得關閉梯度檢查的代碼。
3. 隨機初始化
初始權重矩陣的初始化應該打破對稱性 (symmetry breaking),避免使用全零矩陣進行初始化。可以采用隨機數進行初始化,即 $\Theta^{(l)}_{ij} \in [-\epsilon, +\epsilon]$
如何訓練一個神經網絡
- 隨機初始化權重矩陣
- 利用前向傳播算法(FP)計算模型預測值$h_\theta(x)$
- 計算代價函數$J(\Theta)$
- 利用后向傳播算法(BP)計算代價函數的梯度 $\frac{\partial J(\Theta)}{\partial \Theta^{(l)}}$
- 利用數值算法進行梯度檢查(gradient checking),確保正確后關閉梯度檢查
- 利用梯度下降(或者其他優化算法)求得最優參數$\Theta$
附:一個簡短的后向傳播教學視頻
參考文獻
[1] Andrew Ng Coursera 公開課第五周
[2] Derivation of Backpropagation. http://web.cs.swarthmore.edu/~meeden/cs81/s10/BackPropDeriv.pdf
[3] Wikipedia: Backpropagation. https://en.wikipedia.org/wiki/Backpropagation
[4] How the backpropagation algorithm works. http://neuralnetworksanddeeplearning.com/chap2.html
[5] 神經網絡和反向傳播算法推導. http://www.mamicode.com/info-detail-671452.html
