1. 程式人生 > >神經網路的反向傳播演算法中矩陣的求導方法(矩陣求導總結)

神經網路的反向傳播演算法中矩陣的求導方法(矩陣求導總結)

  前言

神經網路的精髓就是反向傳播演算法,其中涉及到一些矩陣的求導運算,只有掌握了與矩陣相關的求導法則才能真正理解神經網路.

與矩陣有關的求導主要分為兩類:

  • 標量 f 對 矩陣 W的導數 (其結果是和W同緯度的矩陣,也就是f對W逐元素求導排成與W尺寸相同的矩陣)
  • 矩陣 F 對 矩陣 W的導數 (其結果是一個四維的矩陣)

回到博文中提到的神經網路, 這裡f 實際上就是loss(神經網路的損失),每個batch的訓練集所獲得的損失都是一個標量,他是網路引數W和b的函式 (f = LOSS(W,b)),因此想要完成對引數的更新就需要求 L這個標量對W這個矩陣的導數\frac{\partial L}{\partial W},在程式碼中簡記為dW,如下所示,本文的目的就是手動完成dW_1和dW_2以及db_1,db_2的推導過程:

#正向傳播
 
Z_1 = np.dot(W_1.T,X) + b_1    # 維度N1*M ,N1表示第一隱層的神經元數
A_1 = sigmoid(Z_1)             # 維度N1*M
 
Z_2 = np.dot(W_2.T,A_1) + b_2  # 維度N2*M ,N2表示輸出層的神經元數
A_2 = sigmoid(Z_2)             # 維度N2*M
 
L = cross_entropy(A_2,Y)       # 標量(具體實現待研究)
 
#反向傳播
 
dZ_2 = A_2 - Y                                    # 維度N2*M ,N2表示輸出層的神經元數
dW_2 = 1/m* np.dot(dZ_2, A_1.T)                   # 維度N2*N1 
db_2 = 1/m* np.sum(dZ_2,axis = 1,keepdims = true) # 維度N2*1
 
dZ_1 = np.dot(W_2.T,dZ_2) * A_1*(1-A_1)           # 維度N1*M
dW_1 = 1/m* np.dot(dZ_1, X.T)                     # 維度N1*N0,N0表示單樣本的特徵數
db_1 = 1/m* np.sum(dZ_1,axis = 1,keepdims = true) # 維度N1*1

1.基礎知識

首先回顧一下高數中的導數與微分的知識:

  • 一元微積分中的微分df與導數{f}'(x)(標量對標量的導數):  df = {f}'(x) dx
  • 多元微積分中的微分df與梯度\frac{\partial f}{\partial x}(標量對向量的導數):  df = \sum^{n}_{i=1} \frac{\partial f}{\partial x_{i}} dx_{i} = (\frac{\partial f}{\partial x})^{T}dx

這裡微分與梯度的聯絡中第一個等號是全微分公式,第二個等號則表明全微分df是由梯度向量\frac{\partial f}{\partial x}(n*1)和微分向量dx(n*1)的內積(關於向量內積的概念,可以參考這裡)

  • 受此啟發,我們可以將微分df和矩陣導數\frac{\partial f}{\partial X}(標量對矩陣的導數)視為:df = \sum^{m}_{i=1} \sum^{n}_{j=1} \frac{\partial f}{\partial X_{ij}}dX_{ij}=tr(\frac{\partial f}{\partial X}^{T} dX)

這裡,與梯度類似,第一個等號是全微分公式,第二個等號則表明全微分df是由導數矩陣\frac{\partial f}{\partial X}(m*n)和微分矩陣dX(m*n)的內積(矩陣的內積是指兩個同維矩陣進行元素乘法後新矩陣所有元素相加的和,反映到等式中就是兩個sum

)

需要注意的是tr表示矩陣的跡(tarce),是方針對角線元素之和,滿足性質:對尺寸相同的矩陣A,B

tr(A^{T}B)=\sum_{i,j}A_{ij}B_{ij}

也即:上式左部可視為矩陣A,B的內積(上式右部),例如:

tr(\frac{\partial f}{\partial X}^{T} dX)=tr \bigl(\begin{smallmatrix} \frac{\partial f}{\partial X_{1,1}} &\frac{\partial f}{\partial X_{1,2}} \\ \frac{\partial f}{\partial X_{2,1}}& \frac{\partial f}{\partial X_{2,2}} \end{smallmatrix}\bigr)^{T} \bigl(\begin{smallmatrix} dx_{1,1} &dx_{1,2}\\ dx_{2,1}& dx_{2,2} \end{smallmatrix}\bigr) = tr \bigl(\begin{smallmatrix} \frac{\partial f}{\partial X_{1,1}} &\frac{\partial f}{\partial X_{2,1}} \\ \frac{\partial f}{\partial X_{1,2}} & \frac{\partial f}{\partial X_{2,2}} \end{smallmatrix}\bigr) \bigl(\begin{smallmatrix} dx_{1,1} &dx_{1,2}\\ dx_{2,1}& dx_{2,2} \end{smallmatrix}\bigr)

=tr \bigl(\begin{smallmatrix} \frac{\partial f}{\partial X_{1,1}}dX_{1,1}+\frac{\partial f}{\partial X_{2,1}}dX_{2,1} & \frac{\partial f}{\partial X_{1,1}}dX_{1,2}+\frac{\partial f}{\partial X_{2,1}}dX_{2,2}\\ \frac{\partial f}{\partial X_{1,2}}dX_{1,1}+\frac{\partial f}{\partial X_{2,2}}dX_{2,1} & \frac{\partial f}{\partial X_{1,2}}dX_{1,2}+\frac{\partial f}{\partial X_{2,2}}dX_{2,2} \end{smallmatrix}\bigr)

= \frac{\partial f}{\partial X_{1,1}}dX_{1,1}+\frac{\partial f}{\partial X_{2,1}}dX_{2,1} + \frac{\partial f}{\partial X_{1,2}}dX_{1,2}+\frac{\partial f}{\partial X_{2,2}}dX_{2,2}=\sum^{m}_{i=1} \sum^{n}_{j=1} \frac{\partial f}{\partial X_{ij}}dX_{ij}

2.運演算法則

 回想遇到的較複雜的一元函式.如:f= log(2+sinx)e^{\sqrt{x}}我們是如何求導的呢?通常不是從定義開始求極限,而是先建立了初等函式求導和四則運算、複合等法則,再來運用這些法則。故而,我們來創立常用的矩陣微分的運演算法則:

  • 加減法: d(X\pm Y)=dX \pm dY
  • 乘法: d(XY) = (dX)Y+XdY
  • 轉置: d(X^{T})=dX^{T}
  • 跡: d tr(X) = tr(dX)
  • 逆: dX^{-1}=-X^{-1}dXX^{-1} (可由XX^{-1}=I兩側求微分證明)
  • 行列式: d|X| = tr(X^{*} dX) 其中X^{*}表示X的伴隨矩陣,在X可逆時又可以寫成d|X| = |X|tr(X^{-1} dX)此式可用laplace展開證明
  • 逐元素乘法:d(X\odot Y) = (dX) \odot Y + X \odot dY 其中\odot表示尺寸相同的矩陣X,Y進行元素乘法
  • 逐元素函式:d\sigma(X) = {\sigma}'(X) \odot dX其中\sigma(X) = [\sigma(X_{i,j})]是逐元素標量函式計算{\sigma}'(X) = [{\sigma}'(X_{i,j})]是逐元素標量導數計算

這裡解釋一下逐元素函式和逐元素求導,舉個例子:

X=[x_{1},x_{2}],那麼d(sinX) = [cosx_{1}dx_{1},cosx_{2}dx_{2}] = cosX \odot dX

我們試圖利用微分與矩陣導數的聯絡df = \sum^{m}_{i=1} \sum^{n}_{j=1} \frac{\partial f}{\partial X_{ij}}dX_{ij}=tr(\frac{\partial f}{\partial X}^{T} dX)在求出左側的微分df後,該如何寫成右側的形式並得到導數呢?這需要一些跡技巧(trace trick):

  • 標量套上跡 :  a = tr(a)
  • 轉置: tr(A^{T}) = tr(A)
  • 線性:tr(A \pm B) =tr(A) \pm tr(B)
  • 矩陣乘法交換: tr(AB) = tr(BA),其中A與B^{T}尺寸相同,兩側都等於\sum_{i,j}A_{ij}B_{ij}
  • 矩陣乘法/逐元素乘法交換: tr(A^{T}(B \odot C)) = tr((A \odot B)^{T} C)其中ABC尺寸相同,兩側都等於\sum_{i,j}A_{ij}B_{ij}C_{ij}

觀察一下可以斷言: 若標量函式f是矩陣X經加減乘法、行列式、逆、逐元素函式等運算構成,則使用相應的運演算法則對f求微分,再使用跡技巧給df套上跡(df是標量tr(df) = df)並將其它項交換至dX左側,即能得到導數。

3.三層神經網路反向傳播推導

假定一共有M個樣本,每個樣本的特徵值有N0個,第一隱層的神經元有N1個,輸出層的神經元有N2個 ,正向傳播得到損失L(標量)的過程如下:

#正向傳播
 
Z_1 = np.dot(W_1.T,X) + b_1    # 維度N1*M ,N1表示第一隱層的神經元數
A_1 = sigmoid(Z_1)             # 維度N1*M
 
Z_2 = np.dot(W_2.T,A_1) + b_2  # 維度N2*M ,N2表示輸出層的神經元數
A_2 = sigmoid(Z_2)             # 維度N2*M ,本例中N2=1
 
L = cross_entropy(A_2,Y)       # 標量

具體到損失L的計算公式有:

L = (-(Y\odot log(A_2))-((1-Y)\odot log(1-A_2)) I 

(注:I是一個(M,1)的單位向量,表示求均值的操作,用M個樣本的loss均值表示一個batch的loss)

其中Y(N2,M), \odot是逐元素乘法,N2相當於樣本可以分成N2個種類(本例中N2=1,也就是二分類.如果是多元的就得用softmax而不是cross_entropy,最後得到的同樣是一個標量,不過公式不同了),M是樣本總數.  

  • 第一步: 求微分dL

dL = -(dY\odot log(A_{2})+Y\odot dlog(A_{2})+d(1-Y)\odot log(1-A_{2})+(1-Y)\odot dlog(1-A_{2})) I

其中Y是常矩陣,所以dY和dI為零陣,同時由法則知dlog(A_{2}) = \frac{1}{A_{2}} \odot dA_{2}代入得:

dL= (\frac{A_{2}-Y}{A_{2}\odot (1-A{2})} \odot dA_{2}) I

因為我們要求的是\frac{\partial L}{\partial W_{2}}所以需要繼續對A_{2},Z_{2}進行微分以出現dW_{2},由法則可得:

dA_{2} = A_{2}\odot (1-A_{2})\odot dZ_{2}

dZ_{2} = d(W_{2}^{T})A_{1}+W_{2}^{T}dA_{1}  注意這裡W和A都是變數,利用法則:d(XY) = (dX)Y+XdY

代入後可得dL:

dL = ((A_{2}-Y)\odot dZ_{2}) I                                                                   (1)

dL = ((A_{2}-Y)\odot d(W_{2}^{T})A_{1}+(A_{2}-Y)\odot W_{2}^{T}dA_{1}) I            (2)

  •  第二步:  使用跡技巧將dW換到最右側

         對於(1)式:

        dZ_{2}已經在最右側,所以直接進行跡轉換可得

                                          dL = tr(dL) = tr(((A_{2}-Y)\odot dZ_{2})I)

        因為(A_{2}-Y)\odot dZ_{2}I^{T}尺寸相同,所以有:

                                         dL = tr(dL) = tr(I((A_{2}-Y)\odot dZ_{2})) = tr((I^{T})^{T}((A_{2}-Y)\odot dZ_{2}))

        由法則tr(A^{T}(B \odot C)) = tr((A \odot B)^{T} C)得:

                                dL =tr(dL) = tr(I((A_{2}-Y)\odot dZ_{2})) = tr((I^{T})^{T}((A_{2}-Y)\odot dZ_{2}))= tr([(I^{T})\odot (A_{2}-Y)]^{T} dZ_{2})

        根據dL = tr((\frac{\partial L}{\partial Z_{2}})^{T}dZ_{2}),將其和上式最右公式比對知:

                                         \frac{\partial L}{\partial Z_{2}} =(I^{T})\odot (A_{2}-Y) = A_{2}-Y

        對於(2)式:

d(W_{2}^{T})並不在子式的最右端,因此需要進行變換: