深度神經網絡(Deep Neural Networks,簡稱DNN)是深度學習的基礎。
回顧監督學習的一般性問題。假設我們有$m$個訓練樣本$\{(x_1, y_1), (x_2, y_2), …, (x_m, y_m)\}$,其中$x$為輸入向量,$y$為輸出向量,利用這個訓練樣本訓練模型的參數,使得給定模型一個$x_{test}$,其能夠預測$y_{test}$。
采用CNN模型的時候,$x$輸入向量全部喂給輸入層,$y$輸出向量和輸出層的向量一起計算損失函數,而其中若干個神經元的隱藏層,每一個隱藏層都有對應的權重矩陣$W$和偏置向量$b$,對於訓練過程中,喂入樣本$x$得到$y_{predict}$,根據$y_{predict}$以及$y$計算出的損失函數,怎么去更新網絡中的參數,即需要反向傳播算法。在機器學習中,求出損失函數的最小極值,其對應的參數即為我們所期望的到的。在DNN中,常用的優化極值求解過程的方法為梯度下降法,其他還有牛頓法、擬牛頓法等等。
綜上,對DNN的損失函數采用梯度下降法進行迭代優化求極小值的過程即為反向傳播算法。
1 - DNN反向傳播算法
定義一個損失函數,度量訓練樣本通過模型的預測輸出與真實輸出之間的差距(損失)。訓練樣本的預測輸出可以通過一系列對於第l層的一般公式${a^{l}}=\sigma(z^{l})=\sigma(W^{l}a^{l-1}+b^{l})$計算得出。輸出層對應的${a^{L_{output}}}$即為模型預測的輸出。
DNN常用可選擇均方差來作為損失函數,其公式如下$$J(W,b,x,y)=\frac{1}{2}\begin{Vmatrix}a^{L}-y \end{Vmatrix}^2_2$$
其中$a^L$和$y$分別為預測輸出和期望真實輸出(期望輸出),而$\begin{Vmatrix}S\end{Vmatrix}_2$為$S$的$L2$范數。
對於輸出層$L_{output}$,其$W_{output}$和$b_{output}$滿足如下公式:$${a^{L_{output}}}=\sigma(z^{L_{output}})=\sigma(W^{L_{output}}a^{L_{output\_prev}}+b^{L_{output}})$$
因此,對於輸出層的參數,我們有損失函數如下:
$$J(W,b,x,y)=\frac{1}{2}\begin{Vmatrix}a^{L_{output}}-y\end{Vmatrix}^2_2=\frac{1}{2}\begin{Vmatrix} \sigma(W^{L_{output}}a^{L_{output\_prev}}+b^{L_{output}})-y\end{Vmatrix}^2_2$$
因此對於該損失函數,可對其對於輸出層的$W_{output}$和$b_{output}$分別求偏導數從而得到梯度,如下:
$$\frac{\partial J(W,b,x,y)}{\partial W^{L_{output}}}=\frac{\partial J(W,b,x,y)}{\partial z^{L_{output}}}\frac{\partial z^{L_{output}}}{\partial W^{L_{output}}}=(a^{L_{output}}-y)\bigodot \sigma^{'}(z^{L_{output}})(a^{L_{output\_prev}})^T$$
$$\frac{\partial J(W,b,x,y)}{\partial b^{L_{output}}}=\frac{\partial J(W,b,x,y)}{\partial z^{L_{output}}}\frac{\partial z^{L_{output}}}{\partial b^{L_{output}}}=(a^{L_{output}}-y)\bigodot \sigma^{'}(z^{L_{output}})$$
上述$\bigodot$代表$Hadamard$積,對於兩個維度相同的向量$A(a_1,a_2,...,a_n)^T$和$B(b_1,b_2,...,b_n)^T$,有${A}\bigodot{B}=(a_1b_1,a_2b_2,...,a_n,b_n)^T$。
對於$W_{output}$和$b_{output}$,有公共部分$\frac{\partial J(W,b,x,y)}{\partial z^{L_{output}}}$,將其記做$\delta^L$,如下:
$$\delta^L=\frac{\partial J(W,b,x,y)}{\partial z^{L_{output}}}=(a^{L_{output}}-y)\bigodot \sigma^{'}(z^{L_{output}})$$
以上就是計算輸出層的梯度,而對於第l層的梯度,根據鏈式法則可得公式如下:
$$\delta^l=\frac{\partial J(W,b,x,y)}{\partial z^{l}}=\frac{\partial J(W,b,x,y)}{\partial z^{L_{output}}}\frac{\partial z^{L_{output}}}{\partial z^{L-1}}\frac{\partial z^{L-1}}{\partial z^{L-2}}...\frac{\partial z^{l+1}}{\partial z^{l}}$$
注意到,其中$L_{output}$等價於$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$。注意到有遞推公式$\delta^l=\frac{\partial J(W,b,x,y)}{\partial z^l}=\frac{\partial J(W,b,x,y)}{\partial z^{l+l}}\frac{z^{l+1}}{z^l}=\delta^{l+1}\frac{\partial z^{l+1}}{\partial z^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\bigodot\begin{matrix}\underbrace{(\sigma^{'}(z^l),...,\sigma^{'}(z^l))}\\ n={l+1}\end{matrix}$$
代入上式可以得到:
$$\delta^l=\delta^{l+1}\frac{\partial z^{l+1}}{\partial z^l}=(W^{l+1})^T\delta^{l+1}\bigodot\sigma^{'}(z^{l})$$
綜上,可以通過$\delta^l$求出對應l層的$W^l$和$b^l$的梯度。
2 - DNN反向傳播偽代碼
initialize all variables by random value for loop from 1 to num_epoch choose x_i as the model input compute the output of the output-layer a^L compute the δ^L of the output-layer for l=L to 2 compute the δ^l based on δ^(l+1) and W^(l+1) and z^l compute the gradient of W^l and b^l update the W^l and b^l in lth-layer:W^l = W^l-αsum(δ^l(a^(l-1)^T), b^l=b^l-αsum(δ^l)