1. 程式人生 > >神經網路反向傳播時的梯度到底怎麼求?

神經網路反向傳播時的梯度到底怎麼求?

相信每一個剛剛入門神經網路(現在叫深度學習)的同學都一定在反向傳播的梯度推導那裡被折磨了半天。在各種機器學習的課上明明聽得非常明白,神經網路無非就是正向算一遍Loss,反向算一下每個引數的梯度,然後大家按照梯度更新就好了。問題是梯度到底怎麼求呢?課上往往舉的是標量的例子,可是一到你做作業的時候就發現所有的東西都是vectorized的,一個一個都是矩陣。矩陣的微分操作大部分人都是不熟悉的,結果使得很多人在梯度的推導這裡直接選擇死亡。我曾經就是其中的一員,做CS231n的Assignment 1裡面那幾個簡單的小導數都搞得讓我懷疑人生。

我相信很多人都看了不少資料,比如CS231n的講師Karpathy推薦的這一篇矩陣求導指南

cs231n.stanford.edu/vec,但是經過了幾天的折磨以後,我發現事實上根本就不需要去學習這些東西。在神經網路中正確計算梯度其實非常簡單,只需要把握好下面的兩條原則即可。這兩條原則非常適合對矩陣微分不熟悉的同學,雖然看起來並不嚴謹,但是有效。

1. 用好維度分析,不要直接求導

神經網路中求梯度,第一原則是:如果你對矩陣微分不熟悉,那麼永遠不要直接計算一個矩陣對另一個矩陣的導數。我們很快就可以看到,在神經網路中,所有的矩陣對矩陣的導數都是可以通過間接的方法,利用求標量導數的那些知識輕鬆求出來的。而這種間接求導數的方法就是維度分析。我認為維度分析是神經網路中求取梯度最好用的技巧,沒有之一。用好維度分析,你就不用一個一個地去分析矩陣當中每個元素究竟是對誰怎麼求導的,各種求和完了以後是左乘還是右乘,到底該不該轉置等等破事,簡直好用的不能再好用了。這一技巧在Karpathy的Course Note上也提到了一點。

什麼叫維度分析?舉一個最簡單的例子。設某一層的Forward Pass為score=XW+b,X是NxD的矩陣,W是DxC的矩陣,b是1xC的矩陣,那麼score就是一個NxC的矩陣。現在上層已經告訴你L對score的導數是多少了,我們求L對W和b的導數。

我們已經知道\frac{dL}{dscore}一定是一個NxC的矩陣(因為Loss是一個標量,score的每一個元素變化,Loss也會隨之變化),那麼就有

\frac{dL}{dW}=\frac{dL}{dscore}\frac{dscore}{dW}

現在問題來了,score是一個矩陣,W也是個矩陣,矩陣對矩陣求導,怎麼求啊?如果你對矩陣微分不熟悉的話,到這裡就直接懵逼了。於是很多同學都出門右轉去學習矩陣微分到底怎麼搞,看到那滿篇的推導過程就感到一陣噁心,之後就提前走完了從入門到放棄,從深度學習到深度厭學的整個過程。

其實我們沒有必要直接求score對W的導數,我們可以利用另外兩個導數間接地把\frac{dscore}{dW}算出來。首先看看它是多大的。我們知道\frac{dL}{dW}一定是DxC的(和W一樣大),而\frac{dL}{dscore}是NxC的,哦那你瞬間就發現了\frac{dscore}{dW}一定是DxN的,因為(DxN)x(NxC)=>(DxC),並且你還發現你隨手寫的這個式子右邊兩項寫反了,應該是\frac{dL}{dW}=\frac{dscore}{dW}\frac{dL}{dscore}

那好,我們已經知道了\frac{dscore}{dW}是DxN的,那就好辦了。既然score=XW+b,如果都是標量的話,score對W求導,本身就是X;X是NxD的,我們要DxN的,那就轉置一下唄,於是我們就得出了:

\frac{dL}{dW}=\frac{dL}{dscore}X^T

完事了。

你看,我們並沒有直接去用諸如\frac{dscore_{11}}{dW_{11}}這種細枝末節的一個一個元素求導的方式推導\frac{dscore}{dW},而是利用\frac{dL}{dW},\frac{dL}{dscore}再加上熟悉的標量求導的知識,就把這個矩陣求導給算出來了。這就是神經網路中求取導數的正確姿勢。

為什麼這一招總是有效呢?這裡的關鍵點在於Loss是一個標量,而標量對一個矩陣求導,其大小和這個矩陣的大小永遠是一樣的。那麼,在神經網路裡,你永遠都可以執行這個“知二求一”的過程,其中的“二”就是兩個Loss對引數的導數,另一個是你不會求的矩陣對矩陣的導數。首先把你沒法直接求的矩陣導數的大小給計算出來,然後利用你熟悉的標量求導的方法大概看看導數長什麼樣子,最後湊出那個目標大小的矩陣來就好了。

\frac{dL}{db}呢?我們來看看,\frac{dL}{dscore}是NxC的,\frac{dL}{db}是1xC的,\frac{dscore}{db}看起來像1,那聰明的你肯定想到\frac{dscore}{db}其實就是1xN個1了,因為(1xN)x(NxC)=>(1xC)。其實這也就等價於直接對dscore的第一維求個和,把N降低成1而已。

多說一句,這個求和是怎麼來的?原因實際上在於所謂的“廣播”機制。你會發現,XW是一個NxC的矩陣,但是b只是一個1xC的矩陣,按理說,這倆矩陣形狀不一樣,是不能相加的。但是我們都知道,實際上我們想做的事情是讓XW的每一行都加上b。也就是說,我們把b的第一維複製了N份,強行變成了一個NxC的矩陣,然後加在了XW上(當然這件事實際上是numpy幫你做的)。那麼,當你要回來求梯度的時候,既然每一個b都參與了N行的運算,那就要把每一份的梯度全都加起來求個和的。因為求導法則告訴我們,如果一個變數參與了多個運算,那就要把它們的導數加起來。這裡借用一下@午後陽光的圖,相信大家可以看得更明白。

總之,不要試圖在神經網路裡面直接求矩陣對矩陣的導數,而要用維度分析間接求,這樣可以為你省下很多不必要的麻煩。

2. 用好鏈式法則,不要一步到位

我曾經覺得鏈式法則簡直就是把簡單的問題搞複雜,複合函式求導這種東西高考的時候我們就都會了,還用得著一步一步地往下拆?比如h=e^{wx+b},我一眼就能看出來\frac{dh}{dw}=e^{wx+b}\cdot{x},還用得著先把wx+b當成一箇中間函式麼?

不幸的是,在神經網路裡面,你會發現事情沒那麼容易。上面的這些推導只在標量下成立,如果w,x和b都是矩陣的話,我們很容易就感到無從下筆。還舉上面這個例子,設H=e^{XW+b},我們要求\frac{dL}{dW},那麼我們直接就可以寫出

\frac{dL}{dW}=\frac{dL}{dH}\cdot\frac{dH}{dW}

L對H的導數,是反向傳播當中上一層會告訴你的,但問題是H對W的導數怎麼求呢?

如果你學會了剛才的維度分析法,那麼你可能會覺得\frac{dH}{dW}是一個DxN的矩陣。然後就會發現沒有任何招可以用了。事實上,卡殼的原因在於,\frac{dH}{dW}根本不是一個矩陣,而是一個4維的tensor。對這個鬼玩意的運算初學者是搞不定的。

這是一個剛學完反向傳播的初學者很容易踩到的陷阱:試圖不設中間變數,直接就把目標引數的梯度給求出來。如果這麼去做的話,很容易在中間碰到這種非矩陣的結構,因為理論上矩陣對矩陣求導求出來是一個4維tensor,不是我們熟悉的二維矩陣。

但是,如果你不直接求取對W的導數,而把XW+b當做一箇中間變數的話,事情就簡單的多了。因為如果每一步求導都只是一個簡單二元運算的話,那麼即使是矩陣對矩陣求導,求出來也仍然是一個矩陣,這樣我們就可以用維度分析法往下做了。

S=XW+b,則有

\frac{dL}{dS}=\frac{dL}{dH}\frac{dH}{dS}

利用維度分析:dS是NxC的,dH是NxC的,考慮到H=e^S,那麼容易想到\frac{dH}{dS}也是NxC的,也就是e^S,這是一個element-wise的相乘;所以\frac{dL}{dS}=e^S\cdot\frac{dL}{dH}

再求\frac{dL}{dW}=\frac{dL}{dS}\frac{dS}{dW},用上一部分的方法,很容易求得\frac{dS}{dW}=X^T,所以就求完了。

有了這些結果,我們不妨回頭看看一開始的那個式子:\frac{dL}{dW}=\frac{dL}{dH}\cdot\frac{dH}{dW},如果你錯誤地認為\frac{dH}{dW}是一個DxN的矩陣的話,再往下運算:

\frac{dH}{dW}=\frac{dH}{dS}\frac{dS}{dW}

我們已經知道\frac{dH}{dS}=e^S, \frac{dS}{dW}=X^T,這兩個矩陣一個是NxC的,一個是DxN的,無論怎麼相乘,也得不出DxN的矩陣。矛盾就是出在H對W的導數其實並不是一個矩陣。但是如果使用鏈式法則運算的話,我們就可以避開這個複雜的tensor,只使用矩陣運算和標量求導就搞定神經網路中的梯度推導。

藉助這兩個技巧,已經足以計算任何複雜的層的梯度。下面我們來實戰一個:求Softmax層的梯度。

Softmax層往往是輸出層,其Forward Pass公式為:

Loss=\frac{1}{N}\Sigma_N-ln(P_i),P=\frac{e^{score_{y_i}}}{\Sigma_y{e^{score_{y}}}},score=XW+b

假設輸入X是NxD的,總共有C類,那麼W顯然應該是DxC的,b是1xC的。其中P_i就是第i個樣本預測的其正確class的概率。關於softmax的知識在這裡就不多說了。我們來求Loss關於W, X和b的導數。為了簡便起見,下面所有的dxxx指的都是Loss對xxx的導數。

我們首先把Loss重新寫一下,把P代入進去:

Loss=\frac{1}{N}\Sigma_N(-score_{y_i}+ln\Sigma_ye^{score_y})

不要一步到位,我們把前面一部分和後面一部分分開看。設rowsum=\Sigma_ye^{score_y}, rowsum就是每一行的score指數和,因此是Nx1的,那麼就有

Loss=\frac{1}{N}\Sigma_{i=1}^N-score{y_i}+ln(rowsum_i)

先看dscore,其大小與score一樣,是NxC的。你會發現如果扔掉前面的1/N不看,dscore其實就是一堆0,然後在每一行那個正確的class那裡為-1;寫成python程式碼就是

dscore = np.zeros_like(score)
dscore[range(N),y] -= 1

然後看d(rowsum),其實就是\frac{1}{rowsum},非常簡單。

現在我們關注rowsum=\Sigma_ye^{score_y},需要注意的是我們不要直接求\frac{d(rowsum)}{dscore}是什麼,兩個都是矩陣,不好求;相反,我們求\frac{dL}{dscore}是多少。我們會發現上面我們求了一個dscore,這裡又求了一個dscore,這說明score這個矩陣參與了兩個運算,這是符合這裡Loss的定義的。求導法則告訴我們,當一個變數參與了兩部分運算的時候,把這兩部分的導數加起來就可以了。

這一部分的dscore就很好求了:

\frac{dL}{dscore}=\frac{dL}{d(rowsum)}\frac{d(rowsum)}{dscore},左邊是NxC的,右邊已知的是Nx1的,那麼剩下的有可能是1xC的,也有可能是NxC的。這個時候就要分析一下了。我們會發現右邊應該是NxC的,因為每一個score都隻影響一個rowsum的元素,因此我們不應該求和。NxC的矩陣就是e^{score}自己,所以我們就很容易得出:

dscore += drowsum.dot(np.exp(score))
dscore /= N #再把那個1/N給補上

這樣我們就完成了對score的求導,之後score對W, X和b的求導,相信你也就會了。

當然,如果你注意一下的話,你會發現其實第二部分的那個式子就是P矩陣。不過如果你沒有注意到這一點也無所謂,用這套方法也可以求出dscore是多少。

利用同樣的方法,現在看看那個卡住無數人的Batch Normalization層的梯度推導,是不是也感到不那麼困難了?

相關推薦

神經網路反向傳播梯度到底怎麼

相信每一個剛剛入門神經網路(現在叫深度學習)的同學都一定在反向傳播的梯度推導那裡被折磨了半天。在各種機器學習的課上明明聽得非常明白,神經網路無非就是正向算一遍Loss,反向算一下每個引數的梯度,然後大家按照梯度更新就好了。問題是梯度到底怎麼求呢?課上往往舉的是標量的例子,

神經網路反向傳播梯度計算數學原理

[神經網路]反向傳播梯度計算數學原理 1 文章概述 本文通過一段來自於Pytorch官方的warm-up的例子:使用numpy來實現一個簡單的神經網路。使用基本的數學原理,對其計算過程進行理論推導,以揭示這幾句神奇的程式碼後面所包含的原理。 估計對大多數的同學來說,看完這個文章,肯定會是這樣的感覺:字都

BP神經網路反向傳播演算法一步一步例項推導(Backpropagation Example)

1. loss 函式的優化 籠統來講: 設計loss函式是為了衡量網路輸出值和理想值之間的差距,儘管網路的直接輸出並不顯式的包含權重因子,但是輸出是同權重因子直接相關的,因此仍然可以將loss函式視作在權重因子空間中的一個函式。 可以將loss 記為E(w),這裡為

神經網路反向傳播,通俗理解

LR-----1層神經網路     dL/dz 簡稱dz_,L(a,y)使用交叉熵。       da_ = dL/da =  dz_ = dL/da * da/dz = da_* dw_ = dL/dz *dz/dw = dz

【手撕】神經網路反向傳播

神經網路前向傳播一般用於搭建整個神經網路的結構框架,形成整個網路的邏輯通路。反向傳播用於更新每層之間的權重,減少損失,進而提升預測準確度。 下面是一個神經網路的結構圖: 第一層是輸入層,包含兩個神經元i1,i2,和截距項b1;第二層是隱含層,包含兩個神經元h1,h2和截距項b2,第

神經網路反向傳播(BP)演算法原理

一.BP演算法簡介 BP演算法的學習過程由正(前)向傳播過程和反向傳播過程組成。 1.正向傳播 將訓練集資料輸入到ANN的輸入層,經過隱藏層,最後達到輸出層並輸出結果; 2.反向傳播 由於ANN的輸出結果與實際結果有誤差,則計算估計值與

神經網路二之神經網路反向傳播原理與python程式設計實現

技術交流qq群: 659201069 誤差   樣本資料的真實值與神經網路的輸出值之間的差值稱為誤差,當然一般不會直接使用直接的差值,常用的有迴歸演算法的均方差、分類的交叉熵,這方面不影響我們來討論神經網路的反向傳播原理與過程,所以不做過多討論。

人工神經網路——反向傳播演算法(BP)以及Python實現

人工神經網路是模擬生物神經系統的。神經元之間是通過軸突、樹突互相連線的,神經元收到刺激時,神經脈衝在神經元之間傳播,同時反覆的脈衝刺激,使得神經元之間的聯絡加強。受此啟發,人工神經網路中神經元之間的聯絡(權值)也是通過反覆的資料資訊"刺激"而得到調整的。而反向傳

卷積神經網路——反向傳播演算法

卷積神經網路(CNN)的結構可閱讀上一篇博文。CNN的基本層包括卷積層和池化層,二者通常一起使用,一個池化層緊跟一個卷積層之後。這兩層包括三個級聯的函式:卷積,求sigmoid函式(或使用其他激勵函式),池化。其前向傳播和後向傳播的示意圖如下: 

CNN卷積神經網路--反向傳播(2,前向傳播

 卷積層:卷積層的輸入要麼來源於輸入層,要麼來源於取樣層,如上圖紅色部分。卷積層的每一個map都有一個大小相同的卷積核,Toolbox裡面是5*5的卷積核。下面是一個示例,為了簡單起見,卷積核大小為2*2,上一層的特徵map大小為4*4,用這個卷積在圖片上滾一遍,得到一個一個(4-2+1)*(4-2+1)=3

神經網路-反向傳播

  最近在看深度學習的東西,一開始看的吳恩達的UFLDL教程,有中文版就直接看了,後來發現有些地方總是不是很明確,又去看英文版,然後又找了些資料看,才發現,中文版的譯者在翻譯的時候會對省略的公式推導過程進行補充,但是補充的又是錯的,難怪覺得有問題。反向傳播法其實是神經網路的基礎了,但是很多人在學的時候總是會遇

卷積神經網路反向傳播演算法

神經網路的訓練過程,就是通過已有的樣本,求取使代價函式最小化時所對應的引數。代價函式測量的是模型對樣本的預測值與其真實值之間的誤差,最小化的求解一般使用梯度下降法(Gradient Decent)或其他與梯度有關的方法。其中的步驟包括: 初始化引數。求代價函式關

用張量廣播機制實現神經網路反向傳播

### 正向傳播 要想了解反向傳播,先要了解正向傳播:正向傳播的每一步是,用一個或很多輸入生成一個輸出。 ### 反向傳播 反向傳播的作用是計算模型引數的偏導數。再具體一點,反向傳播的每一個step就是:已知正向傳播的輸入本身,和輸出的偏導數,求出每個輸入的偏導數的過程。 反向傳播既簡單,又複雜: * 它

AI應用開發基礎傻瓜書系列2-神經網路反向傳播梯度下降的基本概念

第二篇:神經網路中反向傳播與梯度下降的基本概念 預警:本篇部落格中會涉及到偏導數的概念,但是非常初級,很容易理解,建議硬著頭皮看,跟著算一遍,看完之後保證會覺得人生美好了很多。 反向傳播和梯度下降這兩個詞,第一眼看上去似懂非懂,不明覺厲。這兩個概念是整個神經網路中的重要組成部分,是和誤差函式/損失函式的概念

BP神經網路,BP推導過程,反向傳播演算法,誤差反向傳播梯度下降,權值閾值更新推導,隱含層權重更新公式

%% BP的主函式   % 清空   clear all;   clc;   % 匯入資料   load data;   %從1到2000間隨機排序   k=rand(1,2000);   [m,n]=sort(k);   %輸入輸出資料   input=data(:,2:25);   output1 =d

神經網路系列之二 -- 反向傳播梯度下降

系列部落格,原文在筆者所維護的github上:https://aka.ms/beginnerAI, 點選star加星不要吝嗇,星越多筆者越努力。 第2章 神經網路中的三個基本概念 2.0 通俗地理解三大概念 這三大概念是:反向傳播,梯度下降,損失函式。 神經網路訓練的最基本的思想就是:先“猜”一個結果,我們

反向傳播梯度下降的基本概念

反向傳播和梯度下降這兩個詞,第一眼看上去似懂非懂,不明覺厲。這兩個概念是整個神經網路中的重要組成部分,是和誤差函式/損失函式的概念分不開的。 神經網路訓練的最基本的思想就是:先“蒙”一個結果,我們叫預測結果h,看看這個預測結果和事先標記好的訓練集中的真實結果y之間的差距,然後調整策略,再試一次,這一次就不是

卷積網路反向傳播過程

池化層以後補充。 def conv_backward(dZ, cache): """ Implement the backward propagation for a convolution function Arguments:

斯坦福cs231n學習筆記(11)------神經網路訓練細節(梯度下降演算法大總結/SGD/Momentum/AdaGrad/RMSProp/Adam/牛頓法)

神經網路訓練細節系列筆記: 通過學習,我們知道,因為訓練神經網路有個過程: <1>Sample 獲得一批資料; <2>Forward 通過計算圖前向傳播,獲得loss; <3>Backprop 反向傳播計算梯度,這

機器學習與Tensorflow(5)——迴圈神經網路、長短記憶網路

  1.迴圈神經網路的標準模型 前饋神經網路能夠用來建立資料之間的對映關係,但是不能用來分析過去訊號的時間依賴關係,而且要求輸入樣本的長度固定 迴圈神經網路是一種在前饋神經網路中增加了分虧連結的神經網路,能夠產生對過去資料的記憶狀態,所以可以用於對序列資料的處理,並建立不同時段資料之間