【機器學習】動手寫一個全連線神經網路(一)

artzers發表於2016-12-21

  反向傳播神經網路推導中給出了複雜的BP公式。從頭看這篇多年的部落格的公式,我都有點被繞暈了。現在在這裡我可以從矩陣計算的角度去演示一個全連線神經網路的計算過程,這樣更簡潔明瞭。
人工神經網路
  如上圖,是一個簡單的分類全連線神經網路,每一根線表示權重相乘。如果沒看透這個計算關係,那麼我們很容易這樣設計程式:每一個節點都製作一個class類,每個類節點要與其他類節點有連線關係,要傳遞資料,要計算梯度誤差。這樣做出來的神經網路靈活性很強,但是真的是太複雜了!不靠譜!
  假設我們只研究兩層資料之間的關係,每根線代表一個權重乘法。設權重為w1ij

w_{ij}^1
,前一層資料是x1i
x_i^1
,後一層資料為x2j
x_j^2
,那麼後一層每一個資料就是x2i=ix1iw1ij+b1i
x_i^2=\sum_i {x_i^1w_{ij}^1}+b_i^1
。為了形象表示資料從左向右傳遞的過程,我寫成
  

[x11x12...]w11jw12j...+b11
\begin{bmatrix} x_{1}^1 & x_{2}^1 & ... \end{bmatrix}\begin{bmatrix} w_{1j}^1 \\ w_{2j}^1 \\ ...\end{bmatrix}+b_1^1

  如果我們擴充套件計算整個全連線層,就可以得到簡單的矩陣計算:
[x11x12...]w111w121...w112w122......+[b11b12...]=[x21x22...]X1W1+B1=X2
\begin{bmatrix} x_{1}^1 & x_{2}^1 & ... \end{bmatrix}\begin{bmatrix} w_{11}^1 &w_{12}^1 & ... \\ w_{21}^1 &w_{22}^1 & ... \\ ... \end{bmatrix}+\begin{bmatrix} b_{1}^1 & b_{2}^1 &... \end{bmatrix} = \begin{bmatrix} x_{1}^2 & x_{2}^2 & ... \end{bmatrix} \\ \rightarrow X^1W^1+B^1=X^2

  所以,一個全連線層,實際上就是一個矩陣乘法和一個矩陣加法,資料都是向量,權重引數可以用矩陣表示,計算過程能夠編碼為一個layer類,即一個神經網路層。相應的,啟用層其實就是對資料向量,逐個元素進行計算,即
Activation(X2)=[f(x21)f(x22)...]
Activation(X^2)=\begin{bmatrix} f(x_{1}^2) & f(x_{2}^2) & ... \end{bmatrix}
這兩種操作都可以向量化,在GPU中跑的飛快;CPU使用MKL和BLAS庫也可以大大加速計算。
  下面關鍵就是如何計算梯度來修正權重,梯度下降法的定義是θnew=θoldFθ
\theta_{new}=\theta_{old}-\frac{\partial{F}}{\partial \theta}
。矩陣求導的公式(注意上標2並不是平方,是序號)是:
X2W1=(X1)TEB1=I
\frac{\partial X^2}{\partial W^1}=(X^1)^T \\ \frac{\partial E}{\partial B^1}=I
設損失函式為E。
  
  好了,假設我隨便做一個神經網路,包含一層全連線層
fc1:Xfc1=XinputWfc1+Bfc1
fc1:X_{fc1}=X_{input}W_{fc1}+B_{fc1}
,一層sigmoid啟用層
sig:Xsig=sigmoid(Xfc1)
sig: X_{sig}=sigmoid(X_{fc1})
,一層全連線層,最後只輸出一個結果
fc2:y=Xfc2=XsigWfc2+Bfc2
fc2:y=X_{fc2}=X_{sig}W_{fc2}+B_{fc2}
,損失函式是Euclidean損失函式E=12(yiyi)2
E=\frac{1}{2}\sum (y_i'-y_i)^2
,求和是因為我們可能一次性計算一個批次的資料,即一個batch,把多次計算的誤差全部加起來。
  輸出層誤差梯度為:δ4=EXfc2=(yiyi)
\delta_4=\frac{\partial E}{\partial X_{fc2}}=\sum(y_i'-y_i)

  fc2層要計算W、B的梯度,和一個向上傳遞的梯度:
δ3=EWfc2=EXfc2Xfc2Wfc2=XTsig(yiyi)=XTsigδ4EBfc2=(yiyi)=δ4δup3=δ4WTfc2
\delta_3= \frac{\partial E}{\partial W_{fc2}}=\frac{\partial E}{\partial X_{fc2}}\frac{\partial X_{fc2}}{\partial W_{fc2}}=X_{sig}^T\sum (y_i'-y_i)=X_{sig}^T\delta_4\\ \frac{\partial E}{\partial B_{fc2}}=\sum(y_i'-y_i)=\delta_4 \\ \delta_3^{up}=\delta_4W_{fc2}^T

  sig層不包含W、B,只上傳梯度:
δup2=XsigXfc1δup3=Xsig.(1Xsig).δup3
\delta_2^{up}=\frac{\partial X_{sig}}{\partial X_{fc1}}\delta_3^{up} = X_{sig}.*(1-X_{sig}).*\delta_3^{up}
.*是元素相乘。這只是一個過渡層。
  fc1層函式梯度:
δ1=EWfc1=EXfc2Xfc2XsigXsigXfc1Xfc1Wfc1=XTinputδup2EBfc1=EXfc2Xfc2XsigXsigXfc1Xfc1Bfc1=δup2
\delta_1=\frac{\partial E}{\partial W_{fc1}} = \frac{\partial E}{\partial X_{fc2}}\frac{\partial X_{fc2}}{\partial X_{sig}}\frac{\partial X_{sig}}{\partial X_{fc1}}\frac{\partial X_{fc1}}{\partial W_{fc1}}=X_{input}^T \delta_2^{up} \\ \frac{\partial E}{\partial B_{fc1}}=\frac{\partial E}{\partial X_{fc2}}\frac{\partial X_{fc2}}{\partial X_{sig}}\frac{\partial X_{sig}}{\partial X_{fc1}}\frac{\partial X_{fc1}}{\partial B_{fc1}}=\delta_2^{up}

  
  歸納總結一下:
* 設當前層序號為n,輸入資料為Xn
X_n
,下一層向上傳遞的梯度為δupn+1
\delta_{n+1}^{up}
,則當前層W更新梯度為XTnδupn+1
X_n^T\delta_{n+1}^{up}
,B更新梯度為δupn+1
\delta_{n+1}^{up}
,向上傳遞的梯度為δupn+1WTn
\delta_{n+1}^{up}W_n^T

* 如果當前層不包含W,B,例如啟用層,則上傳向上傳遞梯度即可
* 輸出層的梯度由損失函式定義。

相關文章