神經網絡和BP算法推導

個人原文:www.hijerry.cn/p/53364.htm…html

感知機

感知機(perceptron)於1957年由Rosenblatt提出,是一種二分類線性模型。感知機以樣本特徵向量做爲輸入,輸出爲預測類別,取正、負兩類。感知機最終學習到的是將輸入空間(特徵空間)劃分爲正、負兩類的分離超平面,屬於判別模型。爲此,使用誤分類做爲損失函數,利用梯度降低優化該函數,可求得感知機模型。感知機是神經網絡與支持向量機的基礎。git

單層感知機

單層感知機圖片

{i} 個樣本的預測值 \hat{y_i} = f(\vec{w} \cdot \vec{x_i} + b) ,其中 f(\cdot) 稱爲激活函數,f(\cdot) \in \{-1, 1\} ,損失爲 L_i=\frac{1}{2}(\hat{y_i}-y_i)^2 。單層感知機的目的就是習得合適的 \vec{w}b ,使得全部樣本的損失之和 \sum_{x_i \in X} L_i 最小。github

若是咱們令 z =  \vec{w} \cdot \vec{x_i} + b 即感知機的輸入。那麼當 z < 0 時,f(z) = -1;當z > 0 時,f(z)=1 。由於 zx 線性組合,因此最終獲得的是一個超平面 \vec{w} \cdot \vec{x}+b=0 ,超平面將輸入樣本分爲了 y_i=1y_i= -1兩類。算法

當輸入 x=(x_1, x_2) 是二維向量時,用紅點表示 +1 的數據,黑點表示 -1 的數據,最終習得的是一條直線,將兩個數據分離開,以下圖所示。bash

決策超平面

由於單層感知機最終習得是超平面,因此只能用於解決線性可分問題。對於下面這樣的數據,單層感知機無能爲力。網絡

非線性可分

多層感知機

多層感知機也叫MLP,能夠看作是一個有向圖。MLP由多層節點組成,每一層全鏈接到下一層,除輸入節點外,每一個節點都是一個帶有非線性激活函數的神經元(unit)。多層感知機可用於解決線性不可分問題。機器學習

由於神經網絡的和多層感知器是一個意思,因此下面直接對單層前饋神經網絡進行詳細說明。函數

決策線

單層前饋神經網絡

下圖是一個輸入層節點數爲3,隱藏層節點數爲2,輸出層節點數爲2的前饋神經網絡,該網絡可用於解決二分類問題。學習

3×2×2前饋神經網絡結構圖

單層前饋神經網絡本質上是一個多層感知機,有如下幾個特色:優化

  1. 全鏈接。每一層的節點都與右邊層的全部節點經過權重鏈接。
  2. 隱藏層只有一層。因此稱之爲單層
  3. 數據單向流動。每一層節點只做用於其以後的層,因此叫做前饋
  4. 本質是數學函數。神經網絡能夠明確的用數學語言表達。

神經元

咱們拿出隱藏層的一個神經元(unit)放大來看:

單節點詳解

神經元的任務就是接受輸入,產生輸出

z 表示神經元的輸入,a 是神經元的輸出。

輸入怎麼得來?就是上一層的神經元輸出與權重 的乘積之和再加上偏置

輸出怎麼得來?把輸入值帶入激活函數 獲得。

寫成數學表達式就是:

z^{(2)}_1 = w^{(1)}_{11}a^{(1)}_1+w^{(1)}_{21}a^{(1)}_2+w^{(1)}_{31}a^{(1)}_3+b^{(1)}_1

a^{(2)}_1=f(z^{(2)}_1)

f(\cdot) 是激活函數,常見的有sigmoid、tanh、ReLU。

Sigmoid函數

Sigmoid的表達式爲 S(x)=\frac{1}{1+e^{-x}},定義域爲 R ,值域爲 (0, 1)

x=0 處,函數值爲 \frac{1}{2},其函數圖像以下:

sigmoid函數圖像

sigmoid函數有許多優美的性質,如:

  1. e^x 的複合函數,e 又名天然常數

  2. 1階導函數S'(x)=S(x)(1-S(x)) 。即函數在某一點的導數可由函數在這一點的函數值求得

  3. 曲線光滑,定義域內到處可導,且能夠無限次求導

  4. 能夠把任意輸入壓縮到 (0, 1) 範圍內

在反向傳播算法(BP算法)中,性質二、3起到了極大的做用,性質4起到了防溢出的做用。

前向傳播原理

現考慮一個樣本(x, y) ,其中 x \in R^3 是輸入數據,y \in \{[0,1],[1,0]\}是實際值。咱們如今來手動計算 x 預測值 \hat{y}。預測值 \hat{y} 的計算過程是從輸入層開始從左往右計算的,因此這個過程也叫做前向傳播。

下圖表示,爲了獲得 a^{(3)}_1 ,有哪些神經元被激活了。

前向傳播

爲了方便表述,用 w^{(l)}_{ij} 表示第l 層的第 i 個神經元與第 l+1 層的第 j 個神經元相連的權重,用 b^{(l)}_j 表示第l+1 層第 j 個神經元的偏置值。

輸入層

注意。輸入層沒有激活函數,因此:

[a^{(1)}_1, a^{(1)}_2,a^{(1)}_3]=x

隱藏層

z^{(2)}_1 = w^{(1)}_{11}a^{(1)}_1+w^{(1)}_{21}a^{(1)}_2+w^{(1)}_{31}a^{(1)}_3+b^{(1)}_1

z^{(2)}_2 = w^{(1)}_{12}a^{(1)}_1+w^{(1)}_{22}a^{(1)}_2+w^{(1)}_{32}a^{(1)}_3+b^{(1)}_2

a^{(2)}_1=sigmoid(z^{(2)}_1)

a^{(2)}_2=sigmoid(z^{(2)}_2)

輸出層

若是咱們把 a^{(3)}_1 做爲類別爲 0 的機率,將 a^{(3)}_2 做爲類別爲1的機率,則樣本 x_i 的預測值能夠寫成 \hat{y_i}=\max \{a^{(3)}_1, a^{(3)}_2\} ,因此爲了讓 a^{(3)}_1 + a^{(3)}_2 = 1 ,選用 softmax 做爲輸出層的激活函數。

z^{(3)}_1=w^{(2)}_{11}a^{(2)}_1+w^{(2)}_{21}a^{(2)}_2+b^{(2)}_1

z^{(3)}_2=w^{(2)}_{12}a^{(2)}_1+w^{(2)}_{22}a^{(2)}_2+b^{(2)}_2

g(z^{(k)})=\sum exp({z^{(k)}_i})exp(x)=e^x

a^{(3)}_1=softmax(z^{(3)}_1,z^{(3)})=\frac{exp({z^{(3)}_1)}}{g(z^{(3)})}

a^{(3)}_2=softmax(z^{(3)}_2,z^{(3)})=\frac{exp({z^{(3)}_2})}{g(z^{(3)})}

咱們令 \hat{y}_1=a^{(3)}_1\hat{y}_2=a^{(3)}_2,那麼 \hat{y}=[\hat{y}_1, \hat{y}_2],同理設 y=[y_1, y_2]

神經網絡能夠明確的用數學語言表達,它的函數表達式,能夠明確的寫出來
複製代碼

若是真的將這個數學表達式寫出來,那麼這個數學函數 network(\cdot) 是一個包含 (3+1) \times 2 + (2+1) \times 2=14 個參數的函數,函數輸入 x 可獲得預測值 \hat{y} ,這個表達式會很是長。

反向傳播原理

咱們如今來優化網絡中這10個權重參數和4個偏置參數。

定義輸出層的節點 i 的偏差,可用的損失函數有:

  1. 均方偏差:E = \sum_{j=1}^2\frac{1}{2} (\hat{y}_j-y_j)^2
  2. 交叉熵損失: CE=CE(\hat{y},y)=-\sum_{j=1}^{2}y_{j}ln\hat{y}_j

使用梯度降低算法來優化損失函數,則須要求出損失函數對全部參數的導數,這個過程在計算上是從輸出層開始從右往左計算的,由於與計算預測值 \hat{y_i} 的過程恰巧相反,因此也叫做反向傳播。

權重的導數

以計算權重 w^{(2)}_{21} 的偏導數爲例,根據鏈式法則不可貴到:

\frac{\partial CE}{\partial w^{(2)}_{21}} = \frac{\partial CE}{\partial \hat{y_1}} \frac{\partial  \hat{y}_1}{\partial z^{(3)}_1} \frac{\partial z^{(3)}_1}{\partial w^{(2)}_{21}}

CE=-\sum_{j=1}^{2}y_jln\hat{y}_j=-(y_1ln\hat{y}_1+y_2ln\hat{y}_2) ,又 y_1+y_2=1\hat{y}_1+\hat{y}_2=1

CE =-(y_1ln\hat{y}_1+(1-y_1)ln(1-\hat{y}_1)) (注:這是二分類問題特有的交叉熵表示方式)

\frac{\partial CE}{\partial  \hat{y}_1}=-(\frac{y_1}{\hat{y}_1} - \frac{1-y_1}{1-\hat{y_1}})=\frac{\hat{y}_1-y_1}{\hat{y}_1(1-\hat{y}_1)}

\frac{\partial  \hat{y}_1}{\partial z^{(3)}_1}=\frac{exp(z^{(3)}_1)exp(z^{(3)}_2)}{(exp(z^{(3)}_1)+exp(z^{(3)}_2))^2}=\hat{y}_1\hat{y}_2=\hat{y_1}(1-\hat{y}_1)

\frac{\partial z^{(3)}_1}{\partial w^{(2)}_{21}}=a^{(2)}_2

故原偏導數可寫成:

\frac{\partial CE}{\partial w^{(2)}_{11}}=\frac{\hat{y}_1-y_1}{\hat{y}_1(1-\hat{y}_1)} \cdot \hat{y_1}(1-\hat{y}_1) \cdot a^{(2)}_1=(\hat{y}_1-y_1) \cdot a^{(2)}_2

更通用化的表達,如何計算 w^{(2)}_{ij} ?依葫蘆畫瓢得:

\frac{\partial CE}{\partial w^{(2)}_{ij}} = \frac{\partial CE}{\partial \hat{y_i}} \frac{\partial  \hat{y}_i}{\partial z^{(3)}_i} \frac{\partial z^{(3)}_i}{\partial w^{(2)}_{ij}}=(\hat{y}_j-y_j) \cdot a^{(2)}_i

\delta^{(3)}_j=\hat{y}_j-y_j 表示輸出層節點 j 的偏差值

則上式可寫成:

\frac{\partial CE}{\partial w^{(2)}_{ij}} =\delta^{(3)}_j \cdot a^{(2)}_i

如何理解?用 i 表示爲隱藏層節點的位置, j 表示爲輸出層節點的位置,那麼權重 w^{(2)}_{ij} 的導數爲該權重前一層第i個節點的激活值與後一層第j個節點的偏差值的乘積

下圖是反向傳播的示意圖,損失函數產生的偏差順着紅線一直往左邊傳,每通過一條紅線就求一次導數,直到要求的權重也覆蓋在紅線爲止。下圖有三條紅線,也就是損失函數 CEw^{(2)}_{21} 的導數須要用三個偏導數乘積造成的鏈式求導才能獲得,且最後一個偏導數值爲 a^{(2)}_i

w221導數

如何計算 w^{(1)}_{ij}​ 呢?繼續使用鏈式法則 + 依葫蘆畫瓢可得:

\frac{\partial CE}{\partial w^{(1)}_{ij}} =\sum_{k=1}^2((\hat{y}_k-y_k)w^{(2)}_{jk}) \cdot a^{(2)}_j(1-a^{(2)}_j) \cdot a^{(1)}_i

\delta^{(2)}_j = \sum_{k=1}^2(\hat{y}_k-y_k)w^{(2)}_{jk} \cdot a^{(2)}_j(1-a^{(2)}_j)a^{(2)}_j偏差值 ,那麼上式能夠寫成:

\frac{\partial CE}{\partial w^{(1)}_{ij}} =\delta^{(2)}_j \cdot a^{(1)}_i

觀察能夠發現:

\delta^{(2)}_j=\sum_{k=1}^2(\delta^{(3)}_jw^{(2)}_{jk}) \cdot a^{(2)}_j(1-a^{(2)}_j)

如何理解?若是用 i 表示輸入層節點位置, j 表示隱藏層節點位置,那麼權重 w^{(1)}_{ij} 的導數爲 該權重前一層第i個節點的激活值與後一層第j個節點的偏差值的乘積每一個節點的偏差值 等於 鏈接權重 與 權重另外一端所連節點的偏差值 的乘積之和 與 本節點激活值的導數 的乘積

詳細的推導過程讀者能夠本身琢磨一下,這裏有個關鍵點須要注意:

  • 由於 y_1+y_2=1​\hat{y}_1+\hat{y}_2=1​ ,因此 CE =-(y_2ln\hat{y}_2+(1-y_2)ln(1-\hat{y}_2))​

偏置的導數

如何求 b^{(2)}_j 的導數?根據以前的邏輯推導便可:

\frac{\partial CE}{\partial b^{(2)}_j} = \frac{\partial CE}{\partial \hat{y_i}} \frac{\partial  \hat{y}_i}{\partial z^{(3)}_i} \frac{\partial z^{(3)}_i}{\partial b^{(2)}_j}=(\hat{y}_j-y_j) \cdot 1

如何求 b^{(1)}_j 的導數?鏈條太長,這裏直接給出答案:

\frac{\partial CE}{\partial b^{(1)}_j}=\sum_{k=1}^2((\hat{y}_k-y_k)w^{(2)}_{jk}) \cdot a^{(2)}_j(1-a^{(2)}_j) \cdot 1

與權重導數不一樣的地方就是,在求導過程當中的最後一項 \frac{\partial z^{(l + 1)}_i}{\partial b^{(l)}_j} =1

若是加入偏置單元,也能夠理解爲偏置單元 a^{(l)}_0 的值爲1,以下圖所示:

加入偏置單元

正則化項

正則化(regularation)是防止機器學習過擬合的一種手段。一種常見的手段是經過將權重的平方之和加入到損失函數來實現。那麼損失函數變爲:

CE=-\sum_{j=1}^{2}y_jln\hat{y}_j+\frac{\lambda}{2}\sum_l\sum_i\sum_j(w^{(l)}_{ij})^2

全部權重、偏置之和稱爲 正則項\lambda正則項係數,也叫 懲罰係數

加入正則化項後,w 的導數要多算一個平方項的導數,以 w^{(2)}_{ij} 爲例

grad(w^{(2)}_{ij})=(\hat{y}_j-y_j) \cdot a^{(2)}_i+\lambda w^{(2)}_{ij}

向量化

咱們假設輸入值 x 、 實際值 y 都是列向量。

觀察 z^{(2)}_1z^{(2)}_2 的表達式,進而發現能夠用矩陣形式書寫爲:

\left[\begin{matrix} w^{(1)}_{11} & w^{(1)}_{12} \\ w^{(1)}_{21} & w^{(1)}_{22} \\ w^{(1)}_{31} & w^{(1)}_{32} \end{matrix} \right]^T \left[ \begin{matrix} a^{(1)}_1  \\ a^{(1)}_2 \\ a^{(1)}_3 \end{matrix} \right] + \left[\begin{matrix} b^{(1)}_1 \\ b^{(1)}_2 \end{matrix} \right]= \left[\begin{matrix} z^{(2)}_1 \\ z^{(2)}_2 \end{matrix} \right]

不失通常性,設第 l 層的前向傳播:z^{(l+1)}=(w^{(l)})^Ta^{(l)}+b^{(l)},其中 a^{(l)}z^{(l+1)}b^{(l)} 均爲列向量, W^{(l)} 爲矩陣

激活值 a^{(l)}=sigmoid(z^{(l)}),因此激活值也是列向量。

損失函數向量化爲:

CE=-\left[\begin{matrix} y_1 \\ y_2 \end{matrix} \right]^T  ln\left[\begin{matrix} \hat{y}_1 \\ \hat{y}_2 \end{matrix} \right] + \lambda(\sum_l\sum_i\sum_jw^{(l)}_{ij}+\sum_l\sum_ib^{(l)}_i)

=-y^Tln\hat{y}+\frac{\lambda}{2}\sum_{l=1}^2 sum(w^{(l)}*w^{(l)})

sum(\cdot) 表示把矩陣 \cdot 的全部元素之和

* 表示求哈達馬積,即兩個矩陣對應位置的元素的乘積所造成的一個新矩陣

輸出層偏差值向量化:

\delta^{(3)}= \left[\begin{matrix} \delta^{(3)}_1 \\ \delta^{(3)}_2 \end{matrix} \right]=\left[\begin{matrix} \hat{y}_1-y_1 \\ \hat{y}_2-y_2\end{matrix} \right] =\hat{y}-y

隱藏層偏差向量化:

\delta^{(2)}= \left[\begin{matrix} (\hat{y}_1-y_1)w^{(2)}_{11}+ (\hat{y}_2-y_2)w^{(2)}_{12} \\ (\hat{y}_1-y_1)w^{(2)}_{21}+ (\hat{y}_2-y_2)w^{(2)}_{22} \end{matrix} \right] * a^{(2)}_j(1-a^{(2)}_j)

=\left[\begin{matrix} w^{(2)}_{11} & w^{(2)}_{12} \\ w^{(2)}_{21} & w^{(2)}_{22} \end{matrix} \right] \left[\begin{matrix} \hat{y}_1-y_1 \\ \hat{y}_2-y_2\end{matrix} \right] * a^{(2)}_j(1-a^{(2)}_j)

=w^{(2)}(\hat{y}-y) * a^{(2)}_j(1-a^{(2)}_j)

參數 w^{(2)} 導數向量化:

grad(w^{(2)})= grad(\left[\begin{matrix} w^{(2)}_{11} & w^{(2)}_{12} \\ w^{(2)}_{21} & w^{(2)}_{22} \end{matrix} \right]) = \left[\begin{matrix} \delta^{(3)}_1a^{(2)}_1 & \delta^{(3)}_2a^{(2)}_1 \\ \delta^{(3)}_1a^{(2)}_2 & \delta^{(3)}_2a^{(2)}_2 \end{matrix} \right]

=\left[\begin{matrix} a^{(2)}_1 \\ a^{(2)}_2 \end{matrix} \right] \left[\begin{matrix} \delta^{(3)}_1 \\ \delta^{(3)}_2 \end{matrix} \right]^T =a^{(2)}(\delta^{(3)})^T

不失通常性,有:grad(w^{(l)})=a^{(l)}(\delta^{(l+1)})^T

小批量梯度降低

上述全部過程都是假設只有一個樣本。

當參與計算的樣本數量大於1時:

  • 單個損失函數 => 全部樣本損失值求平均
  • 單個樣本的輸出層偏差 => 全部樣本輸出層偏差求平均

你不用寫一個for循環來計算上述值,使用矩陣乘法會更爲方便,這裏留給讀者思考。

實現

github:github.com/JerryCheese…

ann.py 是面向過程版本實現,且隱藏層數只能爲1。

NN.py 是面向對象版本實現,支持多層隱藏層。

相關文章
相關標籤/搜索