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