您當前的位置是:  首頁 > 新聞 > 專家觀點 >
 首頁 > 新聞 > 專家觀點 >

李理:自動梯度求解 反向傳播算法的另外一種視角

2016-12-14 16:19:09   作者:   來源:CTI論壇   評論:0  點擊:


  本系列文章面向深度學習研發(fā)者,希望通過ImageCaptionGeneration,一個有意思的具體任務(wù),深入淺出地介紹深度學習的知識。本系列文章涉及到很多深度學習流行的模型,如CNN,RNN/LSTM,Attention等。本文為第四篇。
  作者:李理
  目前就職于環(huán)信,即時通訊云平臺和全媒體智能客服平臺,在環(huán)信從事智能客服和智能機器人相關(guān)工作,致力于用深度學習來提高智能機器人的性能。
  相關(guān)文章:
  前面我們講過了反向傳播算法的詳細推導(dǎo)過程,大家可能會覺得有些復(fù)雜。事實上其實就是鏈式求導(dǎo)法則的應(yīng)用。今天我們將會繼續(xù)討論這個問題,不過是從Computational Graphs的角度,也就是我們之前說過的自動求導(dǎo)(Automatic Differentiationor Reverse-mode Differentiation)。并且通過CS231n的Assignment2來學習使用這種方法,通過這種方法來實現(xiàn)一個多層的神經(jīng)網(wǎng)絡(luò)。
  Calculus on Computational Graphs:Backpropagation
  首先我們介紹一篇博客文章:https://colah.github.io/posts/2015-08-Backprop/基本是翻譯過來,不過部分地方是我自己的理解,建議讀者結(jié)合這篇文章一起閱讀。
  簡介
  反向傳播算法是神經(jīng)網(wǎng)絡(luò)的核心算法,不過這個算法在不同的領(lǐng)域被多次”發(fā)現(xiàn)“過,因此有不同的名稱。
  計算圖(Computational Graphs)
  考慮一個簡單的函數(shù)e=(a+b)∗(b+1)e=(a+b)∗(b+1)。這個函數(shù)有兩個操作(函數(shù)),加法和乘法。為了指代方便,我們引入兩個中間變量,c和d。
  c=a+b
  d=b+1
  e=c*d
  下面我們把它畫成一個計算圖,每一個操作是圖中一個節(jié)點,最基本的變量a和b也是一個節(jié)點。每個節(jié)點和它的輸入變量直接有一條邊。比如d的輸入變量是b,那么d和b直接就有一條邊。
  任何一個顯示定義的函數(shù)(隱函數(shù)不行,不過我們定義的神經(jīng)網(wǎng)絡(luò)肯定不會通過隱函數(shù)來定義)都可以分解為一個有向無環(huán)圖(樹),其中葉子節(jié)點是最基本的無依賴的自變量,而中間節(jié)點是我們引入的中間變量,而樹根就是我們的函數(shù)。比如上面的例子,計算圖如下所示:
\
  給定每一個自變量的值,我們可以計算最終的函數(shù)值,對應(yīng)與神經(jīng)網(wǎng)絡(luò)就是feedforward計算。具體用”算法“怎么計算呢?首先因為計算圖是一個有向無環(huán)圖,因此我們可以拓撲排序,先是葉子節(jié)點a和b,他們的值已經(jīng)給定,然后刪除a和b出發(fā)的邊,然后c和d沒有任何未知依賴,可以計算,最后計算e。計算過程如下圖:
\
  計算圖的導(dǎo)數(shù)計算
  首先我們可以計算每條邊上的導(dǎo)數(shù),也就是邊的終點對起點的導(dǎo)數(shù),而且導(dǎo)數(shù)是在起點的取前向計算值時的導(dǎo)數(shù),具體過程如圖所示:
\
  有些邊的導(dǎo)數(shù)不依賴于輸入的值,比如:
\
  但是還有很多邊的導(dǎo)數(shù)是依賴于輸入值的,比如:
\
  因為在“前向”計算的過程中,每個節(jié)點的值都計算出來了,所以邊的計算很簡單,也不需要按照什么的順序。
  不過我們一般比較感興趣的是最終函數(shù)對某個自變量的導(dǎo)數(shù),比如
\
  根據(jù)鏈式法則,只要找到這兩個節(jié)點的所有路徑,然后把路徑的邊乘起來就得到這條邊的值,然后把所有邊加起來就可以了。
  比如上面的例子b到e有兩條路徑:b->c->e和b->d->e,所以
\
  如果用“鏈式”法則來寫就是
\
  路徑反過來而已。
  使用上面的方法,我們可以計算任何一個點(上面的變量)對另外一個點(上面的變量)的導(dǎo)數(shù)。不過我們一般的情況是計算樹根對所有葉子的導(dǎo)數(shù),當然我們可以使用上面的算法一個一個計算,但是這樣會有很多重復(fù)的計算。
  比如a->e的路徑是a->c->e,b->e有一條邊是b->c->e,其中c->e是重復(fù)的【這個例子不太好,我們可以想像c->e是一條很長的路徑】,每次都重復(fù)計算c->e這個“子”路徑是多余的。我們可以從后往前計算,也就是每個節(jié)點都是存放樹根變量(這個例子是e)對當前節(jié)點的導(dǎo)數(shù)(其實也就是樹根到當前節(jié)點的所有路徑的和)。
  反向?qū)?shù)計算
\
  計算流程文字描述如下:
  首先還是對這個圖進行拓撲排序,不過是反過來。
  首先是
\
  這個沒什么好說的。
  然后計算
\
  然后計算
\
  然后計算
\
  計算
\
  前向?qū)?shù)計算
  如果我們需要計算每一個變量對某一個變量的導(dǎo)數(shù),就可以使用前向計算的方法。不過我們的神經(jīng)網(wǎng)絡(luò)都是相反——計算某個一個變量(一般是損失函數(shù))對所有變量的導(dǎo)數(shù),所以這里就不詳細介紹了。
  至此,本系列文章的第四部分告一段落。在接下來的文章中,作者將為大家詳細講述關(guān)于Optimization、常見的深度學習框架/工具的使用方法、使用自動求導(dǎo)來實現(xiàn)多層神經(jīng)網(wǎng)絡(luò)等內(nèi)容,敬請期待。

專題