深度學習 - 反向傳播算法


理解反向傳播

要理解反向傳播,先來看看正向傳播。下面是一個神經網絡的一般結構圖:

其中,\(x\) 表示輸入樣本,\(\bm{w}\) 表示未知參數(圖中未標出偏置 \(b\)), \(S\) 表示激活函數,\(y\) 表示預測值,\(\hat{y}\) 表示真實值。
顯然,通過從樣本 \(x\) 的輸入,以及一連串激活函數的運算,最終可以得到預測值 \(y\),從而可以計算損失函數的大小。如果誤差不達標(或者未達到迭代次數),我們就需要使用梯度下降的方法,先初始化出一組 \(w\),再沿梯度相反的方向對 \(w\) 進行不斷迭代,求出最優的一組參數。對任意一個參數 \(w_j\) 來說,都可以通過梯度下降法進行求解:
\(\begin{equation*} w_j = w_j - \frac{\partial{L(\bm{w})}}{\partial{w_j}} \end{equation*}\)

這個式子的關鍵是求梯度 \(\frac{\partial{L(\bm{w})}}{\partial{w_j}}\)。梯度在這里的含義是對 \(w_j\) 做一個微小的改變 \(\Delta{w_j}\),會導致損失函數產生 \(\Delta{L(\bm{w})}\) 的變化。觀察整個網絡傳輸的過程可以發現,\(\Delta{w_j}\) 並不直接作用於最終的輸出 \(\bm{y}\),而是先改變當前層神經元的輸入 \(z_j\),再改變當前層神經元的輸出 \(a_j\),而 \(a_j\) 又會作為下一層各神經元的輸入。所以這種影響是間接的、傳導性的:

一個參數就會引起后續所有神經元輸出的變化,這是一種鏈式傳導效應。所以如果要求梯度 \(\frac{\partial{L(\bm{w})}}{\partial{w_j}}\) ,就需要考慮后續這些被影響到的神經元,而要計算這些值的變化,則需要完成正向計算,然后才能計算出梯度,從而對參數進行更新。因為每一層的信息都依賴后面各層已經計算出的信息,看上去就像從反方向再傳遞一遍:

下面是以一個參數為例,表示參數的更新過程:

誤差的定義

上面說了,一個任意的參數 \(w_j\) 是通過依次改變神經元輸入 \(z_j\),神經元輸出 \(a_j\),從而最終影響到 \(\bm{y}\) 的。所以如果以神經元為單位,就可以說是由於神經元輸入 \(z_j\) 的改變導致了 \(\bm{y}\) 的變化,最終導致損失函數 \(L(\bm{w})\) 的變化。所以一個神經元輸入的改變對整個網絡的損失函數產生的誤差就可以表示為: \(\delta_j = \frac{\partial{L(\bm{w})}}{\partial{z_j}}\)
那么如何表示上圖中的鏈式傳導效應呢?巧了,導數中的鏈式法則正好可以描述這一現象:

所以有:

\(\frac{\partial{L(\bm{w})}}{\partial{w_j}} = \frac{\partial{z_j}}{\partial{w_j}} \frac{\partial{L(\bm{w})}}{\partial{z_j}} = \frac{\partial{z_j}}{\partial{w_j}}\delta_j \\\)
\(\delta_j = \frac{\partial{L(\bm{w})}}{\partial{z_j}} = \frac{\partial{a_j}}{\partial{z_j}} \frac{\partial{L(\bm{w})}}{\partial{a_j}}\)

誤差的傳導過程

1.打通傳導鏈路

目前這個鏈式傳導好像卡在了 \(w_j\) 參數所在的這一層,無法繼續向下一層傳導,因為我們沒有顯式的定義神經網絡的層數。所以在這里我們需要新增關於層數的參數 \(l\)

\(w^{l}_{jk}\) 表示第 \(l-1\) 層的第 \(k\) 個神經元到第 \(l\) 層的第 \(j\) 個神經元的參數 \(w\)
\(b^{l}_j\) 表示第 \(l\) 層的第 \(j\) 個神經元的參數 \(b\)
\(z^l_j\) 表示第 \(l\) 層的第 \(j\) 個神經元的輸入;
\(a^l_j\) 表示第 \(l\) 層的第 \(j\) 個神經元的輸出;
\(\delta^l_j\) 表示第 \(l\) 層的第 \(j\) 個神經元的誤差。

有了 \(l\),我們便可以使用 \(l\) 層的輸出 \(a^l_j\),定義 \(l+1\) 層的輸入 \(z^{l+1}_k\) 了(假設 \(l\) 層 有 \(j\) 個神經元,\(l+1\) 層有 \(k\) 個神經元):

\(z^{l+1}_k = \sum_{j}w^{l+1}_{kj}{a^l_j} + b^{l+1}_k\)

由此,我們也可以讓第 \(l\) 層第 \(j\) 個神經元產生的誤差 \(\delta^l_j\)\(l+1\) 層的所有神經元(共 \(k\) 個)進行傳播

\(\delta^l_j = \frac{\partial{L(\bm{w})}}{\partial{z^l_j}} = \sum_{k}\frac{\partial{z^{l+1}_k}}{\partial{z^l_j}} \frac{\partial{L(\bm{w})}}{\partial{z^{l+1}_k}}\)

注意到,\(\frac{\partial{L(\bm{w})}}{\partial{z^{l+1}_k}} = \delta^{l+1}_k\)\(\frac{\partial{z^{l+1}_k}}{\partial{z^l_j}} = \frac{\partial{\sum_{J}w^{l+1}_{kj}{a^l_j} + b^{l+1}_k}}{\partial{z^l_j}}\)

因為 \(a^l_j = \sigma(z^l_j)\),其中 \(\sigma(z^l_j)\) 是激活函數,所以 \(\frac{\partial{z^{l+1}_k}}{\partial{z^l_j}} = w^{l+1}_{kj}{\sigma'(z^l_j)}\) (僅當 \(J = j\) 時有微分)

所以 \(\delta^l_j = \sum_{k}w^{l+1}_{kj}{\sigma'(z^l_j)}\delta^{l+1}_k\)

寫成向量形式:

\(\bm{\delta}^l = (\bm{w}^{l+1})^T \bm{\delta}^{l+1} \circ {\sigma'(\bm{z}^l)} \quad \quad \quad (1)\)

其中 \(\bm{w}^{l+1}\)\(k \times j\) 階向量,\(\bm{\delta}^{l+1}\)\(k \times 1\) 階向量,\(\bm{w}^{l+1}\) 轉置后與 \(\bm{\delta}^{l+1}\) 相乘,得到 $ j \times 1$ 的向量,而 \({\sigma'(\bm{z}^l)}\) 的維度也是 $ j \times 1$,所以需要使用 Hadamard 乘積進行計算,即兩個維度相同的向量對應位置的數相乘。
這個式子還有一個含義,就是可以通過 \(l+1\) 層的誤差,求出 \(l\) 層的誤差。所以這個式子是整個反向傳播能夠實現的關鍵。如果知道了最后一層(即輸出層)的誤差,就可以使用這個式子求出前面所有層的誤差。那么我們就來看看最后一層的誤差如何求出。

2.輸出層的誤差

由於輸出層的結果就是預測值,所以有:

\(\delta^l_j = \frac{\partial{L}}{\partial{z^l_j}} = \frac{\partial{L}}{\partial{a^l_j}}\frac{\partial{a^l_j}}{\partial{z^l_j}}\)

其中,\(\frac{\partial{L}}{\partial{a^l_j}} = \nabla_{a_j}L ;\quad \frac{\partial{a^l_j}}{\partial{z^l_j}} = \frac{\partial{\sigma(z^l_j)}}{\partial{z^l_j}} = \sigma'(z^l_j)\)

寫成向量形式:

\(\bm{\delta}^l = \nabla_{\bm{a}^l}L \circ \sigma'(\bm{z}^l) \quad \quad \quad \quad \quad \quad (2)\)

\(\nabla_{a^l}L\) 與損失函數的形式相關,如果使用均方誤差作為損失函數,則:

\(\nabla_{a}L = \frac{\partial{\frac{1}{2}(a^l - y)^2}}{\partial{a^l}} = (a^l - y)\)

3.通過誤差求梯度

我們再回到最初的式子:

\(\frac{\partial{L(\bm{w})}}{\partial{w^l_{jk}}} = \frac{\partial{z^l_j}}{\partial{w^l_{jk}}} \frac{\partial{L(\bm{w})}}{\partial{z^l_j}} = \frac{\partial{z^l_j}}{\partial{w^l_{jk}}}\delta^l_j \\\)

其中 \(\delta^l_j\) 可通過反向傳播求出,而 \(\frac{\partial{z^l_j}}{\partial{w^l_{jk}}} = \frac{\partial{w^l_{jk}a^{l-1}_k + b^l_j}}{\partial{w^l_{jk}}} = a^{l-1}_k\)
所以:

\(\frac{\partial{L(\bm{w})}}{\partial{w^l_{jk}}} = a^{l-1}_k \delta^l_j \quad \quad \quad \quad \quad \quad \quad (3)\)
同理可得:
\(\frac{\partial{L(\bm{w})}}{\partial{b^l_{j}}} = \delta^l_j \quad \quad \quad \quad \quad \quad \quad \quad \quad (4)\)

至此,我們就求出了參數 \(w\)\(b\) 的梯度,從而可以通過對整個網絡的不斷迭代,優化初始模型。

具體計算過程

下面以一個只有兩個神經元、一個隱藏層的簡單神經網絡為例,闡述一下整個過程。

其中,\(z_{11}\) 為激活函數 \(S_{11}\) 的輸入,\(a_{11}\)\(S_{11}\) 的輸出,則有:
\(\begin{equation*} z_{11} = w_{11}x_1 + w_{12}x_2 + b_{11} \end{equation*}\)
\(\begin{equation*} a_{11} = \frac{1}{1 + e^{-z_{11}}} \end{equation*} \quad \quad \quad \quad \quad \quad \quad (\mbox{使用 } Sigmoid \mbox{ 函數作為激活函數})\)

\(z_{12}, z_{21}, z_{22}, a_{12}, a_{21}, a_{22}\)可同理得到。

1.正向計算

我們先觀察一下參數\(w_{11}\)在整個正向計算過程中的軌跡:
(1)\(w_{11}\)組成了神經元 \(S_{11}\) 的輸入 \(z_{11}\)
(2)\(S_{11}\) 神經元經過計算后輸出 \(a_{11}\)
(3)\(a_{11}\) 又作為輸入,組成了 \(z_{21}, z_{22}\),並參與到神經元 \(S_{21}, S_{22}\) 的計算中,得到 \(a_{21}, a_{21}\),即預測值 \(y_{1}、y_{2}\)\(S_{2n}\) 為輸出層)。
所以可以這么理解,\(w_{11}\)只與這些值有關,而與網絡中的其他值無關。由此可以得到如下關系:

根據這個關系,我們可以便可以得到 \(\frac{\partial{L(\bm{\theta})}}{\partial{w_{11}}}\)

我們再對公式中的各項依次求解:

只要我們隨機初始化一組\(w\),就能得到這些項的值。

2.反向更新參數

有了上面那些通過正向計算得到的值,其實只要從下到上這么反向計算,就能得到我們要求的偏導數:

至此,我們就能夠對\(w_{11}\)進行更新了:

\(w_{11} = w_{11} - \eta\frac{\partial{L(\bm{\theta})}}{\partial{w_{11}}}\)

下面再帶入具體值,手算一下更新的過程。

手算神經網絡

1.正向計算

(1)初始化\(\bm{w}\)

為了能夠更好地了解這一過程,我們可以直接帶入真實值進行計算,從而可以避免摻雜過多的符號。下面是一個初始化好的神經網絡:

(2)計算輸入與輸出值

\(\begin{equation*} z_{11} = 0.15\times0.05 + 0.2\times0.1 +0.35 = 0.3775 \end{equation*}\)

\(\begin{equation*} a_{11} = \frac{1}{1 + e^{-0.3775}} = 0.5933 \end{equation*}\)

\(\begin{equation*} z_{12} = 0.25\times0.05 + 0.3\times0.1 +0.35= 0.3925 \end{equation*}\)

\(\begin{equation*} a_{12} = \frac{1}{1 + e^{0.3925}} = 0.5969 \end{equation*}\)

\(\begin{equation*} z_{21} = 0.4\times0.5933 + 0.45\times0.5969 +0.6 = 1.1059 \end{equation*}\)

\(\begin{equation*} z_{22} = 0.55\times0.5933 + 0.5\times0.5969 +0.6 = 1.2248 \end{equation*}\)

\(\begin{equation*} a_{21} = \frac{1}{1 + e^{-1.1059}} = 0.7514 \end{equation*}\)

\(\begin{equation*} a_{22} = \frac{1}{1 + e^{-1.2248}} = 0.7729 \end{equation*}\)

由此我們得到了預測值 \((0.7514, 0.7729)\) ,這與真實值 \((0.01, 0.99)\) 相差的非常多,所以需要進行反向更新。

2.反向更新參數

根據公式進行計算:

通過這樣的計算,便可以成功更新神經網絡中的每個參數了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM