前言
這幾天的文章會是一系列的,會需要一起看才比較能看懂整個ML模型的輪廓,
然而因為一天能寫的內容量有限,所以我會在前言部分稍微說明我寫到哪。
複習一下ML的整個訓練過程
因為ML模型的訓練階段章節內容會分很多部分,我們要先確認好自己在哪個階段,
以免吸收新內容卻不知道用在內容的什麼地方。
★ML的整個「訓練過程」:這裡以「監督式學習(Supervised Learning)」為例
| 階段 | 要做的事情 | 簡介 |
|---|---|---|
| 訓練前 | 決定資料集與分析資料 | 你想要預測的是什麼資料? 這邊需要先知道 「example」、「label」、「features」的概念。介紹可參考:[【Day 15】](https://ithelp.ithome.com.tw/articles/10215499),而我們這次作為範例的訓練資料集介紹在[【Day 19】](https://ithelp.ithome.com.tw/articles/10217666)。 |
| 訓練前 | 決定問題種類 | 依據資料,會知道是什麼類型的問題。「regression problem(回歸問題)」? 「classification problem(分類問題)」? 此處可參考:[【Day 16】](https://ithelp.ithome.com.tw/articles/10216585)、與進階內容:[【Day 17】](https://ithelp.ithome.com.tw/articles/10215946) |
| 訓練前 | 決定ML模型(ML models) | 依據問題的種類,會知道需要使用什麼對應的ML模型。「回歸模型(Regression model)」? 「分類模型(Classification model)」? 此處可參考:[【Day 18】](https://ithelp.ithome.com.tw/articles/10217431),「神經網路(neural network)」? 簡介於:[【Day 25】](https://ithelp.ithome.com.tw/articles/10221227) |
| (模型裡面的參數) | ML模型裡面的「參數(parameters)」與「超參數(hyper-parameters)」 此處可參考:[【Day 18】](https://ithelp.ithome.com.tw/articles/10217431) | |
| 訓練中 - 調整模型 | 評估當前模型好壞 | 「損失函數(Loss Functions)」:使用損失函數評估目前模型的好與壞。以「MSE(Mean Squared Error)」, 「RMSE(Root Mean Squared Error)」, 「交叉熵(Cross Entropy)」為例。此處可參考:[【Day 20】](https://ithelp.ithome.com.tw/articles/10218158) |
| 訓練中 - 調整模型 | 修正模型參數 | 以「梯度下降法 (Gradient Descent)」為例:決定模型中參數的修正「方向」與「「步長(step size)」」此處可參考:[【Day 21】](https://ithelp.ithome.com.tw/articles/10218980) |
| 訓練中 - 調整腳步 | 調整學習腳步 | 透過「學習速率(learning rate)」來調整ML模型訓練的「步長(step size)」,調整學習腳步。(此參數在「訓練前」設定,為「hyper-parameter」)。此處可參考:[【Day 22】](https://ithelp.ithome.com.tw/articles/10219458) |
| 訓練中 - 加快訓練 | 取樣與分堆 | 設定「batch size」,透過「batch」從訓練目標中取樣,來加快ML模型訓練的速度。(此參數在「訓練前」設定,為「hyper-parameter」)。與「迭代(iteration)」,「epoch」介紹。此處可參考:[【Day 23】](https://ithelp.ithome.com.tw/articles/10219945/draft) |
| 訓練中 - 加快訓練 | 檢查loss的頻率 | 調整「檢查loss的頻率」,依據「時間(Time-based)」與「步驟(Step-based)」。此處可參考:[【Day 23】](https://ithelp.ithome.com.tw/articles/10219945/draft) |
| 訓練中 - 完成訓練 | (loop) -> 完成 | 重覆過程(評估當前模型好壞 -> 修正模型參數),直到能「通過「驗證資料集(Validation)」的驗證」即可結束訓練。此處可參考:[【Day 27】](https://ithelp.ithome.com.tw/articles/10222043) |
| 訓練後 | 訓練結果可能問題 | 「「不適當的最小loss?」」 此處可參考:[【Day 28】](https://ithelp.ithome.com.tw/articles/10222317) |
| 訓練後 | 訓練結果可能問題 | 「欠擬合(underfitting)」?「過度擬合(overfitting)」? 此處可參考:[【Day 26】](https://ithelp.ithome.com.tw/articles/10221245) |
| 訓練後 | 評估 - 性能指標 | 「性能指標(performance metrics)」:以「混淆矩陣(confusion matrix)」分析,包含「「Accuracy」」、「「Precision」」、「「Recall」」三種評估指標。簡介於:[【Day 28】](https://ithelp.ithome.com.tw/articles/10222317)、詳細介紹於:[【Day 29】](https://ithelp.ithome.com.tw/articles/10222697) |
| 訓練後 | 評估 - 新資料適用性 | 「泛化(Generalization)」:對於新資料、沒看過的資料的模型適用性。此處可參考:[【Day 26】](https://ithelp.ithome.com.tw/articles/10221245) |
| 訓練後 | 評估 - 模型測試 | 使用「「獨立測試資料集(Test)」」測試? 使用「交叉驗證(cross-validation)」(又稱「bootstrapping」)測試? 此處可參考:[【Day 27】](https://ithelp.ithome.com.tw/articles/10222043) |
| (資料分堆的方式) | 訓練前 - 依據上方「模型測試」的方法,決定資料分堆的方式:訓練用(Training)、驗證用(Validation)、測試用(Test)。此處可參考:[【Day 27】](https://ithelp.ithome.com.tw/articles/10222043) |
而今天的文章我們就要來介紹所謂的「梯度下降法 (Gradient Descent)」
與ML模型中參數的修正「方向」與「步長(「step size」)」概念。
Course - Launching into Machine Learning
第三章節的課程地圖:「(紅字標記為本篇文章中會介紹到的章節)」
- 「Optimization」
- Introduction to Optimization
- Introduction
- Defining ML Models
- Defining ML Models
- Introducing the Natality Dataset
- Introducing Loss Functions
- 「Gradient Descent」
- 「Gradient Descent」
- Troubleshooting a Loss Curve
- ML Model Pitfalls
- TensorFlow Playground
- Lab: Introducing the TensorFlow Playground
- Lab: TensorFlow Playground - Advanced
- Lab: Practicing with Neural Networks
- Loss Curve Troubleshooting
- Performance Metrics
- Performance Metrics
- Confusion Matrix
- Module Quiz
- Introduction to Optimization
1. Gradient Descent
課程地圖
- Optimization
- Gradient Descent
- Gradient Descent
- Gradient Descent
在昨天的章節中,我們介紹了「損失函數(loss function)」的計算方式,
然而「損失函數loss function」只能「告訴我們參數的好壞」,
我們仍需要一個「修改參數的方法」,
今天我們要介紹的「梯度下降法 (Gradient Descent)」,就是一種「修改參數的方法」。
自己的註1:
「損失函數(loss function)」是判斷誤差大小的計算方法,然而還需要一個「修改參數的方法」。像這邊介紹的「梯度下降法 (Gradient Descent)」就是一個基於「損失函數(loss function)」的值去「修改參數的方法」。
自己的註2:
現在機器學習可使用於「修改參數的方法」有非常多種,然而這邊只介紹最經典的「梯度下降法 (Gradient Descent)」,仍有其他好的「修改參數的方法」可以使用。

「梯度下降法 (Gradient Descent)」,是一種「搜尋參數的策略」,
他是在一個參數空間中的每個點所代表的loss上,沿著表面往下走的過程,如上圖。
自己的註:
我們從上一節可以知道一個點表示一組參數,而一組參數能算出一個loss值(代表誤差多少),
我們可以將這個「loss值的計算結果」想像成「山的高度」,而對應位置就是參數的點,
就能夠畫出像上圖的等高線圖。

然而我們通常不可能把所有的loss都計算出來,我們頂多知道要評估哪個點時,
才會去計算那一個點的loss,例如說我們可能只知道像上圖的兩個點。
但即使如此,我們仍然要知道接下來我們要往哪裡移動,才能找到最小值。
自己的註:
還記得「最小化loss」是我們的訓練目標嗎?
另外我們所謂的「修正模型參數」,也就等同於「修正點的位置」,
那「最小的loss」會在這個像山的圖的哪邊呢?
當然是山谷的地方,所以上面才說「梯度下降法」像是「沿著表面往下走的過程」。

我們把這個問題稍微拆解成兩個不同卻同樣重要的問題。
- 我應該往哪個方向移動?
- 我應該要走多遠?
現在我們先做個簡單的假設,我們先「固定我們走一步的移動距離」,
「走一步的移動距離」又稱為,我們只討論我們「該往哪個方向移動」。

而這使得我們能得到上述的簡單演算法。
當 loss > 某一個很小的常數(epsilon)時,我們先計算方向,
然後對於模型中的參數(parameter),
設定新的值為我們現在的點加上【往我們要的方向「走幾步」乘上「步長(「step size」)」】,
然後針對新的點計算新的loss。

我們可以用地形圖或等高線圖的概念去想,
等高線上的每一條線代表一定的深度。
線與線的距離越近,表示那段越陡峭。
就像上面這張圖的每一個點,我們可以從點與點之間看出點移動的方式。
這就是一個從頂部邊緣開始漸漸往下走,直到走到最終的最小值。
另外一個可以注意的點是:因為我們現在固定步長(「step size」),所以每個點之間的距離是一樣的。
我們再來試著想一個問題,如果步長(「step size」)太小,我們的訓練會花很多時間。
但我們還是能夠保證能找到「可能的最小值」,
這裡會說是「可能的最小值」是因為「最小值可能不只一個」,後面我們會再討論。
自己的註1:
如果步長(「step size」)太小,我們的訓練會花很多時間。
這句話也可以想像為走一步的距離小,走道目標的時間就會長。
自己的註2:
另外「最小值可能不只一個」,是因為這張圖只有一個山谷。
但想想現實生活中的山谷也應該不是只有一個吧? 這裡也是一樣的。

(如上面這張圖,從開始點到走到山谷,步長(「step size」)越小,到山谷花的時間自然就要越長)

既然我們說步長(「step size」)越小,花的時間越長,
那我們走大步一點總會比較快了吧? 然而事情也沒有這麼順利。
如果步長(「step size」)太大,你有可能從loss表面的其中一面甚至直接跳到另外一面,
甚至有可能整個直接跳出這個山谷中,然後到了全新未知的地方,如上圖。
因為這個原因,步長(「step size」)太大,很有可能導致ML模型模辦法收斂。
自己的註1:
可以想像成,人走一個超級大步,連山谷都跨出去都有可能的那麼大步。(現實中可能有點扯啦XD)
可以想像成巨人之類的XDDD,總之太大步也不行,
有可能直接跨出山谷,或跨到山谷的另外一面。
自己的註2:
這裡突然提到「收斂」一詞,其實我們確實在找谷底的過程就是在做「收斂」的動作,
「當抵達谷底時」=「收斂完成」=「找到最小的loss」=「完成學習目標」
不能收斂的原因就是跟上面所說一樣,走太大步了! 谷底都被跨過了! 找不到谷底了!

從上面的例子我們就可以知道,我們應該要指定一個剛剛好的步長(「step size」),
不可以太大、也不可以太小。
但想要找到這個剛剛好的值,似乎是沒那麼容易?

我們觀察左邊的圖與右邊的圖,
我們都給這兩張圖設定一樣的步長(「step size」),
- 左邊的圖沒問題。
- 但在右邊的圖中,一開始的移動也許還可以,但我們看到在接近山谷時,
這個我們設定的步長卻讓他一腳跨過了山谷,造成了訓練失敗。
所以從上面例子我們知道一個固定的步長(「step size」),
似乎沒辦法適用於所有的ML模型,那我們該怎麼改變步長(「step size」)呢?

我們這裡用一些斜率與曲線變化的速率,
使我們對步長(「step size」)與方向(「direction」)更有概念。
我們看上圖,圖下方表示圖上方圖曲線(此曲線就是loss的變化曲線)的各點斜率值,
我們發現值較大的地方通常比值較小的地方離底部更遠。
自己的註:
(這裡的值指的是絕對值之後的值,也就是說下圖負越多或正越多離底部越遠。)
- 如果「斜率值越小」,表示我們「快要到底部了」(「要走一小步」)
- 如果「斜率值越大」,表示我們「離底部還很遠」(「要走一大步」)
另外再注意:
- 如果「斜率是負」,表示我們的「「谷底在右手邊」(「向右找最小值」)
- 如果「斜率是正」,表示我們的「谷底在左手邊」(「向左找最小值」)

我們換一個點看,例如點B,
他有「「正的斜率」」,告訴我們要「「向左找最小值」」,
另外他的「「斜率值很大」」,告訴我們「「要走一大步」」。

我們再換另一個點看,例如點C,
他有「「正的斜率」」,告訴我們要「「向左找最小值」」,
另外他的「「斜率值很小」」,告訴我們「「要走一小步」」,以避免走過頭。

我們現在就將我們的一開始所說的「固定的步長(「step size」)」,
用一個新函數「computeDerivative」來取代掉,
同時這個函數也能夠同時替我們決定「要前進的方向(derivative)」
我們將原本的點減掉「loss值的偏微分」,以獲得新的點。
自己的註:
也就是說,我們對loss值偏微分,依照剛剛上面的概念,
我們能同時獲得「應該前進的方向」與「要走多遠」。
啊對了,這方法就叫做「梯度下降法 (Gradient Descent)」,
這邊就已經介紹完了XDD,梯度就是指「loss的偏微分」,下降就是「找谷底」。
「loss的偏微分」:y是「loss值」,偏微的對象x是所有模型內的參數(「parameter」),
可以參考更上方的二維圖:「y反應loss值的大小,而x反應的是參數所在位置。」
而上圖中的點也可以注意他的變化:「該走快時走很快,該走慢時走很慢,且走的方向很正確。」
我們似乎找到了一個非常好的方法,
他能幫我們找到合適的步長(「step size」)與要前進的方向(direction),
但這樣就沒有問題了嗎?
以經驗來說,ML的種種問題集之中,我們所能建的loss表面,
這個算法通常會花費較多的時間,可能會找到次小值而非最小值,甚至是沒有完成。
自己的註:
- 「「花費較多的時間」」:「梯度下降法 (Gradient Descent)」相對比較新的算法來說,確實較慢,但並非不能用(下面也有提到XD)
- 「「找到次小值而非最小值」」:這確實是常見問題,我們可以想像等高線上有很多山谷,我們從找到第一個點時,就會開始往一個山谷的谷底直直前進。然而,如果這個山谷不是全部山谷最深的,那我們就找不到最深的山谷。不過目前也已經有新方法能解決這個搜索的問題。
- 「「沒有完成」」:有時候花費時間太長,而且特別是在接近底部的時候,可以想像一個問題,我們在做「y = 1/x」的畫圖時,那種趨近x軸卻永遠碰不到x軸的感覺(y無限接近0, x無限增加),收斂的感覺也很像這樣,一直無限接近,但遲遲沒有到。
但「梯度下降法 (Gradient Descent)」仍然是一個常被使用的方法,
這也表示像上述可能會出現問題的資料集,我們往往很少會碰到。
本文同步發佈在: 第 11 屆 iT 邦幫忙鐵人賽
【Day 21】 Google ML - Lesson 7 - 梯度下降法 (Gradient Descent)介紹,使用「梯度下降法」決定ML模型中參數修正的「方向」與「步長(step size)」
參考資料
coursera - Launching into Machine Learning 課程
若圖片有版權問題請告知我,我會將圖撤掉
