神經網路和BP演算法推導
我的原文:www.hijerry.cn/p/53364.htm…
感知機
感知機(perceptron)於1957年由Rosenblatt提出,是一種二分類線性模型。感知機以樣本特徵向量作為輸入,輸出為預測類別,取正、負兩類。感知機最終學習到的是將輸入空間(特徵空間)劃分為正、負兩類的分離超平面,屬於判別模型。為此,使用誤分類作為損失函式,利用梯度下降優化該函式,可求得感知機模型。感知機是神經網路與支援向量機的基礎。
單層感知機
第 個樣本的預測值 ,其中 稱為啟用函式, ,損失為 。單層感知機的目的就是習得合適的 與 ,使得所有樣本的損失之和 最小。
如果我們令
當輸入 是二維向量時,用紅點表示 的資料,黑點表示 的資料,最終習得的是一條直線,將兩個資料分離開,如下圖所示。
因為單層感知機最終習得是超平面,所以只能用於解決線性可分問題。對於下面這樣的資料,單層感知機無能為力。
多層感知機
多層感知機也叫MLP,可以看做是一個有向圖。MLP由多層節點組成,每一層全連線到下一層,除輸入節點外,每個節點都是一個帶有非線性啟用函式的神經元(unit)。多層感知機可用於解決線性不可分問題。
因為神經網路的和多層感知器是一個意思,所以下面直接對單層前饋神經網路進行詳細說明。
單層前饋神經網路
下圖是一個輸入層節點數為3,隱藏層節點數為2,輸出層節點數為2的前饋神經網路,該網路可用於解決二分類問題。
單層前饋神經網路本質上是一個多層感知機,有以下幾個特點:
- 全連線。每一層的節點都與右邊層的所有節點通過
權重
連線。 - 隱藏層只有一層。所以稱之為
單層
- 資料單向流動。每一層節點只作用於其之後的層,所以叫作
前饋
。 - 本質是數學函式。神經網路可以明確的用數學語言表達。
神經元
我們拿出隱藏層的一個神經元(unit)放大來看:
神經元的任務就是接受輸入,產生輸出
。
z
表示神經元的輸入,a
是神經元的輸出。
輸入怎麼得來?就是上一層的神經元輸出與權重
的乘積之和再加上偏置
。
輸出怎麼得來?把輸入值帶入啟用函式
得到。
寫成數學表示式就是:
是啟用函式,常見的有sigmoid、tanh、ReLU。
Sigmoid函式
Sigmoid的表示式為 ,定義域為 ,值域為
在 處,函式值為 ,其函式影象如下:
sigmoid函式有許多優美的性質,如:
-
是 的複合函式, 又名
自然常數
-
1階導函式
為 。即函式在某一點的導數可由函式在這一點的函式值求得 -
曲線光滑,定義域內處處可導,且可以無限次求導
-
可以把任意輸入壓縮到 範圍內
在反向傳播演算法(BP演算法)中,性質2、3起到了極大的作用,性質4起到了防溢位的作用。
前向傳播原理
現考慮一個樣本 ,其中 是輸入資料,是實際值。我們現在來手動計算 預測值 。預測值 的計算過程是從輸入層開始從左往右計算
的,所以這個過程也叫作前向傳播。
下圖表示,為了得到 ,有哪些神經元被激活了。
為了方便表述,用 表示第 層的第 個神經元與第 層的第 個神經元相連的權重,用 表示第 層第 個神經元的偏置值。
輸入層
注意。輸入層沒有啟用函式,所以:
隱藏層
輸出層
如果我們把 作為類別為 的概率,將 作為類別為1的概率,則樣本 的預測值可以寫成 ,所以為了讓 ,選用 作為輸出層的啟用函式。
令 ,
我們令 ,,那麼 ,同理設
神經網路可以明確的用數學語言表達,它的函式表示式,可以明確的寫出來
複製程式碼
如果真的將這個數學表示式寫出來,那麼這個數學函式 是一個包含 個引數的函式,函式輸入 可得到預測值 ,這個表示式會非常長。
反向傳播原理
我們現在來優化網路中這10個權重引數和4個偏置引數。
定義輸出層的節點 的誤差,可用的損失函式有:
- 均方誤差:
- 交叉熵損失:
使用梯度下降演算法來優化損失函式,則需要求出損失函式對所有引數的導數
,這個過程在計算上是從輸出層開始從右往左計算
的,因為與計算預測值 的過程恰巧相反,所以也叫作反向傳播。
權重的導數
以計算權重 的偏導數為例,根據鏈式法則不難得到:
∵ ,又 ,
∴ (注:這是二分類問題特有的交叉熵表示方式)
∴
又
且
故原偏導數可寫成:
更通用化的表達,如何計算 ?依葫蘆畫瓢得:
令 表示輸出層節點 的誤差值
則上式可寫成:
如何理解?用 表示為隱藏層節點的位置, 表示為輸出層節點的位置,那麼權重 的導數為該權重前一層第i個節點的啟用值與後一層第j個節點的誤差值的乘積
。
下圖是反向傳播的示意圖,損失函式產生的誤差順著紅線一直往左邊傳,每經過一條紅線就求一次導數,直到要求的權重也覆蓋在紅線為止。下圖有三條紅線,也就是損失函式 對 的導數需要用三個偏導數乘積形成的鏈式求導才能得到,且最後一個偏導數值為 。
如何計算 呢?繼續使用鏈式法則 + 依葫蘆畫瓢可得:
令 為 的誤差值
,那麼上式可以寫成:
觀察可以發現:
如何理解?如果用 表示輸入層節點位置, 表示隱藏層節點位置,那麼權重 的導數為 該權重前一層第i個節點的啟用值與後一層第j個節點的誤差值的乘積
。每個節點的誤差值 等於 連線權重 與 權重另一端所連節點的誤差值 的乘積之和 與 本節點啟用值的導數 的乘積
。
詳細的推導過程讀者可以自己琢磨一下,這裡有個關鍵點需要注意:
- 因為 , ,所以
偏置的導數
如何求 的導數?根據之前的邏輯推導即可:
如何求 的導數?鏈條太長,這裡直接給出答案:
與權重導數不同的地方就是,在求導過程中的最後一項 。
如果加入偏置單元,也可以理解為偏置單元 的值為1,如下圖所示:
正則化項
正則化(regularation)是防止機器學習過擬合的一種手段。一種常見的手段是通過將權重的平方之和加入到損失函式來實現。那麼損失函式變為:
所有權重、偏置之和稱為 正則項
, 是 正則項係數
,也叫 懲罰係數
。
加入正則化項後, 的導數要多算一個平方項的導數,以 為例
向量化
我們假設輸入值 、 實際值 都是列向量。
觀察 、 的表示式,進而發現可以用矩陣形式書寫為:
不失一般性,設第 層的前向傳播:,其中 、 、 均為列向量, 為矩陣
啟用值 ,所以啟用值也是列向量。
損失函式向量化為:
表示把矩陣 的所有元素之和
*
表示求哈達馬積
,即兩個矩陣對應位置的元素的乘積所形成的一個新矩陣
輸出層誤差值向量化:
隱藏層誤差向量化:
引數 導數向量化:
不失一般性,有:
小批量梯度下降
上述所有過程都是假設只有一個樣本。
當參與計算的樣本數量大於1時:
- 單個損失函式 => 所有樣本損失值求平均
- 單個樣本的輸出層誤差 => 所有樣本輸出層誤差求平均
你不用寫一個for迴圈來計算上述值,使用矩陣乘法會更為方便,這裡留給讀者思考。
實現
github:github.com/JerryCheese…
ann.py
是面向過程版本實現,且隱藏層數只能為1。
NN.py
是面向物件版本實現,支援多層隱藏層。