深度学习入门笔记(三):求导和计算图
歡迎關注WX公眾號:【程序員管小亮】
專欄——深度學習入門筆記
聲明
1)該文章整理自網上的大牛和機器學習專家無私奉獻的資料,具體引用的資料請看參考文獻。
2)本文僅供學術交流,非商用。所以每一部分具體的參考資料并沒有詳細對應。如果某部分不小心侵犯了大家的利益,還望海涵,并聯系博主刪除。
3)博主才疏學淺,文中如有不當之處,請各位指出,共同進步,謝謝。
4)此屬于第一版本,若有錯誤,還需繼續修正與增刪。還望大家多多指點。大家都共享一點點,一起為祖國科研的推進添磚加瓦。
文章目錄
- 歡迎關注WX公眾號:【程序員管小亮】
- 專欄——深度學習入門筆記
- 聲明
- 深度學習入門筆記(三):求導和計算圖
- 0、寫在前面
- 1、導數
- 2、深入理解導數
- 3、計算圖
- 4、使用計算圖求導數
- 推薦閱讀
- 參考文章
深度學習入門筆記(三):求導和計算圖
0、寫在前面
這一次主要是想對微積分和導數直觀理解一下。很多人在想或許自從大學畢以后,再也沒有接觸微積分。不要擔心,為了高效應用神經網絡和深度學習,其實 并不需要非常深入理解微積分。
如果你是精通微積分的那一小部分人群,對微積分非常熟悉,可以跳過這個筆記。
1、導數
導數,也叫導函數值,又名微商,是微積分中的重要基礎概念,但是其實理解起來并沒有那么難。來看一個例子:
一個函數 f(a)=3af(a)=3af(a)=3a,如圖可以看出它是一條直線,這個別說你不會,xD。那么什么是導數,簡單理解一下:
看看函數中幾個點,假定 a=2a=2a=2,那么 f(a)=3af(a)=3af(a)=3a 是 aaa 的 3 倍,也就是 3 * 2 = 6,即若 a=2a=2a=2,那么函數 f(a)=6f(a)=6f(a)=6,第一個點就是(a,f(a))=(2,6)(a,f(a))=(2,6)(a,f(a))=(2,6)。
如果假定稍微改變一點點 aaa 的值,只增加一點,變為 2.001(只增加了 0.001),這時 aaa 將向右做微小的移動。0.001 的差別實在是太小了,10?310^{-3}10?3 數量級的移動,不能在圖中很明顯地看出來,這里稍稍夸張了一下,意思到位就ok。現在 f(a)=3af(a)=3af(a)=3a 等于 aaa 的 3 倍是 2.001 * 3 = 6.003。
請看這個綠色小清新的三角形!!!根據剛才的結果,如果向右移動 0.001,那么 f(a)f(a)f(a) 增加 6.003 - 6 = 0.003,f(a)f(a)f(a) 的值增加 3 倍于右移的 aaa,0.003 / 0.001 = 3,因此我們說函數 f(a)f(a)f(a) 在 a=2a=2a=2點的導數就是在這個點的斜率,而這個點的斜率是 3,那么斜率是什么?
已知一個圖如上,斜率 K 計算公式如下:
導數這個概念意味著斜率!!!導數 這個詞,聽起來就是一個很可怕、很令人驚恐的詞,但是 斜率 以一種很友好的方式來描述導數這個概念。所以提到導數,不嚴格的說,就把它當作函數的斜率就好了。通過一個例子來體會一下斜率的定義,在上圖的綠色三角形中,用三角形的高除以三角形的寬,即斜率等于 0.003 / 0.001 = 3,等于3,或者說導數等于 3。這意味著什么呢?這意味著當你將 aaa 右移 0.001時,f(a)f(a)f(a) 的值增加 3 倍水平方向的量。
如果換個數呢?現在假設 a=5a=5a=5 也是一樣的,此時 f(a)=3a=15f(a)=3a=15f(a)=3a=15。把 aaa 右移一個很小的幅度,增加到 5.001,根據 f(a)=3af(a) = 3af(a)=3a 可以得到 3 * 5.001 = 15.003。即在 a=5a=5a=5 時,斜率是 3。這就表示,當變量 aaa 的值發生微小改變時,df(a)da=3\frac{df(a)}{da}=3dadf(a)?=3。一個等價的導數表達式還可以這樣寫 ddaf(a)\fracze8trgl8bvbq{da}f(a)dad?f(a) ,即 f(a)f(a)f(a) 放在上面或者放在右邊都沒有關系,是一樣的。
那就是導數的正式定義!!!數學上導數用 f′(a)=df(a)daf'(a) = \frac{df(a)}{da}f′(a)=dadf(a)? 表示。
導數的一個特性是:這個例子中的這個函數在任何地方的斜率總是等于 3,不管 a=2a=2a=2 或 a=5a=5a=5,這個函數的斜率總等于3,也就是說導數總等于 3。那么所有的函數斜率都是不變的嘛?當然不是,下面這個例子中函數在不同點的斜率是可變的。
2、深入理解導數
下面來看一個更加復雜的例子,有多復雜?在這個例子中,函數在不同點處的斜率是不一樣的,別慌,先來舉個例子:
這里有一個不一樣的函數,f(a)=a2f(a)={{\text{a}}^{\text{2}}}f(a)=a2,直觀上看,是個曲線,眉頭一皺,感覺事情不太對勁。現在如果假設 a=2a=\text{2}a=2 的話,那么 f(a)=a2f(a)={{\text{a}}^{\text{2}}}f(a)=a2 可以得到 f(2)=22=4f(2) = 2^2 = 4f(2)=22=4。還是稍稍往右推進一點點,現在 a=2.001a=\text{2}.\text{001}a=2.001,則 f(a)≈4.004f(a)\approx 4.004f(a)≈4.004 (為什么要約等于?如果你用計算器算的話,就會發現這個準確的值應該為4.004001,只是為了簡便起見,省略了后面的部分)。
還是畫圖的方法進行理解,得到一個小三角形,如果細心的話你就會發現,這次嚴格意義上并不是三角形。如果把 aaa 往右移動 0.001,那么 f(a)f(a)f(a) 將增大四倍,即增大 4.004 - 4 = 0.004,而 0.004 / 0.001 = 4。
在微積分中,把這個三角形斜邊的斜率,稱為 f(a)f(a)f(a) 在點 a=2a=\text{2}a=2 處的導數(即為 4 );或者寫成微積分的正式定義形式,當 a=2a=\text{2}a=2 的時候, ddaf(a)=4\fracze8trgl8bvbq{da}f(a)=4dad?f(a)=4。由此可知,函數 f(a)=a2f(a)={{a}^{{2}}}f(a)=a2,在 aaa 取不同值的時候,它的斜率是不同的,這和上面的例子顯然是不同的。
如果你還是不太理解的話,這里有種直觀的方法可以解釋,就是畫圖法。為什么一個點的斜率,在不同位置會不同如果?我們可以在曲線上的不同位置,畫一些小小的三角形你就會發現,三角形高和寬的比值,即斜率,在曲線上不同的地方是不同的。所以當 a=2a=2a=2 時,斜率為 4;而當 a=5a=5a=5 時,斜率為 10。
如果嚴謹地說,可以百度導數表。你會發現,函數 f(a)=a2f(a)={{a}^{{2}}}f(a)=a2 的斜率(即導數)為 2a2a2a,而函數 f(a)=3af(a)=3af(a)=3a 的斜率(即導數)為3。
這意味著什么?這么說,如果任意給定一點 aaa,稍微將 aaa 增大 0.001,兩個函數增大的完全不一樣。一個是和 aaa 有關的,而另一個則是常數。
來小結一下:
導數就是斜率,而函數的斜率在不同的點可能是不同的。在 f(a)=3af(a)=\text{3}af(a)=3a 時,在任何點它的斜率都是相同的,均為3。但對 f(a)=a2f(a)={{\text{a}}^{\text{2}}}f(a)=a2,斜率是變化的,所以它們的導數或者斜率,在曲線上不同的點處是不同的。
如果想知道一個函數的導數,可參考導數表,然后應該就能找到這些函數的導數公式,直接帶數就完事了。
3、計算圖
一個神經網絡的計算大體上可以看成是,前向或反向傳播組合而成的。只有公式描述,確實有一些晦澀,這個時候我們想到了計算圖。計算圖是什么?
計算圖是一種描述方程的語言,既然是圖,則有 節點(變量) 和 邊(操作)。
這么說太官方了,來舉一個比邏輯回歸更加簡單的,或者說不那么正式的神經網絡的例子。
我們的目的是計算函數 JJJ,函數 JJJ 的組成是什么呢?是由三個變量 a,b,ca,b,ca,b,c 組成的函數,這個函數是 3(a+bc)\text{3(a}+\text{bc)}3(a+bc) 。計算這個函數實際上有三個不同的步驟,也就是拆分一下,用復合函數的思想去理解。
首先是計算 bbb 乘以 ccc,用一個函數 u=bc{u}={bc}u=bc 來表示;然后計算另一個函數 v=a+uv=a+uv=a+u;最后輸出 J=3vJ=3vJ=3v,這就是要計算的函數 JJJ。這三步可以畫成如下的計算圖:
先畫三個變量 a,b,ca,b,ca,b,c,第一步就是計算 u=bcu=bcu=bc,放個矩形框,它的輸入是 b,cb,cb,c;接著還是放個矩形框,進行第二步 v=a+uv=a+uv=a+u;最后一步還是個矩形框,進行 J=3vJ=3vJ=3v。
舉個例子:a=5,b=3,c=2a=5, b=3, c=2a=5,b=3,c=2 ,u=bcu=bcu=bc 就是 3 * 2 = 6;而 v=a+uv=a+uv=a+u,就是 5+6=11;JJJ 是 3 倍的 vvv ,因此,JJJ = 3 × (5 + 3 × 2)。如果把它算出來,就得到33,實際上就是 JJJ 的值。
計算圖的一個大優勢是:當有不同的或者一些特殊的輸出變量時,例如上面例子中的 JJJ 和邏輯回歸中準備優化的代價函數 JJJ,用計算圖來處理會很方便。從這個小例子中可以看出,通過一個從左向右(藍色箭頭)的過程,可以計算出 JJJ 的值。而為了計算導數,從右到左(紅色箭頭,和藍色箭頭的過程相反)的過程是用于計算導數最自然、最直觀的方式。
4、使用計算圖求導數
如何利用計算圖來計算函數 JJJ 的導數呢?
先不急,來看個例子,下面用到的公式:
dJdu=dJdvdvdu\frac{dJ}{du}=\frac{dJ}{dv}\frac{dv}{du}dudJ?=dvdJ?dudv?
dJdb=dJdududb\frac{dJ}{db}=\frac{dJ}{du}\frac{du}{db}dbdJ?=dudJ?dbdu?
dJda=dJdududa\frac{dJ}{da}=\frac{dJ}{du}\frac{du}{da}dadJ?=dudJ?dadu?
這是一個計算圖,記錄了整個流程:
假設計算 dJdv\frac{{dJ}}{{dv}}dvdJ?,那要怎么算呢?如果你會微積分的話,就好說了,直接求導數沒啥好說的;那么不會的話呢,也不用著急!這么看,比如要把這個 vvv 值拿過來,改變一下,那么 JJJ 的值會怎么變呢?(是不是用上了上面提到的導數講解 😃)
首先 J=3vJ = 3vJ=3v,v=11v=11v=11,J=33J=33J=33,這是已知條件。如果讓 vvv 增加一點點,比如到11.001,那么 J=3v=33.003J = 3v = 33.003J=3v=33.003,這里 vvv 增加了 0.001,而最終結果是 JJJ 上升了 0.003,也就是原來的 3 倍,所以 dJdv=3\frac{{dJ}}{{dv}}=3dvdJ?=3。
為啥這么說?當然是因為對于任何 vvv 的增量,JJJ 都會有 3 倍增量。所以有 J=3vJ=3vJ=3v,推出 dJdv=3\frac{{dJ}}{{dv}} =3dvdJ?=3。
吳恩達老師的手稿如下:
看另一個例子,dJda\frac{{dJ}}{da}dadJ? 是多少呢?換句話說,如果提高 aaa 的值,JJJ 的數值有什么影響?
變量 a=5a=5a=5,增加到了 5.001,那么對 vvv 的影響就是 a+ua+ua+u,之前 v=11v=11v=11,現在變成 5.001 - 5 + 11 = 11.001,JJJ 就變成11.001 * 3 = 33.003,所以 aaa 增加 0.001,JJJ 增加 0.003。那么增加 aaa,aaa 的改變量會傳播到計算圖的最右邊,所以 JJJ 最后是 33.003。所以 JJJ 的增量是 3 乘以 aaa 的增量,也就意味著導數是 3,即 dJda=3\frac{{dJ}}{da}=3dadJ?=3。
吳恩達老師的手稿如下:
要解釋清楚這個計算過程,就會牽扯出鏈式法則,名字雖然挺厲害的,其實很簡單。
首先 aaa 增加了,vvv 也會增加;vvv 增加多少呢?這取決于 dvda\frac{{dv}}{da}dadv?;然后 vvv 的增加導致 JJJ 也會增加。所以這在微積分里實際上叫鏈式法則,顧名思義,互相之間被鏈住了,一個變化都會變化。
那么怎么計算一個鏈式法則的求導呢?
其實不難,前面給了三個公式,這就是答案。通過分解的方法,把整個鏈式法則分解為幾個小的鏈子,分別求導再相乘,就解出正確答案了。
通過改變一個變量來看另一個變量的變化關系這種方法,我們得到了 dJdv=3\frac{{dJ}}{{dv}} =3dvdJ?=3、dvda=1\frac{{dv}}{da} =1dadv?=1,所以 dJda=dJdvdvda=3?1=3\frac{{dJ}}{da}=\frac{{dJ}}{{dv}} \frac{{dv}}{da}=3 * 1=3dadJ?=dvdJ?dadv?=3?1=3,即為所求。
下圖表示了整個計算過程:
繼續計算另一條線的導數,也就是這個 uuu,那么 dJdu\frac{dJ}{du}dudJ? 是多少呢?
通過和之前類似的計算,這里簡單說一下。從 u=6u=6u=6 出發,令 uuu 增加到 6.001,vvv 之前是 11,現在變成 6.001 - 6 + 11 = 11.001,JJJ 從 33 變成 33 * 3 = 33.003,所以 dJdu=3\frac{{dJ}}{du}= 3dudJ?=3。
對 uuu 的分析很類似對 a 的分析,為啥這么說呢?實際上還是計算,dJdu=dJdv?dvdu\frac{{dJ}}{du}=\frac{{dJ}}{dv}\cdot \frac{{dv}}{du}dudJ?=dvdJ??dudv?,又因為有 dJdv=3\frac{{dJ}}{dv} =3dvdJ?=3、dvdu=1\frac{{dv}}{du} = 1dudv?=1,最終算出的結果是 3×1=33×1=33×1=3,所以可以看出對 uuu 的分析類似對 a 的分析。
吳恩達老師的手稿如下:
現在,來看最后一個例子,那么 dJdb\frac{{dJ}}{db}dbdJ? 呢?
事實上,使用微積分鏈式法則,這也可以寫成乘積的形式,就是 dJdb=dJdu?dudb\frac{{dJ}}{db}=\frac{{dJ}}{du}\cdot \frac{{du}}{db}dbdJ?=dudJ??dbdu?。
當 bbb 增加 0.001 變成 3.001 時,u=bcu=bcu=bc 就變成 3.001 * 2 = 6.002,uuu 增加了 6.002 - 6 = 0.002,也就是 bbb 的增加量的二倍,所以 dudb=2\frac{{du}}{db} =2dbdu?=2。那么 dJdu\frac{{dJ}}{du}dudJ? 是多少呢?在前面我們已經弄清楚了,等于 3,所以這兩部分相乘,可得 dJdb=6\frac{{dJ}}{db}= 6dbdJ?=6。
其實還有另一個例子,不過 ccc 和 bbb 是比較相似的。經過計算你會發現 dJdc=dJdu?dudc=3×3\frac{{dJ}}{dc} =\frac{{dJ}}{du}\cdot \frac{{du}}{dc} = 3 \times 3dcdJ?=dudJ??dcdu?=3×3,這個結果是 9。
吳恩達老師的手稿如下:
所以當計算所有這些導數時,最有效率的辦法是從右到左計算,跟著這個紅色箭頭走,充分利用計算圖的優勢。特別是當第一次計算對 vvv 的導數時,之后在計算對 aaa 導數時,然后對 uuu 的導數,最后是對 bbb 和 ccc 的導數。
到這里,計算圖求導數就完事了。這是一個計算圖,也是一個流程圖。是不是簡單了好多,尤其是對 bbb 和 ccc 的導數!!!
推薦閱讀
- 深度學習入門筆記(一):深度學習引言
- 深度學習入門筆記(二):神經網絡基礎
- 深度學習入門筆記(三):求導和計算圖
- 深度學習入門筆記(四):向量化
- 深度學習入門筆記(五):神經網絡的編程基礎
- 深度學習入門筆記(六):淺層神經網絡
- 深度學習入門筆記(七):深層神經網絡
- 深度學習入門筆記(八):深層網絡的原理
- 深度學習入門筆記(九):深度學習數據處理
- 深度學習入門筆記(十):正則化
- 深度學習入門筆記(十一):權重初始化
- 深度學習入門筆記(十二):深度學習數據讀取
- 深度學習入門筆記(十三):批歸一化(Batch Normalization)
- 深度學習入門筆記(十四):Softmax
- 深度學習入門筆記(十五):深度學習框架(TensorFlow和Pytorch之爭)
- 深度學習入門筆記(十六):計算機視覺之邊緣檢測
- 深度學習入門筆記(十七):深度學習的極限在哪?
- 深度學習入門筆記(十八):卷積神經網絡(一)
- 深度學習入門筆記(十九):卷積神經網絡(二)
- 深度學習入門筆記(二十):經典神經網絡(LeNet-5、AlexNet和VGGNet)
參考文章
- 吳恩達——《神經網絡和深度學習》視頻課程
總結
以上是生活随笔為你收集整理的深度学习入门笔记(三):求导和计算图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [UOJ]#36. 【清华集训2014】
- 下一篇: 任正非谈接班人要求:要具有对新技术与客户