神經網絡反向傳播向量化(CS231n A1 Q4)——已重寫

禁止轉載

問題

常見的標量版反向傳播公式從推導上易於理解,但對代碼實現不友好
所以這裏用向量化的形式寫出反向傳播。 具體要求:

  1. 向量化寫法,避免出現\sum,只採用矩陣的四則運算和逐元素運算
  2. 帶有L2正則項
  3. 直接寫一個batch,避免一個一個樣本的寫
  4. 多分類交叉熵損失

說明

  • 上述這些要求的優勢在於可以直接轉化爲向量化的計算代碼
  • 在pytorch、numpy等框架中,向量化的計算比用循環累加要快非常多
  • 本文參考了矩陣求導術-上,強推!本文采用的符號規範與之一致,如果沒有看過直接看本文也沒有問題

網絡結構

  • 網絡結構必須定義明確,說明清楚
  • 輸入數據爲X,YX,Y
  • 網絡一共三層,結構爲:
    fc1:XF1relu:F1G1fc2:G1F2f_{c_1}:X \rightarrow F_1 \\ relu: F_1 \rightarrow G_1 \\ f_{c_2}: G_1 \rightarrow F_2 \\
  • 輸入層維度爲DD,隱層維度爲HH,輸出層維度爲CC. 所以每一層的參數形狀爲
    W1RH×DW2RC×Hb1RH×1b2RC×1 W_1 \in \mathbb{R}^{H \times D} \\ W_2 \in \mathbb{R}^{C \times H}\\ b_1 \in \mathbb{R}^{H \times 1}\\ b_2 \in \mathbb{R}^{C \times 1}
  • 記一次batch樣本數爲NN,所以輸入層、隱層、類別標註的形狀爲
    XRD×NF1,G1RH×NF2,YRC×N X \in \mathbb{R}^{D \times N} \\ F_1,G_1 \in \mathbb {R}^{H \times N} \\ F_2, Y \in \mathbb {R}^{C \times N} \\
    這裏YY採用了one-hot編碼
  • 我用了列向量寫法,如果你習慣於行向量,那麼可以參考我貼在文末的手稿

前向傳播

F1=W1X+b111×N(1) F_1 = W_1 X + b_1 \mathbf{1}_{1 \times N} \tag{1}
G1=max(0,F1)(2) G_1 = max(0, F_1) \tag{2}
F2=W2G1+b211×N(3) F_2 = W_2 G_1 + b_2 \mathbf{1}_{1 \times N} \tag{3}
其中1a×b\mathbf{1}_{a\times b}表示形狀爲a×ba\times b的全1矩陣
L1\mathcal{L}_1爲經驗損失項
L1=[ln(11×CeF2)11×C(F2Y)]1N×1(4) \mathcal{L}_1 = [\ln (\mathbf{1}_{1\times C}e^{F_2} )- \mathbf{1}_{1\times C}(F_2 \odot Y)] \mathbf{1}_{N\times 1}\tag{4}
其中“\odot”表示逐元素乘法,要求參與運算的兩個矩陣維度相同
本文所有的指數函數ee^{\cdot}和對數函數ln()\ln(\cdot)都爲逐元素函數
取均值的操作1NL1\frac{1}{N}\mathcal{L}_1放到了後文引入,爲了方便求導書寫
式(4)的正確性稍加解釋
對於樣本iiL1i=lneF2yiiy=1CeF2yi=ln(y=1CeF2yi)F2yii=ln(11×CeF2i)11×C(F2iYi)\mathcal{L}_1^i=-\ln \frac{e^{{F_2}_{y_i i}}}{\sum_{y=1}^{C} e^{{F_2}_{y i}}}=\ln (\sum_{y=1}^{C} e^{{F_2}_{y i}}) - {F_2}_{y_i i}=\ln(\mathbf{1}_{1\times C}e^{{F_2}_{\cdot i}})-\mathbf{1}_{1\times C}({F_2}_{\cdot i} \odot Y_{\cdot i}).
其中yi{1,2,...,N}y_i \in \{1,2,...,N\},表示樣本ii的類別。只要注意到YiY_{\cdot i}是one-hot編碼,該推導不難成立
L1=i=1NL1i\mathcal{L}_1=\sum_{i=1}^{N}\mathcal{L}_1^i,得式(4),可以自行驗證

[

  • 一段冗筆,可以不看
    如果記Y^\hat{Y}爲經過softmax後的網絡輸出,Y^RC×N\hat{Y} \in \mathbb{R}^{C \times N},那麼
    Y^=eF211C×CeF2 \hat{Y} = e^{F_2} \odot \frac{1}{\mathbf{1}_{C \times C} e^{F_2}}
    其中1A\frac{1}{A}表示把AA逐元素取倒數,L1\mathcal{L}_1又可寫成
    L1=ln(11×C(Y^Y))1N×1 \mathcal{L}_1 = - \ln(\mathbf{1}_{1\times C} (\hat{Y} \odot Y)) \mathbf{1}_{N \times 1}
    這樣L1\mathcal{L}_1就避免了直接使用F2F_2,但是該式到式(4)的正確性不易看出,該式也不利於後續求導
    不過這兩式易於構建計算圖,方便代碼實現
    後續推導仍然使用式(4)

]

L2\mathcal{L}_2表示正則損失項,L21\mathcal{L}_{21}W1W_1的損失,L22\mathcal{L}_{22}W2W_2的損失
L2=L21 ⁣+ ⁣L22=11×H ⁣(W1 ⁣ ⁣W1) ⁣1D×1 ⁣+ ⁣11×C ⁣(W2 ⁣ ⁣W2) ⁣1H×1(5) \mathcal{L}_2=\mathcal{L}_{21} \!+ \!\mathcal{L}_{22}=\mathbf{1}_{1\times H}\!(W_1 \!\odot \! W_1) \!\mathbf{1}_{D\times 1} \! + \! \mathbf{1}_{1\times C} \! (W_2 \! \odot \! W_2) \!\mathbf{1}_{H\times 1} \tag{5}
L=1NL1+λL2(6) \mathcal{L} =\frac{1}{N} \mathcal{L}_1+\lambda \mathcal{L}_2 \tag{6}
式(1)~式(6)完整介紹了前向傳播的向量化寫法
下一節將介紹反向傳播的向量化寫法,高潮要來了呀,準備好

反向傳播

首先簡單介紹兩個知識點

  • Jacobian辨識:如果df=tr(AdX)df=tr(AdX),那麼fX=AT\frac{\partial f}{\partial X} =A^T
    即如果想求fX\frac{\partial f}{\partial X},只要能把dfdf寫成tr(AdX)tr(AdX)的形式,那麼就能把fX\frac{\partial f}{\partial X}辨識出來,爲ATA^T
  • 跡的一些性質,很重要,這些技巧後文會用
    • 矩陣乘法/逐元素乘法交換:tr{AT(BC)}=tr{(AB)TC}tr\{A^T(B \odot C)\}=tr\{(A \odot B)^T C\}
    • 輪換對稱性:tr{AB}=tr{BA}tr\{AB\}=tr\{BA\}
    • 轉置跡不變:tr{A}=tr{AT}tr\{A\}=tr\{A^T\}
    • 微分內提:dtr{A}=tr{dA}dtr\{A\}=tr\{dA\}

另外,我們記1A\frac{1}{A}表示把AA逐元素取倒數

開始吧

經驗損失項

dL=1NdL1+λdL2(7) d\mathcal{L} =\frac{1}{N}d \mathcal{L}_1 + \lambda d\mathcal{L}_2 \tag{7}
dL1=[d[ln(11×CeF2)]11×C(dF2Y)]1N×1=[d[(11×CeF2)]111×CeF211×C(dF2Y)]1N×1=[(11×C(eF2dF2))111×CeF211×C(dF2Y)]1N×1=tr{[(11×C(eF2dF2))111×CeF211×C(dF2Y)]1N×1}=tr{[(11×C(eF2dF2))111×CeF2]1N×1}tr{11×C(dF2Y)1N×1}=tr{1N×1[(11×C(eF2dF2))111×CeF2]}tr{1N×C(dF2Y)}=tr{[11×N(11×C(eF2dF2))]T111×CeF2}tr{(1C×NdF2)TY)}=tr{[11×C(eF2dF2)]T111×CeF2}tr{dF2TY}=tr{(dF2TeF2T)(1C×1111×CeF2)}tr{dF2TY}=tr{dF2T[eF2(1C×1111×CeF2)]}tr{dF2TY}=tr{[eF2(1C×1111×CeF2)Y]TdF2} \begin{aligned} d\mathcal{L}_1 &= [d[\ln (\mathbf{1}_{1\times C}e^{F_2} )]- \mathbf{1}_{1\times C}(dF_2 \odot Y)] \mathbf{1}_{N\times 1} \\ &=[d[(\mathbf{1}_{1\times C}e^{F_2} )] \odot \frac{1}{\mathbf{1}_{1\times C}e^{F_2}}- \mathbf{1}_{1\times C}(dF_2 \odot Y)] \mathbf{1}_{N\times 1} \\ &=[(\mathbf{1}_{1\times C}(e^{F_2}\odot dF_2)) \odot \frac{1}{\mathbf{1}_{1\times C}e^{F_2}}- \mathbf{1}_{1\times C}(dF_2 \odot Y)] \mathbf{1}_{N\times 1} \\ &= tr\{[(\mathbf{1}_{1\times C}(e^{F_2}\odot dF_2)) \odot \frac{1}{\mathbf{1}_{1\times C}e^{F_2}}- \mathbf{1}_{1\times C}(dF_2 \odot Y)] \mathbf{1}_{N\times 1} \} \\ &= tr\{[(\mathbf{1}_{1\times C}(e^{F_2}\odot dF_2)) \odot \frac{1}{\mathbf{1}_{1\times C}e^{F_2}}] \mathbf{1}_{N\times 1}\}- tr\{\mathbf{1}_{1\times C}(dF_2 \odot Y) \mathbf{1}_{N\times 1} \} \\ &= tr\{\mathbf{1}_{N\times 1}[(\mathbf{1}_{1\times C}(e^{F_2}\odot dF_2)) \odot \frac{1}{\mathbf{1}_{1\times C}e^{F_2}}] \}- tr\{\mathbf{1}_{N\times C}(dF_2 \odot Y) \} \\ &= tr\{[\mathbf{1}_{1\times N}\odot(\mathbf{1}_{1\times C}(e^{F_2}\odot dF_2))]^T\frac{1}{\mathbf{1}_{1\times C}e^{F_2}} \}- tr\{(\mathbf{1}_{C\times N}\odot dF_2 )^T Y) \} \\ &= tr\{[\mathbf{1}_{1\times C}(e^{F_2}\odot dF_2)]^T\frac{1}{\mathbf{1}_{1\times C}e^{F_2}} \}- tr\{dF_2^T Y\} \\ &= tr\{(dF_2^T\odot {e^{F_2}}^T) (\mathbf{1}_{C\times 1}\frac{1}{\mathbf{1}_{1\times C}e^{F_2}} ) \}-tr\{dF_2^T Y\} \\ &= tr\{dF_2^T [ {e^{F_2}} \odot (\mathbf{1}_{C\times 1}\frac{1}{\mathbf{1}_{1\times C}e^{F_2}})]\}- tr\{dF_2^T Y\} \\ &= tr\{ [ {e^{F_2}} \odot (\mathbf{1}_{C\times 1}\frac{1}{\mathbf{1}_{1\times C}e^{F_2}}) - Y]^TdF_2\}\\ \end{aligned}
一波推導,Jacobian辨識得
L1F2=eF2(1C×1111×CeF2)Y(8) \frac{\partial{\mathcal L_1}}{\partial F_2} = {e^{F_2}} \odot (\mathbf{1}_{C\times 1}\frac{1}{\mathbf{1}_{1\times C}e^{F_2}}) - Y \tag{8}
接下來,開始反向傳播,由式(3)
dL1=tr{L1F2TdF2}=tr{L1F2T(dW2G1+W2dG1+db211×N)}=tr{G1L1F2TdW2}+tr{L1F2TW2dG1}+tr{11×NL1F2Tdb2} \begin{aligned} d\mathcal{L}_1 &= tr\{\frac{\partial{\mathcal L_1}}{\partial F_2}^TdF_2\} \\ &=tr\{\frac{\partial{\mathcal L_1}}{\partial F_2}^T(dW_2 G_1+W_2 dG_1+db_2 \mathbf{1}_{1\times N})\} \\ &=tr\{G_1\frac{\partial{\mathcal L_1}}{\partial F_2}^TdW_2 \}+tr\{\frac{\partial{\mathcal L_1}}{\partial F_2}^T W_2dG_1 \} + tr\{\mathbf{1}_{1\times N}\frac{\partial{\mathcal L_1}}{\partial F_2}^Tdb_2 \} \end{aligned}
Jacobian辨識得
L1W2=L1F2G1T(9) \frac{\partial{\mathcal L_1}}{\partial W_2}=\frac{\partial{\mathcal L_1}}{\partial F_2}G_1^T \tag{9}
L1b2=L1F21N×1(10) \frac{\partial{\mathcal L_1}}{\partial b_2}=\frac{\partial{\mathcal L_1}}{\partial F_2}\mathbf{1}_{N\times 1} \tag{10}
L1G1=W2TL1F2(11) \frac{\partial{\mathcal L_1}}{\partial G_1}=W_2^T\frac{\partial{\mathcal L_1}}{\partial F_2} \tag{11}
式(9)和式(10)給出了經驗損失項關於W2W_2b2b_2的參數更新公式
我們繼續反向傳播,由式(2)
dL1=tr{L1G1dG1}+...G1無關項)=tr{L1G1[I(F1>0)dF1]}+...=tr{[L1G1TI(F1>0)]TdF1}+... \begin{aligned} d\mathcal{L}_1 &= tr\{\frac{\partial{\mathcal L_1}}{\partial G_1}dG_1 \} + ...\text{($G_1$無關項)} \\ &= tr\{\frac{\partial{\mathcal L_1}}{\partial G_1} [\mathbb{I}(F_1 > 0) \odot dF_1] \} + ... \\ &= tr\{[\frac{\partial{\mathcal L_1}}{\partial G_1}^T \odot \mathbb{I}(F_1 > 0)] ^TdF_1 \} + ... \end{aligned}
Jacobian辨識得
L1F1=L1G1I(F1>0)(12) \frac{\partial{\mathcal L_1}}{\partial F_1}=\frac{\partial{\mathcal L_1}}{\partial G_1} \odot \mathbb{I}(F_1 > 0) \tag{12}
由式(1)
dL1=tr{L1F1TdF1}+...F1無關項)=tr{L1F1T(dW1X+db111×N)}+...=tr{XL1F1TdW1}+tr{11×NL1F1Tdb1}+... \begin{aligned} d\mathcal{L}_1 &= tr\{\frac{\partial{\mathcal L_1}}{\partial F_1}^TdF_1\} + ...\text{($F_1$無關項)} \\ &= tr\{\frac{\partial{\mathcal L_1}}{\partial F_1}^T (dW_1 X + db_1 \mathbf{1}_{1\times N})\} + ... \\ &= tr\{X\frac{\partial{\mathcal L_1}}{\partial F_1}^T dW_1\} + tr\{ \mathbf{1}_{1\times N}\frac{\partial{\mathcal L_1}}{\partial F_1}^Tdb_1\}+ ... \end{aligned}
Jacobian辨識得
L1W1=L1F1XT(13) \frac{\partial{\mathcal L_1}}{\partial W_1} = \frac{\partial{\mathcal L_1}}{\partial F_1} X^T \tag{13}
L1b1=L1F11N×1(14) \frac{\partial{\mathcal L_1}}{\partial b_1} = \frac{\partial{\mathcal L_1}}{\partial F_1} \mathbf{1}_{N\times 1} \tag{14}
式(13)和式(14)給出了經驗損失項關於W1W_1b1b_1的參數更新公式。注意這兩式和W2,b2W_2,b_2更新公式(9)和(10)之間的相似性。更多層反向傳播公式是可以歸納出來的

正則損失項

對於L2\mathcal{L}_{2}
dL21=11×H(W1dW1)1D×1+11×H(dW1W1)1D×1=2tr{11×H(W1dW1)1D×1}=2tr{1D×H(W1dW1)}=2tr{(1H×DW1)TdW1)}=tr{2W1TdW1} \begin{aligned} d\mathcal{L}_{21} &= \mathbf{1}_{1\times H}(W_1 \odot dW_1) \mathbf{1}_{D\times 1} + \mathbf{1}_{1\times H}(dW_1 \odot W_1) \mathbf{1}_{D\times 1} \\ &= 2tr\{\mathbf{1}_{1\times H}(W_1 \odot dW_1) \mathbf{1}_{D\times 1} \} \\ &= 2tr\{\mathbf{1}_{D\times H}(W_1 \odot dW_1)\} \\ &= 2tr\{(\mathbf{1}_{H\times D} \odot W_1) ^T dW_1)\} \\ &= tr\{2W_1^T dW_1\} \end{aligned}
由Jacobian辨識得
L21W1=2W1(15) \frac{\partial \mathcal{L}_{21}}{\partial W_1} = 2W_1 \tag{15}
同理
L21W2=2W2(16) \frac{\partial \mathcal{L}_{21}}{\partial W_2} = 2W_2 \tag{16}
可以看出L2參數項對參數的影響與用標量寫法推導是一致的
L1參數項的向量化推導類似

後記

  • 寫了一天……
  • 矩陣求導是非常強大的工具,而且求出來的表達式可以直接轉化成代碼實現
  • 類似的方法可以推導SVM合頁損失、Logistic迴歸、線性迴歸等的參數更新公式,可以留作練習(想起來之前面試讓我求最小二乘的梯度,我想推向量寫法,沒推出來就很氣,無奈勉強寫了標量寫法)
  • 上述方法始終保持了標量對矩陣求導,反向傳播即是把矩陣微分不斷打開的過程
  • 矩陣求導術(下)中,給出了一種矩陣對矩陣求導的技法,似乎是可以寫出另一種鏈式法則,這裏我存有一個疑問:
    如果輸出結果爲標量(例如loss),是否用矩陣求導術(上)的方法更爲方便?因爲(下)中方法要先把矩陣拍開,而後再合上?
  • 我用手稿寫了一份行向量的版本,僅供參考
    在這裏插入圖片描述
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章