寫在前面
前期學習深度學習的時候,很多概念都是一筆帶過,只是覺得它在一定程度上解釋得通就行,但是在強化學習的過程中突然意識到,反向傳播求梯度其實并不是一件簡單的事情,這篇博客的目的就是要講清楚反向傳播是如何對特定的某一層求梯度,進而更新其參數的
為什么反向傳播不容易實現
首先,眾所周知,深度網絡就是一個廣義的多元函數,
但在通常情況下,想要求一個函數的梯度,就必須知道這個函數的具體表達式
但是問題就在于,深度網絡的“傳遞函數”并不容易獲得,或者說并不容易顯式地獲得
進而導致反向傳播的過程難以進行
為什么反向傳播可以實現
損失函數是關于參數的函數
如果要將一個函數F對一個變量x求偏導,那偏導存在的前提條件就是F是關于x的函數,否則求導結果就是0
- 符號定義(后續公式均據此展開)
- x=[x1,x2,…xn]x=[x_1,x_2,\dots x_n]x=[x1?,x2?,…xn?]
- ypred=[y1,y2,…ym]y_{pred}=[y_1,y_2, \dots y_m]ypred?=[y1?,y2?,…ym?]
- θ=[w1,b1,w2,b2,…wn,bn]\theta=[w_1,b_1,w_2,b_2,\dots w_n,b_n]θ=[w1?,b1?,w2?,b2?,…wn?,bn?]
- ai=第i層網絡激活函數的輸出,最后一層的輸出就是ypreda^{i}=第 i層網絡激活函數的輸出,最后一層的輸出就是y_{pred}ai=第i層網絡激活函數的輸出,最后一層的輸出就是ypred?
- zi=第i層網絡隱藏層的輸出z^{i}=第i層網絡隱藏層的輸出zi=第i層網絡隱藏層的輸出
- gi?′(zi)第i層激活函數的導數,在輸入=zi處的值g^i\ '(z^i)第i層激活函數的導數,在輸入=z^i處的值gi?′(zi)第i層激活函數的導數,在輸入=zi處的值
- 關系式
- 網絡的抽象函數式 ypred=F(x;θ)y_{pred}=F(x;\theta)ypred?=F(x;θ)
即網絡就是一個巨大的多元函數,接受兩個向量(模型輸入和參數)作為輸入,經過內部正向傳播后輸出一個向量 - 損失函數Loss的抽象函數式 Loss=L(ytrue,ypred)=L(ytrue,F(x;θ))Loss=L(y_{true},y_{pred})=L(y_{true},F(x;\theta))Loss=L(ytrue?,ypred?)=L(ytrue?,F(x;θ))
其中 ytruey_{true}ytrue? 和 xxx 屬于參變量,它雖然會變,但是和模型本身沒什么關系,唯一屬于模型自己的變量就是 θ\thetaθ,所以不難看出,損失函數L是關于模型參數 θ\thetaθ 的函數,損失值Loss完全由模型參數 θ\thetaθ 決定
- 網絡的抽象函數式 ypred=F(x;θ)y_{pred}=F(x;\theta)ypred?=F(x;θ)
鏈式法則
-
這個法則是深層網絡得以實現梯度計算的關鍵
核心公式如下:
?L?θi=?L?zi??zi?θi \frac{\partial L}{\partial \theta^i}=\frac{\partial L}{\partial z^i}·\frac{\partial z^i}{\partial \theta^i} ?θi?L?=?zi?L???θi?zi?
其中,?L?zi\frac{\partial L}{\partial z^i}?zi?L?是損失L對第i層加權輸入ziz^izi的梯度,?zi?θi\frac{\partial z^i}{\partial \theta^i}?θi?zi?是第i層加權輸入ziz^izi對本層參數θi\theta^iθi的梯度 -
進一步深究可以發現?zi?θi\frac{\partial z^i}{\partial \theta^i}?θi?zi?相對容易求,因為它只涉及到當前層的當前神經元的求解,在面向對象語言中,很容易為每個屬于同一個類的實例增加一個方法,比如像這里的輸入對參數求導,舉例來說;
if?θi=Wi?and?Zi=Wi?ai?1+bi,then??zi?θi=(ai?1)T if\ \theta^i=W^i\ and\ Z^i=W^i*a^{i-1}+b^i,\\ then\ \frac{\partial z^i}{\partial \theta^i}=(a^{i-1})^T if?θi=Wi?and?Zi=Wi?ai?1+bi,then??θi?zi?=(ai?1)T
其中,
(說實話,我非常想把隱藏層稱為“傳遞函數”,控制和機器學習實際上有非常多可以相互借鑒的地方,而且在事實上,二者也確實是不可分割的關系) -
然后我們要來處理相對麻煩的 ?L?zi\frac{\partial L}{\partial z^i}?zi?L?
- 多層感知機為例,共k層,已知網絡輸出,求網絡第i層的梯度
- 用數學歸納法在這種遞歸系統中比較合適
-
歸納奠基
L=L(ytrue,ypred)=L(ytrue,F(x;θ))L=L(y_{true},y_{pred})=L(y_{true},F(x;\theta))L=L(ytrue?,ypred?)=L(ytrue?,F(x;θ))?L?zk=?L?ak??ak?zk=?L?ak?(gk)′(zk)\frac{\partial L}{\partial z^k}=\frac{\partial L}{\partial a^k}·\frac{\partial a^k}{\partial z^k}=\frac{\partial L}{\partial a^k}\otimes (g^k)'(z^k)?zk?L?=?ak?L???zk?ak?=?ak?L??(gk)′(zk)
上面的公式說明:損失對隱藏層輸出的偏導,等價于損失函數對最終輸出的偏導,再逐元素乘上最后層激活函數 在隱藏層輸出處 的導數
其中,激活函數在創建網絡時就明確已知,因此求導取值并沒有難度
由于Loss=L(ytrue,ypred)Loss=L(y_{true},y_{pred})Loss=L(ytrue?,ypred?)直接與網絡最終輸出ypredy_{pred}ypred?相關,因此損失對最終輸出的偏導并不難求;
比如將損失函數定義為均方差MSE:(其他網絡基本同理)
L=12∑j=1m(yj?ajk)2?L?ak=?(yj?ajk)L=\frac{1}{2}\sum^m_{j=1}(y_j-a_j^k)^2\\\frac{\partial L}{\partial a^k}=-(y_j-a_j^k)L=21?j=1∑m?(yj??ajk?)2?ak?L?=?(yj??ajk?) -
歸納遞推(從第 i 層到第 i-1 層)
假設已知 ?L?zi\frac{\partial L}{\partial z^i}?zi?L?(反向傳播,因此我們假設的是后一層已知)
由鏈式法則可得:
?L?zi?1=(?L?zi)?(?zi?ai?1)?(?ai?1?zi?1)\frac{\partial L}{\partial z^{i-1}}=(\frac{\partial L}{\partial z^i})·(\frac{\partial z^i}{\partial a^{i-1}})·(\frac{\partial a^{i-1}}{\partial z^{i-1}})?zi?1?L?=(?zi?L?)?(?ai?1?zi?)?(?zi?1?ai?1?)
其中,第一個因子已知第二個因子?zi?ai?1\frac{\partial z^i}{\partial a^{i-1}}?ai?1?zi?,分子為第 i 層隱藏層的輸出,分母為第 i 層隱藏層的輸入(即第 i-1 層激活層的輸出),因此其值就是第 i 層隱藏層的權重矩陣WiW^iWi本身
第三個因子?ai?1?zi?1\frac{\partial a^{i-1}}{\partial z^{i-1}}?zi?1?ai?1?,分子為第 i-1 層激活層的輸出,分母為第 i-1 層激活層的輸入,因此其值就是 第 i-1 層激活函數 在隱藏層輸出處 的導數
綜上:在已知第 i 層損失對輸出的梯度的情況下,可以推出第 i-1 層損失對輸出的梯度,遞推成立
-
歸納總結
綜上所述,反向傳播求梯度完全可行,按照上面的過程撰寫程序,就可以很方便地反向逐層 根據損失梯度 更新參數
-