深度神經網路(DNN)反向傳播演算法(BP)

劉建平Pinard發表於2017-02-21

    在深度神經網路(DNN)模型與前向傳播演算法中,我們對DNN的模型和前向傳播演算法做了總結,這裡我們更進一步,對DNN的反向傳播演算法(Back Propagation,BP)做一個總結。

1. DNN反向傳播演算法要解決的問題

    在瞭解DNN的反向傳播演算法前,我們先要知道DNN反向傳播演算法要解決的問題,也就是說,什麼時候我們需要這個反向傳播演算法? 

    回到我們監督學習的一般問題,假設我們有m個訓練樣本:$\{(x_1,y_1), (x_2,y_2), ..., (x_m,y_m)\}$,其中$x$為輸入向量,特徵維度為$n\_in$,而$y$為輸出向量,特徵維度為$n\_out$。我們需要利用這m個樣本訓練出一個模型,當有一個新的測試樣本$(x_{test},?)$來到時, 我們可以預測$y_{test}$向量的輸出。 

    如果我們採用DNN的模型,即我們使輸入層有$n\_in$個神經元,而輸出層有$n\_out$個神經元。再加上一些含有若干神經元的隱藏層。此時我們需要找到合適的所有隱藏層和輸出層對應的線性係數矩陣$W$,偏倚向量$b$,讓所有的訓練樣本輸入計算出的輸出儘可能的等於或很接近樣本輸出。怎麼找到合適的引數呢?

    如果大家對傳統的機器學習的演算法優化過程熟悉的話,這裡就很容易聯想到我們可以用一個合適的損失函式來度量訓練樣本的輸出損失,接著對這個損失函式進行優化求最小化的極值,對應的一系列線性係數矩陣$W$,偏倚向量$b$即為我們的最終結果。在DNN中,損失函式優化極值求解的過程最常見的一般是通過梯度下降法來一步步迭代完成的,當然也可以是其他的迭代方法比如牛頓法與擬牛頓法。如果大家對梯度下降法不熟悉,建議先閱讀我之前寫的梯度下降(Gradient Descent)小結

    對DNN的損失函式用梯度下降法進行迭代優化求極小值的過程即為我們的反向傳播演算法。

2. DNN反向傳播演算法的基本思路

    在進行DNN反向傳播演算法前,我們需要選擇一個損失函式,來度量訓練樣本計算出的輸出和真實的訓練樣本輸出之間的損失。你也許會問:訓練樣本計算出的輸出是怎麼得來的?這 個輸出是隨機選擇一系列$W,b$,用我們上一節的前向傳播演算法計算出來的。即通過一系列的計算:$a^l = \sigma(z^l) = \sigma(W^la^{l-1} + b^l)$。計算到輸出層第$L$層對應的$a^L$即為前向傳播演算法計算出來的輸出。

    回到損失函式,DNN可選擇的損失函式有不少,為了專注演算法,這裡我們使用最常見的均方差來度量損失。即對於每個樣本,我們期望最小化下式:$$J(W,b,x,y) = \frac{1}{2}||a^L-y||_2^2$$

    其中,$a^L$和$y$為特徵維度為$n\_out$的向量,而$||S||_2$為S的L2範數。

    損失函式有了,現在我們開始用梯度下降法迭代求解每一層的$W,b$。

    首先是輸出層第$L$層。注意到輸出層的$W,b$滿足下式:$$a^L = \sigma(z^L) = \sigma(W^La^{L-1} + b^L)$$

    這樣對於輸出層的引數,我們的損失函式變為:$$J(W,b,x,y) = \frac{1}{2}||a^L-y||_2^2 =  \frac{1}{2}|| \sigma(W^La^{L-1} + b^L)-y||_2^2$$

    這樣求解$W,b$的梯度就簡單了:$$\frac{\partial J(W,b,x,y)}{\partial W^L} = \frac{\partial J(W,b,x,y)}{\partial z^L}\frac{\partial z^L}{\partial W^L} =(a^L-y) \odot \sigma^{'}(z^L)(a^{L-1})^T$$$$\frac{\partial J(W,b,x,y)}{\partial b^L} = \frac{\partial J(W,b,x,y)}{\partial z^L}\frac{\partial z^L}{\partial b^L} =(a^L-y)\odot \sigma^{'}(z^L)$$

    注意上式中有一個符號$\odot$,它代表Hadamard積,對於兩個維度相同的向量$A(a_1,a_2,...a_n)^T$和$B(b_1,b_2,...b_n)^T$,則$A \odot B = (a_1b_1, a_2b_2,...a_nb_n)^T$。

    我們注意到在求解輸出層的$W,b$的時候,有公共的部分$\frac{\partial J(W,b,x,y)}{\partial z^L}$,因此我們可以把公共的部分即對$z^L$先算出來,記為:$$\delta^L = \frac{\partial J(W,b,x,y)}{\partial z^L} = (a^L-y)\odot \sigma^{'}(z^L)$$

    現在我們終於把輸出層的梯度算出來了,那麼如何計算上一層$L-1$層的梯度,上上層$L-2$層的梯度呢?這裡我們需要一步步的遞推,注意到對於第$l$層的未啟用輸出$z^l$,它的梯度可以表示為:$$\delta^l =\frac{\partial J(W,b,x,y)}{\partial z^l} = \frac{\partial J(W,b,x,y)}{\partial z^L}\frac{\partial z^L}{\partial z^{L-1}}\frac{\partial z^{L-1}}{\partial z^{L-2}}...\frac{\partial z^{l+1}}{\partial z^{l}}$$

    如果我們可以依次計算出第$l$層的$\delta^l$,則該層的$W^l,b^l$很容易計算?為什麼呢?注意到根據前向傳播演算法,我們有:$$z^l= W^la^{l-1} + b^l$$

    所以根據上式我們可以很方便的計算出第l層的$W^l,b^l$的梯度如下:$$\frac{\partial J(W,b,x,y)}{\partial W^l} = \frac{\partial J(W,b,x,y)}{\partial z^l} \frac{\partial z^l}{\partial W^l} = \delta^{l}(a^{l-1})^T$$$$\frac{\partial J(W,b,x,y)}{\partial b^l} = \frac{\partial J(W,b,x,y)}{\partial z^l} \frac{\partial z^l}{\partial b^l} = \delta^{l}$$

    那麼現在問題的關鍵就是要求出$ \delta^{l}$了。這裡我們用數學歸納法,第$L$層的$\delta^{L}$上面我們已經求出, 假設第$l+1$層的$\delta^{l+1}$已經求出來了,那麼我們如何求出第$l$層的$\delta^{l}$呢?我們注意到:$$\delta^{l} = \frac{\partial J(W,b,x,y)}{\partial z^l} = \frac{\partial J(W,b,x,y)}{\partial z^{l+1}}\frac{\partial z^{l+1}}{\partial z^{l}} = \delta^{l+1}\frac{\partial z^{l+1}}{\partial z^{l}}$$

    可見,用歸納法遞推$\delta^{l+1}$和$\delta^{l}$的關鍵在於求解$\frac{\partial z^{l+1}}{\partial z^{l}}$。

    而$z^{l+1}$和$z^{l}$的關係其實很容易找出:$$z^{l+1}= W^{l+1}a^{l} + b^{l+1} = W^{l+1}\sigma(z^l) + b^{l+1} $$

    這樣很容易求出:$$\frac{\partial z^{l+1}}{\partial z^{l}} = (W^{l+1})^T\odot \underbrace{(\sigma^{'}(z^l),..,\sigma^{'}(z^l))}_{n_{l+1}}$$

    將上式帶入上面$\delta^{l+1}$和$\delta^{l}$關係式我們得到:$$\delta^{l} = \delta^{l+1}\frac{\partial z^{l+1}}{\partial z^{l}} = (W^{l+1})^T\delta^{l+1}\odot \sigma^{'}(z^l)$$

    現在我們得到了$\delta^{l}$的遞推關係式,只要求出了某一層的$\delta^{l}$,求解$W^l,b^l$的對應梯度就很簡單的。

    (注意,上面的矩陣求導推導部分不太嚴謹,定性理解即可。)

3. DNN反向傳播演算法過程

    現在我們總結下DNN反向傳播演算法的過程。由於梯度下降法有批量(Batch),小批量(mini-Batch),隨機三個變種,為了簡化描述,這裡我們以最基本的批量梯度下降法為例來描述反向傳播演算法。實際上在業界使用最多的是mini-Batch的梯度下降法。不過區別僅僅在於迭代時訓練樣本的選擇而已。

    輸入: 總層數L,以及各隱藏層與輸出層的神經元個數,啟用函式,損失函式,迭代步長$\alpha$,最大迭代次數MAX與停止迭代閾值$\epsilon$,輸入的m個訓練樣本$\{(x_1,y_1), (x_2,y_2), ..., (x_m,y_m)\}$

    輸出:各隱藏層與輸出層的線性關係係數矩陣$W$和偏倚向量$b$

    1) 初始化各隱藏層與輸出層的線性關係係數矩陣$W$和偏倚向量$b$的值為一個隨機值。

      2)for iter to 1 to MAX:

    2-1) for i =1 to m:

      a) 將DNN輸入$a^1$設定為$x_i$

      b) for $l$=2 to L,進行前向傳播演算法計算$a^{i,l} = \sigma(z^{i,l}) = \sigma(W^la^{i,l-1} + b^l)$

      c) 通過損失函式計算輸出層的$\delta^{i,L}$

      d) for $l$= L-1 to 2, 進行反向傳播演算法計算$\delta^{i,l} =  (W^{l+1})^T\delta^{i,l+1}\odot \sigma^{'}(z^{i,l})$

    2-2) for $l$ = 2 to L,更新第$l$層的$W^l,b^l$:$$W^l = W^l -\alpha \sum\limits_{i=1}^m \delta^{i,l}(a^{i, l-1})^T $$$$b^l = b^l -\alpha \sum\limits_{i=1}^m \delta^{i,l}$$

    2-3) 如果所有$W,b$的變化值都小於停止迭代閾值$\epsilon$,則跳出迭代迴圈到步驟3。

    3) 輸出各隱藏層與輸出層的線性關係係數矩陣$W$和偏倚向量$b$。

4. DNN反向傳播演算法小結

    有了DNN反向傳播演算法,我們就可以很方便的用DNN的模型去解決第一節裡面提到了各種監督學習的分類迴歸問題。當然DNN的引數眾多,矩陣運算量也很大,直接使用會有各種各樣的問題。有哪些問題以及如何嘗試解決這些問題並優化DNN模型與演算法,我們在下一篇講。

 

(歡迎轉載,轉載請註明出處。歡迎溝通交流: liujianping-ok@163.com) 

參考資料:

1) Neural Networks and Deep Learning by By Michael Nielsen

2) Deep Learning, book by Ian Goodfellow, Yoshua Bengio, and Aaron Courville

3) UFLDL Tutorial

 

相關文章