前面總結了利用單神經元和Logistic迴歸解決簡單的二分類問題,接下來就是建立一個簡單的BP神經網絡模型了,也就是簡單的輸入層-隱藏層-輸出層網絡模型,相比起之前的模型僅僅多了一個隱藏層。
先給出直觀的網絡示意圖(注:圖來源於吳恩達老師深度學習課程JupterNotebok):
模型解釋
輸入層 x=[x1,x2,...,xn]T 對應樣本的 n 個特徵。輸入層到隱層的權重矩陣用 W[1] 表示,隱層的輸入用 z[1] 表示,隱層的輸出用 a[1] 表示。隱層到輸出層的權重矩陣用 W[2] 表示,輸出層的輸入用 z[2] 表示,網絡的輸出用 a[2] 表示。
從上圖可以看出,對於一個二分類網絡來說,輸出層只需要一個神經元,用來輸出一個位於 [0,1] 區間的概率值。這樣對於一個輸入樣本 x ,一個網絡的正向傳播機制可以用數學公式描述爲
z[1]=W[1]x+b[1](1)a[1]=tanh(z[1])(2)z[2]=W[2]a[1]+b[2](3)y^=a[2]=sigmoid(z[2])(4)其中 W[1]⊆Rnh×nx , W[2]⊆Rny×nh,nx、nh、ny 分別爲輸入層、隱層和輸出層節點數量,b[1] 和 b[2] 分別表示隱層和輸出層(更確切地應該說輸出神經元)的閾值,從式子裏可以看出隱層用了 tanh 作爲激活函數,輸出層毫無疑問還是 sigmoid 函數。
這樣輸入樣本 x 的預測值即爲
yprediction={1,0,a[2]>0.5otherwise (5)
多個輸入樣本的向量化實現
上面用單個模型解釋了一個單隱層神經網絡的正向傳播機制,實際中對於一個包含很多訓練樣本的數據集,如果通過遍歷的方式一個一個樣本輸入神經網絡進行運算是很耗時的,這時候可以嘗試使用Python強大的 numpy 庫進行向量化編程,numpy庫中定義了各種矩陣和向量運算的函數,可以有效地提高效率。(實質上式 (1) 和 (3) 就是向量化的實現。)
對於一個包含 m 樣本的數據集,我們可以將其表示爲
X=[x(1),x(2),...,x(m)](6)其中 x(i)=[x1(i),x2(i),...,xn(i)]T 爲第 i 個樣本的特徵向量,將式 (6) 展開爲矩陣形式即爲
X=⎣⎢⎢⎢⎢⎡x1(1)x2(1)⋮xn(1)x1(2)x2(2)⋮xn(2)⋯⋯⋱⋯x1(m)x2(m)⋮xn(m)⎦⎥⎥⎥⎥⎤顯然 X⊆Rn×m,n爲樣本特徵數量,同樣也是網絡輸入層節點數量,因此 n=nx。
這樣就可以通過向量化編程同時將所有樣本輸入到網絡,此時式(1)-(4)就可以向量化表示爲以下形式:
Z[1]=W[1]X+b[1](7)A[1]=tanh(Z[1])(8)Z[2]=W[2]A[1]+b[2](9)Y^=A[2]=sigmoid(Z[2])(10)
對應輸出了 m個樣本的預測值 Y^=[y^(1),y^(2),...,y^(m)]。
損失函數仍舊使用交叉熵函數,向量化表示爲:
J=−m1(Ylog(Y^T)+(1−Y)log(1−Y^)T)(11)
反向傳播的過程主要就是逐層對誤差函數求偏導,過程和單神經元Logistic分類器類似,首先對輸出層求導,接下來對隱層求導。每一步的求導結果如下:
dZ[2]=A[2]−Y(12) dW[2]=m1dZ[2]A[1]T(13)
db[2]=m1∑dZ[2](14)
dZ[1]=W[2]TdZ[2]∗g′(Z[1])(15) dW[1]=m1dZ[1]XT(16)
db[1]=m1∑dZ[1](17)
式 (15) 中 g′(⋅) 表示隱層激活函數(即 tanh )的導函數,在激活函數總結中已經提到 tanh 函數的導函數性質:
g′(z)=1−g2(z)(18)這樣就可以很容易得到
dZ[1]=W[2]TdZ[2]∗g′(Z[1])=W[2]TdZ[2]∗(1−(A[1])2)(19)
到這裏基本已經完成了大部分的計算任務,最後就是利用計算得到的梯度信息更新網絡的參數,即兩個權重矩陣和兩個閾值向量:
dW[1]=W[1]−αdW[1](20)
db[1]=b[1]−αdb[1](21)
dW[2]=W[2]−αdW[2](22)
db[2]=b[2]−αdb[2](23)
這樣在迭代次數內不斷重複上面的更新過程從而不斷降低損失函數的值,最終就可以得到一個較好的二分類神經網絡模型。
總結
包含單隱層的神經網絡只是一個很簡單很基礎的模型,實現過程中發現當隱層節點數爲5的時候,最後的在測試集上的準確率甚至不如單神經元Logistic分類器;增加網絡節點數會提高性能,但是計算量也明顯上升。