最近一個月項目好忙,終於擠出時間把這篇 BP 算法基本思想寫完了,公式的推導放到下一篇講吧。python
神經網絡能夠看作是複雜邏輯迴歸的組合,所以與其相似,咱們訓練神經網絡也要定義代價函數,以後再使用梯度降低法來最小化代價函數,以此來訓練最優的權重矩陣。git
咱們從經典的邏輯迴歸代價函數引出,先來複習下:面試
邏輯迴歸代價函數計算每一個樣本的輸入與輸出的偏差,而後累加起來除以樣本數,再加上正則化項,這個我以前的博客已經寫過了:算法
這裏補充一點對單變量邏輯迴歸代價函數的理解,雖然這一行代價公式很長:編程
可是其實能夠把它簡單的理解爲輸出與輸入的方差,雖然形式上差異很大,可是能夠幫助咱們理解上面這個公式到底在計算什麼,就是計算輸出與輸入的方差,這樣理解就能夠:網絡
前面講的簡單邏輯迴歸的只有一個輸出變量,可是在神經網絡中輸出層能夠有多個神經元,因此能夠有不少種的輸出,好比 K 分類問題,神經元的輸出是一個 K 維的向量:機器學習
所以咱們須要對每一個維度計算預測輸出與真實標籤值的偏差,即對 K 個維度的偏差作一次求和:函數
而後累加訓練集的 m 個樣本:post
再加上全部權重矩陣元素的正則化項,注意 \(i, j\) 都是從 1 開始的,由於每一層的 \(\theta_0\) 是偏置單元,不須要對其進行正則化:學習
這就獲得了輸出層爲 K 個單元神經網絡最終的代價函數:
有了代價函數後,就能夠經過反向傳播算法來訓練一個神經網絡啦!
以前寫神經網絡基礎的時候,跟你們分享瞭如何用訓練好的神經網絡來預測手寫字符:從 0 開始機器學習 - 神經網絡識別手寫字符!,只不過當時咱們沒有訓練網絡,而是使用已經訓練好的神經網絡的權重矩陣來進行前饋預測,那麼咱們如何本身訓練神經網絡呢?
這就須要學習反向 BP 算法,這個算法能夠幫助咱們求出神經網絡權重矩陣中每一個元素的偏導數,進而利用梯度降低法來最小化上面的代價函數,你能夠聯想簡單的線性迴歸算法:從 0 開始機器學習 - 一文入門多維特徵梯度降低法!,也是先求每一個參數的偏導數,而後在梯度降低算法中使用求出的偏導數來迭代降低。
所以訓練神經網絡的關鍵就是:如何求出每一個權重係數的偏導數?,反向 BP 就能夠解決這個問題!這裏強烈建議你學習的時候徹底搞懂 BP 算法的原理,最好本身獨立推導一遍公式,由於你之後學習深度學習那些複雜的網絡,不論是哪一種,最終都要使用反向 BP 來訓練,這個 BP 算法是最核心的東西,面試也逃不過的,因此既然要學,就要學懂,否則就是在浪費時間。
我先用個例子簡單介紹下 BP 算法的基本原理和步驟,公式的推導放到下一節,反向 BP 算法顧名思義,與前饋預測方向相反:
如下面這個 4 層的神經網絡爲例:
假如咱們的訓練集只有 1 個樣本 \((x^{(1)}, y^{(1)})\),每層全部激活單元的輸出用 \(a^{(i)}\) 向量表示,每層全部激活單元的偏差用 \(\delta^{(i)}\) 向量表示,來看下反向傳播的計算步驟(公式的原理下一節講):
有了每層全部激活單元的偏差後,就能夠計算代價函數對每一個權重參數的偏導數,即每一個激活單元的輸出乘以對應的偏差,這裏不考慮正則化:
解釋下這個偏導數的計算:
這個計算過程是對一個樣本進行的,網絡的輸入是一個特徵向量,因此每層計算的偏差也是向量,可是咱們的網絡輸入是特徵矩陣的話,就不能用一個個向量來表示偏差了,而是應該也將偏差向量組成偏差矩陣,由於特徵矩陣就是多個樣本,每一個樣本都作一個反向傳播,就會計算偏差,因此咱們每次都把一個樣本計算的偏差累加到偏差矩陣中:
而後,咱們須要除以樣本總數 \(m\),由於上面的偏差是累加了全部 \(m\) 個訓練樣本獲得的,而且咱們還須要考慮加上正則化防止過擬合,注意對偏置單元不須要正則化,這點已經提過好屢次了:
最後計算的全部偏導數就放在偏差矩陣中:
這樣咱們就求出了每一個權重參數的偏導數,再回想以前的梯度降低法,咱們有了偏導數計算方法後,直接送到梯度降低法中進行迭代就能夠最小化代價函數了,好比我在 Python 中把上面的邏輯寫成一個正則化梯度計算的函數 regularized_gradient
,而後再用 scipy.optimize
等優化庫直接最小化文章開頭提出的神經網絡代價函數,以此來使用反向 BP 算法訓練一個神經網絡:
import scipy.optimize as opt res = opt.minimize(fun = 神經網絡代價函數, x0 = init_theta, args = (X, y, 1), method = 'TNC', jac = regularized_gradient, options = {'maxiter': 400})
因此神經網絡反向 BP 算法關鍵就是理解每一個權重參數偏導數的計算步驟和方法!關於偏導數計算公式的詳細推導過程,我打算在下一篇文章中單獨分享,本次就不帶你們一步步推導了,不然內容太多,先把基本步驟搞清楚,後面推導公式就容易理解。
以前學習前饋預測時,咱們知道一個激活單元是輸入是上一層全部激活單元的輸出與權重的加權和(包含偏置),計算方向從左到右,計算的是每一個激活單元的輸出,看圖:
其實反向 BP 算法也是作相似的計算,一個激活單元偏差的輸入是後一層全部偏差與權重的加權和(可能不包含偏置),只不過這裏計算的反向是從右向左,計算的是每一個激活單元的偏差,對比看圖:
你只須要把單個神經元的前饋預測和反向 BP 的計算步驟搞清楚就能夠基本理解反向 BP 的基本過程,由於全部的參數都是這樣作的。
每種優化算法都須要初始化參數,以前的線性迴歸初始化參數爲 0 是沒問題的,可是若是把神經網絡的初始參數都設置爲 0,就會有問題,由於第二層的輸入是要用到權重與激活單元輸出的乘積:
因此爲了在神經網絡中避免以上的問題,咱們採用隨機初始化,把全部的參數初始化爲 \([-\epsilon, \epsilon]\) 之間的隨機值,好比初始化一個 10 X 11 的權重參數矩陣:
注意上面優化庫的輸入 X0 = init_theta
是一個向量,而咱們的神經網絡每 2 層之間就有一個權重矩陣,因此爲了把權重矩陣做爲優化庫的輸入,咱們必需要把全部的權重參數都組合到一個向量中,也就是實現一個把矩陣組合到向量的功能,可是優化庫的輸出也是一個包含全部權重參數的向量,咱們拿到向量後還須要把它轉換爲每 2 層之間的權重矩陣,這樣才能進行前饋預測:
梯度校驗是用來檢驗咱們的 BP 算法計算的偏導數是否和真實的偏導數存在較大偏差,計算如下 2 個偏導數向量的偏差:
對於單個參數,在一點 \(\theta\) 處的導數可由 \([\theta - \epsilon, \theta + \epsilon]\) 表示,這也是導數定義的一種:
如圖:
可是咱們的神經網絡代價函數有不少參數,當咱們把參數矩陣轉爲向量後,能夠對向量裏的每一個參數進行梯度檢驗,只須要分別用定義求偏導數便可,好比檢驗 \(\theta_1\):
以此類推,檢驗 \(\theta_n\):
求出導數定義的偏導數後,與 BP 算法計算的偏導數計算偏差,在偏差範圍內認爲 BP 算法計算的偏導數(D_vec)是正確的,梯度檢驗的僞代碼以下:
for i = 1 : n theta_plus = theta theta_plus[i] = theta_plus + epsilon theta_minu = theta theta_minu[i] = theta_minu - epsilon grad = (J(theta_plus) - J(theta_minu)) / (2 * epsilon) end check 偏差: grad 是否約等於 D_vec
注意一點:梯度檢驗一般速度很慢,在訓練神經網絡前先別進行檢驗!
今天就到這,溜了溜了,下篇文章見:)