Deep Learning 基本功:Gradient Descent 介紹

1 前言
在〈Deep Learning 原理:Neural Network 如何分類圖像〉一文中,我們以「手寫數字圖像」的分類問題為例,站在 Neural Network 的角度感受它如何理解一張圖像。接著我們也知道,Neural Network 要靠以下 3 個元素來調整內部的參數 (weight 與 bias),讓輸出愈來愈接近正確答案:
- 訓練資料集 (Training Dataset)
- 損失函數 (Cost Function)
- 最佳化演算法 (Optimizer)
前兩個元素在Deep Learning 基本功:認識 MNIST 資料集與損失函數一文中已經介紹過,本文要談的是第三個元素:最佳化演算法 (Optimizer),而且是其中最基本、也最重要的一種——Gradient Descent。讀完本文,你會知道 Gradient Descent 到底在做什麼、它背後的數學長什麼樣子,以及 Learning Rate 在裡面扮演什麼角色。
- 訓練 Neural Network 的本質:調整參數 (w 與 b),使得 Cost Function 的數值變小。
- Gradient Descent 的比喻:我們是一顆停在山壁上的球,看不到谷底,只能感受附近哪個方向是下坡,然後往那走一步、再走一步。
- (Gradient Vector) 決定每個參數的「移動方向」, (Learning Rate) 決定「移動的大小」,兩者缺一不可。
- Learning Rate 是 Hyperparameter:太大會跨過頭讓 Cost 反而變大,太小則要走非常多步才會到谷底。
2 訓練 Neural Network 到底在訓練什麼
在進入演算法之前,先把「訓練」這件事講清楚。訓練 Neural Network,說白了就是把網路裡的參數 (weight 與 bias) 調整到一組好的數值,讓網路的輸出愈接近正確答案愈好。
那「好」與「不好」怎麼衡量?靠的就是 Cost Function。

Cost Function 會把「目前這組參數表現得如何」濃縮成一個數字:值愈小,代表網路的輸出愈接近正確答案。所以訓練 Neural Network 的過程,其實就是調整 w (weight) 與 b (bias),使得 C (Cost Function) 的值最小。
一句話總結:訓練 Neural Network ⇒ 調整參數 (w 與 b),使得 Cost Function 變小。
問題來了,該怎麼調整 w 與 b,才能讓 Cost Function 愈來愈小?這就要靠 Gradient Descent 這個演算法。
3 先用「山谷」與「球」理解 Gradient Descent
為了把概念講清楚,我們先把問題簡化。暫時忘掉 Neural Network、Cost Function、weight 與 bias 這些名詞。
現在手上只有一個函數 ,其中 ,表示 C 這個函數可以接受任意數量的參數。目標很單純:透過 Gradient Descent 調整每一個 v,讓 的值愈來愈小。
為了方便視覺化,我們假設 C 只接受兩個參數 與 ,也就是 。輸入不同的 與 會得到不同的數值,如果把所有 的情況都畫出來,這些點會在 3 維空間中形成一個面:

單看上面這張圖,你大概一眼就能看出最小值在哪裡。但實務上一個 Neural Network 動輒好幾千萬個參數,不可能這樣用眼睛看出來。這正是 Gradient Descent 派上用場的地方。
在講數學之前,先換個更貼近真實世界的角度:把 函數想成一座「山谷」,而我們自己是山谷上的一顆「球」。球會怎麼移動?當然是沿著山壁往下滾,直到滾進谷底才停下來。

這裡的眉角是:我們是一顆停在山壁上的球,而這座山谷地勢錯綜複雜(如上圖),我們看不到谷底在哪裡,只知道自己「目前所在位置」附近的地勢怎麼變化。
既然如此,要抵達谷底就只能靠一個土法煉鋼的辦法:感受一下四面八方哪個方向是「下坡」,朝那個方向走一步;到了新位置後,再感受一次哪個方向是下坡,再走一步……如此反覆,直到四面八方都是平地、找不到下坡方向為止。那時我們就在谷底了。
4 Gradient Descent 的數學
有了「山谷與球」的比喻,接著把數學補上。這裡不會深入到數學系的程度,只需要一點偏微分的概念就夠了。
回到剛剛的 。球的起始位置落在哪裡,取決於 與 的初始數值。因為我們把自己當成球,看不到整座山谷的全貌,也就看不到 的最低點在哪,只能看到所處位置的狀態。
假設我們已經決定要往某個方向前進(用向量 表示),可以把這一步拆成先朝 方向移動 、再朝 方向移動 ,也就是 (T 是 Transpose 的意思)。
朝 走一步之後, 的變化量稱為 ,可以寫成下面這個算式:

偏微分的概念在Perceptron 的改良版:了解什麼是 Sigmoid Neuron一文中介紹過,這裡可以簡單把它視為:一個多變數函數對於某一個獨立變數的「改變率」。舉例來說,當 加上 5 時 (),對 C 的影響不一定就是加上 5 ( 不一定等於 5),而是要再乘上 C 對 的改變率( 變動 1 時,C 變動多少)。
接著,我們把 算式中偏微分的部分抽出來,給它一個新符號 ,稱為「Gradient of C」:

第一次看到 這個符號不用緊張。 通常用來表示 Gradient Vector,而 Gradient Vector 也不是什麼了不起的東西,就是一個向量,裡頭每一個元素都是一個偏微分(函數對某個特定參數的微分)。
有了 與 ,原來的 算式就可以改寫成:

從這個算式可以看得更清楚:(函數的變化量)取決於 (每一個參數的變動量)與 (每一個參數變動一單位時對 C 造成的影響)兩者相乘。
別忘了我們的目的。我們是一顆球,希望移動 之後 的數值變小,也就是 。那要怎麼挑 ?只要設定:
代入後會得到 。因為 一定大於等於 0,所以 一定小於等於 0——這一步保證不會走上坡。
到這裡,我們已經知道每一步該怎麼走了。當球目前位於 v,要移動到新位置 v’:

依照這個規則,每要移動一步就重新計算一次 (Gradient Vector),每移動一次 就變小一點。一步一步走下去,直到抵達谷底,也就是 的最小值。這整個過程就叫做 Gradient Descent。
5 η (Learning Rate) 是什麼
上面的算式裡還有一個符號沒交代:。 在機器學習中代表 Learning Rate。
要理解 Learning Rate 的意義,先回頭看 (也就是前面提到的 Gradient Vector)在做什麼。 裡記錄的是函數對各參數的偏微分;在 C 只有一個參數 v 的情況下,其實就是在算切線斜率,而斜率告訴我們每個參數該往哪個方向移動。如果 C 對 v 的偏微分是「負值」,代表 v 變大時 C 會「減少」;如果偏微分是「正值」,代表 v 變大時 C 會「增加」。
所以分工很清楚: 決定每一個參數的「移動方向」, (Learning Rate) 決定「移動的大小」。
在 Deep Learning 中屬於一種超參數 (Hyperparameter),意思是它必須由我們自己設定、自己調整,沒辦法透過 Neural Network 的學習過程自動調出來。
而設定 Learning Rate 的數值也是一門學問,兩個方向都會出問題:
- Learning Rate 太大:v 一次改變太多,某些情況下反而會讓 大於 0,C 函數的數值愈跑愈大。用山谷的比喻來說,就是一步跨太大,直接從這側山壁跨到對面山壁上去了。
- Learning Rate 太小:v 每次只改變一點點,雖然方向沒錯,但要花非常多步、非常多時間才走得到最小值。
6 Gradient Descent:從兩個變數到多個變數
前面都是用兩個變數的 在說明。實際的 Neural Network 當然沒這麼單純,但好消息是:如果上面的內容你都懂了,那 Gradient Descent 如何應用在 Deep Learning 上,你其實也已經懂了。
差別只在於變數變多:兩個變數的 Cost Function 換成多個變數的 。當我們移動 後,一樣會產生 的改變,兩者的關係也跟前面完全相同:

只不過現在的 包含了更多元素:, 也同樣從兩個元素變成了多個:

在兩個變數的例子中,我們每一步都選 ;在多個變數的情況下,一樣這樣選,也一樣用前面那條規則更新 v,讓 Cost Function 的數值愈來愈小。整套邏輯完全沒變,只是向量變長了而已。
7 結論
本文介紹了 Gradient Descent 的觀念。說穿了,Gradient Descent 就是透過計算一個函數的 Gradient Vector,得知參數的更新方向,讓函數的數值愈來愈小。
我們也談到 Learning Rate:它是一種必須事先設定好的超參數 (Hyperparameter)。計算 Gradient 讓我們掌握參數的「更新方向」,Learning Rate 則讓我們決定參數的「更新大小」,兩者缺一不可。
理解了 Gradient Descent 之後,下一篇文章會接著說明它在實務上的變形:Stochastic Gradient Descent。