神經網絡及其訓練

在前面的博客人工神經網絡入門訓練深度神經網絡,也介紹了與本文相似的內容。前面的兩篇博客側重的是如何使用TensorFlow實現,而本文側重相關數學公式及其推導。html

1 神經網絡基礎

1.1 單個神經元

一個神經元就是一個計算單元,傳入$n$個輸入,產生一個輸出,再應用於激活函數。記$n$維輸入向量爲$x$,$n$維權重矩陣向量是$w$,偏置項爲$b$,激活函數爲sigmoid,最終激活後的輸出爲$a$:web

\begin{align*}
a = \frac{1}{1 + \exp(-(w^T x + b))}
\end{align*}安全

將權重和偏置項組合在一塊兒,獲得以下公式:網絡

\begin{align*}
a = \frac{1}{1 + \exp(-[w^T \quad b] \cdot [x \quad 1])}
\end{align*}函數

圖1更直觀地描述了該公式:翻譯

圖1 單個神經元的輸入及輸出htm

1.2 單層神經元

將單個神經元擴展到一層,共$m$個神經元,每一個神經元的輸入都是$x$,權重記作$\{ w^{(i)}, \cdots, w^{(m)} \}$,偏置項記作$\{ b^{(i)}, \cdots, b^{(m)} \}$,則每一個神經元激活後的輸出:blog

\begin{align*}
a_1 &= \frac{1}{1 + \exp(-((w^{(1)})^T x + b_1))} \\
&\vdots \\
a_m &= \frac{1}{1 + \exp(-((w^{(m)})^T x + b_m))}
\end{align*}遞歸

下面咱們定義更抽象的形式,以便用於複雜的神經網絡:ci

\begin{align*}
&W = \begin{bmatrix} - & w^{(1)T} & -\\ & \cdots & \\ - & w^{(m)T} & - \end{bmatrix} \in \mathbb{R}^{m \times n} \\
&b = \begin{bmatrix} b_1\\ \vdots \\ b_m \end{bmatrix} \in \mathbb{R}^m \\
&z = Wx + b \\
&\sigma(z) = \begin{bmatrix} \frac{1}{1 + \exp(-z_1)}\\ \vdots \\ \frac{1}{1 + \exp(-z_m)} \end{bmatrix} \\
&\begin{bmatrix} a^{(1)}\\ \vdots \\ a^{(m)} \end{bmatrix} = \sigma(z) = \sigma(Wx + b)
\end{align*}

1.3 前饋計算

 

圖2 簡單的前饋神經網絡

如圖2所示的神經網絡,只有1個隱層,輸出:

\begin{align*}
s = U^T a = U^T f(Wx + b)
\end{align*}

其中,$f$是激活函數。

維度分析:假設詞向量維度爲2,一次使用5個詞做爲輸入,則輸入$x \in \mathbb{R}^{20}$。若是隱層有8個sigmoid神經元,並在輸出層產生1個未規範化的分值,那麼$W \in \mathbb{R}^{8 \times 20},b \in \mathbb{R}^{8},U \in \mathbb{R}^{8 \times 1},s \in \mathbb{R}$。

1.4 最大間隔目標函數

最大間隔目標函數的思想是,確保正樣本的分值高於負樣本的分值。這與SVM的目標韓式較爲類似。正樣本經神經網絡計算,獲得的分值記作$s$,負樣本記作$s_c$,目標函數就是最大化$(s - s_c)$,或者最小化$(s_c - s)$。只有在$s_c > s$時才須要更新神經網絡的參數。所以,若是$s_c > s$,則損失是$s_c - s$;不然,損失是0。所以損失函數:

\begin{align*}
J = \max(s_c-s,0)
\end{align*}

訓練神經網絡的目標是使得$J$最小。

爲了獲得一個更安全的邊界,咱們但願正樣本分值比負樣本分值大出$\Delta$(大於0),所以:

\begin{align*}
J = \max(s_c - s + \Delta ,0)
\end{align*}

其實爲了簡化公式,能夠直接取$\Delta = 1$(根據SVM提到的知識,對函數距離的縮放,不會影響最終結果。$s$和$s_c$都是函數距離),模型在訓練過程當中其參數會自動適應這一約束,且不影響最終結果。此時目標函數:

\begin{align*}
J = \max(s_c - s + 1 ,0)
\end{align*}

1.5 反向傳播訓練模型

咱們須要求得損失函數關於每一個參數的偏導數,而後使用梯度降低更新參數:

\begin{align*}
\theta^{(t+1)} = \theta^{(t)} - \alpha \nabla_{\theta^{(t)}} J
\end{align*}

反向傳播使用鏈式求導法則,求得損失函數關於每一個參數的偏導數。爲了進一步理解這一技術,首先看一下圖3的神經網絡:

圖3

上圖的神經網絡只有一個隱層,一個輸出。爲簡單起見,定義如下機率:

  • $x_i$是神經網絡的一個輸入
  • $s$是神經網絡的輸出
  • 第$k$層的第$j$個神經元接受標量輸入$z^{(k)}_j$併產生標量激活輸出$a^{(k)}_j$
  • 將$z^{(k)}_j$算出的反向傳播偏差記作$\delta^{(k)}_j$
  • 第一層是指輸入層,而不是第一個隱層。對於輸入層,$x_j = z^{(1)}_j = a^{(1)}_j$
  • $W^{(k)}$是轉移矩陣,將第$k$層的輸出映射爲第$k+1$層的輸入

圖4 與更新$W^{(1)}_{14}$相關的部分

如圖4,若是要更新$W^{(1)}_{14}$,首先要意識到,只有在計算$z^{(2)}_1$時纔會用到$W^{(1)}_{14}$。$z^{(2)}_1$僅僅用於計算了$a^{(2)}_1$,$a^{(2)}_1$與$W^{(2)}_1$用於計算最終的分值。首先有算是函數關於$s$和$s_c$的偏導數:

\begin{align*}
\frac{\partial J}{\partial s} = -\frac{\partial J}{\partial s_c} = -1
\end{align*}

爲簡單起見,咱們只計算$\frac{\partial s}{\partial w^{(1)}_{ij}}$:

\begin{align*}
\frac{\partial s}{\partial w^{(1)}_{ij}} &= \frac{\partial W^{(2)} a^{(2)}}{\partial w^{(1)}_{ij}} \tag{1} \\
&= \frac{\partial W^{(2)}_i a^{(2)}_i}{\partial w^{(1)}_{ij}} \tag{2} \\
&= W^{(2)}_i \frac{\partial a^{(2)}_i}{\partial w^{(1)}_{ij}} \tag{3} \\
\end{align*}

第(1)步很直觀,由於$s = W^{(2)} a^{(2)}$。第(2)步是由於,只有在計算標量$a^{(2)}_i$時,纔會用到向量$W^{(1)}_i$。第(3)步也很直觀,咱們是在求關於$W^{(1)}_i$的偏導數,$W^{(2)}_i$直接看作常數。

而後應用鏈式法則:

\begin{align*}
W^{(2)}_i \frac{\partial a^{(2)}_i}{\partial w^{(1)}_{ij}} &= W^{(2)}_i \frac{\partial a^{(2)}_i}{\partial z^{(2)}_i} \frac{\partial z^{(2)}_i}{\partial w^{(1)}_{ij}} \\
&= W^{(2)}_i \frac{\partial f(z^{(2)}_i)}{\partial z^{(2)}_i} \frac{\partial z^{(2)}_i}{\partial w^{(1)}_{ij}} \\
&= W^{(2)}_i f'(z^{(2)}_i) \frac{\partial z^{(2)}_i}{\partial w^{(1)}_{ij}} \\
&= W^{(2)}_i f'(z^{(2)}_i) \frac{\partial}{\partial w^{(1)}_{ij}} (b^{(1)}_i + a^{(1)}_1W^{(1)}_{i1} + a^{(1)}_2W^{(1)}_{i2} + a^{(1)}_3W^{(1)}_{i3} + a^{(1)}_4W^{(1)}_{i4}) \\
&= W^{(2)}_i f'(z^{(2)}_i) a^{(1)}_j \\
&= \delta^{(2)}_i \cdot a^{(1)}_j
\end{align*}

$\delta^{(2)}_i$本質上是第2層第$i$個神經元反向傳回的偏差。

如今咱們換一種方式,用偏差分配和反向傳播來討論如何更新圖4中的更新$W^{(1)}_{14}$:

  1. 首先從$a^{(3)}_1$反向傳回偏差1
  2. 這個偏差乘以把$z^{(3)}_1$映射到$a^{(3)}_1$的神經元的導數。因爲輸出層沒有激活函數,$z^{(3)}_1 = a^{(3)}_1$,所以這一導數恰好是1,乘積依然是1,也就是$\delta^{(3)}_1 = 1$
  3. 目前偏差已經反向傳播到了$z^{(3)}_1 = 1$,咱們須要將偏差「公平分配」給$a^{(2)}_1 = 1$
  4. 到達$a^{(2)}_1$的偏差是$\delta^{(3)}_1 \times W^{(2)}_1 = W^{(2)}_1$
  5. 和第2不同,求得將$z^{(2)}_1$映射到a^{(2)}_1$的神經元的導數$f'(z^{(2)}_1)$
  6. 到達$z^{(2)}_1$的偏差$f'(z^{(2)}_1)W^{(2)}_1$,也就是$\delta^{(2)}_1 = 1$
  7. 而後須要將偏差「公平分配」給$W^{(1)}_{14}$,也就是上一步的偏差乘以$a^{(4)}_1$
  8. 所以,最終獲得損失函數關於$W^{(1)}_{14}$的偏導數$a^{(4)}_1 f'(z^{(2)}_1) W^{(2)}_{1}$

以上咱們用鏈式法則和偏差分配反向傳播獲得的結果是同樣的。

偏置項更新:偏置項也能夠當作輸入向量的一個維度,只不過這個維度始終爲1(這種1.1小節中的第二個公式就能夠看出)。所以,第$k$層第$i$個神經元偏置項的偏導數直接就是$\delta^{(k)}_i$。例如,在上面咱們是要更新$b^{(1)}_1$,而不是$W^{(1)}_{14}$,那麼梯度直接就是$f'(z^{(2)}_1) W^{(2)}_{1}$。

將$\delta^{(k)}$到$\delta^{(k-1)}$的偏差計算通常化:

 

圖5 從$\delta^{(k)}$到$\delta^{(k-1)}$的偏差傳播

  1. 咱們已經有了從$z^{(k)}_i$傳回的偏差$\delta^{(k)}$,如圖5左側所示
  2. 計算反向傳給$a^{(k-1)}_j$的偏差,經過$\delta^{(k)}_i$乘以路徑權重$W^{(k-1)}_{ij}$
  3. 所以,$a^{(k-1)}_j$接收到的偏差就是$\delta^{(k)}_i W^{(k-1)}_{ij}$
  4. 然而,$a^{(k-1)}_j$可能會前饋到下一層的多個節點,如圖5右側所示。這樣的話,$a^{(k-1)}_j$還要接收從$k$層的節點$m$反向傳回的偏差。
  5. 一次,$a^{(k-1)}_j$接收到的偏差是$\delta^{(k)}_i W^{(k-1)}_{ij} + \delta^{(k)}_m W^{(k-1)}_{mj}$
  6. 事實上,這能夠通常化爲$\sum_i \delta^{(k)}_i W^{(k-1)}_{ij}$
  7. 如今已經有了$a^{(k-1)}_j$的偏差,而且$a^{(k-1)}_j$關於$z^{(k-1)}_j$的導數爲$f'(z^{(k-1)}_j)$
  8. 所以,偏差傳到了$z^{(k-1)}_j$,記作$\delta^{(k-1)}_j$,大小爲$f'(z^{(k-1)}_j) \sum_i \delta^{(k)}_i W^{(k-1)}_{ij}$

1.6 反向傳播訓練向量化

用向量化的代碼取代for循環,有助於提升代碼的執行效率(能夠充分利用GPU加速吧?)。

上面咱們給出瞭如何計算一個參數的梯度,如今咱們介紹更通常化的方法,一次性地更新整個權重矩陣和偏置向量。這一簡單的擴張有助於爲咱們創建一種直覺,偏差傳播能夠抽象到矩陣-向量級別。

給出一個權重$W^{(k)}_{ij}$,咱們定義其偏差梯度爲$\delta^{(k+1)}_i \cdot a^{(k)}_j$。$W^{(k)}$是將$a^{(k)}$映射爲$z^{(k+1)}$的權重矩陣。咱們能夠創建整個矩陣$W^{(k)}$的偏差梯度:

\begin{align*}
\nabla_{W^{(k)}} = \begin{bmatrix}
\delta^{(k+1)}_1 a^{(k)}_1 & \delta^{(k+1)}_1 a^{(k)}_2 &\cdots \\
\delta^{(k+1)}_2 a^{(k)}_1 & \delta^{(k+1)}_2 a^{(k)}_2 &\cdots \\
\vdots & \vdots & \ddots
\end{bmatrix}
= \delta^{(k+1)} a^{(k)T}
\end{align*}

下面咱們來看如何計算偏差向量$\delta^{(k)}$。在圖5中咱們已經知道,$\delta^{(k)}_j = f'(z^{(k)}_j) \sum_i \delta^{(k+1)}_i W^{(k)}_{ij}$,這能夠通常化爲以下的矩陣形式:

\begin{align*}
\delta^{(k)} = f'(z^{(k)}) \circ (W^{(k)T}\delta^{(k+1)}_i)
\end{align*}

其中,$\circ$運算符是指矩陣點乘($\mathbb{R}^N \circ \mathbb{R}^N \rightarrow \mathbb{R}^N$)。

計算效率:咱們探索了基於元素的更新和基於矩陣的更新。咱們必須意識到,向量化的實如今科學運算環境裏效率更高,好比MATLAB和Python的NumPy/SciPy包。所以,咱們應該使用向量化的實現。更進一步,在反向傳播時應該避免重複計算。好比,$\delta^{(k)}$直接依賴於$\delta^{(k+1)}$。咱們應該確保,在使用$\delta^{(k+1)}$更新完$W^{(k)}$以後,不能丟棄,而是要保存訓練,用於後面計算$\delta^{(k)}$。重複這一過程$(k-1) \cdots (1)$。最終獲得了一個計算上還負擔得起的遞歸過程。

 

 

本文翻譯自CS224n課程的官方筆記3,對應該課程的第四、5節。筆記的後半部分還介紹了神經網絡的一些實踐經驗以及技巧,這與先前的博客訓練深度神經網絡存在較大重疊,因此並無寫在這裏。

相關文章
相關標籤/搜索