【Pytorch 深度學習筆記】機器如何學習

哈囉大家好我是 LukeTseng,感謝您點進本篇筆記,該篇筆記主要配合讀本 《Deep Learning with pytorch》 進行學習,另外透過網路資料作為輔助。本系列筆記是我本人奠基深度學習基礎知識的開始,若文章有誤煩請各位指正,謝謝!

本篇為 《Deep Learning with pytorch》 這本書第五章 The mechanics of learning 的相關筆記。

學習僅是參數估計(Learning is just parameter estimation)

在書中的章節 5.2,所想表達的是:所謂學習,在 ML / DL 中,從機制上看就是在參數估計,用資料去把模型裡未知的參數調到最合理,讓模型對新資料也能預測得準。

在書中把學習描述成一個反覆迭代的流程。

給模型一批輸入資料、模型用目前參數算出輸出(Forward)、再把輸出跟正確答案(Ground Truth)相比得到誤差,接著用誤差去決定參數該往哪個方向更新(Backward),重複到誤差夠小為止。

在這邊最重要的觀念是模型不是靠人手寫規則學會,而是靠調參數讓輸入輸出關係越來越符合資料。

image

Source:“Deep Learning with PyTorch” P. 107 Figure 5.2

  • 基準真相(Ground Truth):希望模型產出的正確答案。
  • 權重(Weights):模型中的參數,初始值通常是隨機的。
  • 前向傳播(Forward Propagation):將數據輸入模型,根據當前的權重產生輸出。
  • 誤差評估(Error Evaluation):就是損失函數(Loss Function),透過比較模型的預算輸出與 Ground Truth,計算出一個誤差衡量值。
  • 反向傳播(Backward Propagation):計算誤差對權重的導數(梯度),了解如果權重改變一個單位,誤差會如何變化。
  • 權重更新:朝著減少誤差的方向調整權重,並重複此過程直到誤差降至可接受的水準。

例子:校正溫度計

假設你有一個好看但沒標記單位指針式溫度計。

為了解決單位的問題,所以就來建立一個模型,將溫度計的讀數轉換為大家所熟悉的攝氏溫度。

那這模型裡面要做什麼事情?透過記錄一組讀數(未知單位 tut_u )與相對應的攝氏溫度( tct_c ),來估計兩者之間的轉換參數。

這也是監督式學習最典型的資料形式,(輸入, 正確輸出) 的配對。

資料預處理

收集好相關資料後,來將這些資料轉換成 tensor(Code Source:p1ch5
/1_parameter_estimation.ipynb
):

1
2
3
4
t_c = [0.5,  14.0, 15.0, 28.0, 11.0,  8.0,  3.0, -4.0,  6.0, 13.0, 21.0]
t_u = [35.7, 55.9, 58.2, 81.9, 56.3, 48.9, 33.9, 21.8, 48.4, 60.4, 68.4]
t_c = torch.tensor(t_c)
t_u = torch.tensor(t_u)

這些數據包含了噪點(Noise),可能是讀數誤差或設備本身的不精確。

資料視覺化

如果進一步將資料視覺化,採用 matplotlib 做繪圖的話,讀數與攝氏溫度看起來會有呈現線性趨勢的樣子:

1
2
3
4
5
6
7
8
9
%matplotlib inline
from matplotlib import pyplot as plt

fig = plt.figure(dpi=600)
plt.xlabel("Measurement")
plt.ylabel("Temperature (°Celsius)")
plt.plot(t_u.numpy(), t_c.numpy(), 'o')

plt.savefig("temp_data_plot.png", format="png")

temp_data_plot

模型選擇

藉由剛才觀察到的線性趨勢,假設最簡單的模型是: $$t_c = w \times t_u + b$$

  • ww (weight, 權重):表示縮放比例。
  • bb (bias, 偏差值):表示常數的偏移量。

在此的學習任務就是要根據現有資料對參數 wwbb 來做估計這件事。如果能找到一組參數,使得輸入 tut_u 得到的預測溫度與實際測量的 tct_c 非常接近,那就完成了擬合(Fitting)或學習。

接著就可以定義模型了:

1
2
def model(t_u, w, b):
return w * t_u + b

當中 wwbb 都是 0 維 tensor,即為純量的意思。

雖然這兩個是純量,但與 tut_u tensor 做相乘或相加的時候,PyTorch 會自動用廣播機制來產生 tensor 的結果。

減少損失是我們所想的(Less loss is what we want)

損失函數(Loss Function)

有時也稱為 Cost Function(成本函數)。

Loss Function 是一個將模型表現量化為單一數字的函數,學習過程的目標就是最小化這個數值。

基本上就是告訴訓練模型的人,這個模型的表現有多好,如果值越大表示模型表現差(預測與目標差距很大),越小表示越好(與目標差距小)。

計算方式:通常是模型產出的預測值( tpt_p )與期望的目標值( tct_c,Ground Truth)之間的差。

數學運算式的選擇:絕對值 vs. 平方

為了保證損失值不論在預測過高或過低時都是正數,書中提出兩種比較常看到的選擇(接續溫度計的例子來舉例):

  1. 絕對差( tptc|t_p - t_c| ):這是比較簡單且直接的方式,但在預測等於目標的地方(最小值處),其導數(斜率)是未定義的。
  2. 平方差( (tptc)2(t_p - t_c)^2 ):書中所採用的方式。

為何選擇平方差

  • 導數性質:平方差在接近最小值時表現更為平滑,在當 tp=tct_p = t_c 時,其導數為 0,有助於數值的優化。
  • 懲罰離群值(Outliers):讓模型產生許多「微小的錯誤」比產生少數幾個「巨大的錯誤」要好,因此平方運算會放大那些錯的離譜的結果,這正是所樂見的。
  • 凸函數(Convex):對線性模型來說,這兩種 Loss Function 都是凸的,因此有明確的單一最小值,可以很容易就找到。

補充:所謂凸函數指的是二階導數 f(x)0f''(x) \ge 0 的情況,根據二階導數判斷法,這種情況會產生極小值。

接下來看圖可能會更好理解:

image

Source:“Deep Learning with PyTorch” P. 110 Figure 5.4

左邊是絕對差的部分,右邊是平方差。

絕對值函數( xxˉ|x - \bar{x}| )在 x = 0 的地方導數不存在,這會有個問題,就是不能做 gradient descent,因為梯度的原理就是求導數,然後剛好那邊不存在,也就沒有辦法計算梯度。

而平方差函數( (xxˉ)2(x - \bar{x})^2 ) 恰好相反,在 x = 0 附近曲線平滑,可微分(導數 = 0)。

繼續溫度計例子:定義 loss function

先前有將模型定義好,接著就來定義一個 Loss Function,書中採取的方式是均方誤差(Mean Square Error, MSE) 的方式。

1
2
3
def loss_fn(t_p, t_c):
squared_diffs = (t_p - t_c)**2
return squared_diffs.mean()

(t_p - t_c)**2 會對 tensor 中的每個元素計算差異並平方,產生一個與輸入相同形狀的新 tensor。

最後呼叫 .mean() 方法,將 tensor 中所有元素的平方差取平均值,最終輸出一個單一的純量損失值。

由於 loss function 的輸出是要一個純量值,因而這邊用 .mean() 求純量值,而非直接 return squared_diffs,因為這東西是個向量,看不出模型的好壞程度。

初始化參數及檢查損失值

ww 權重設定為 1.0,偏差值 bb 設定為 0.0。

接下來呼叫模型 model(t_u, w, b),而這時候的模型僅僅只是把輸入的資料原封不動的做輸出( 1×x+0=x1 \times x + 0 = x

1
2
3
4
5
w = torch.ones(())
b = torch.zeros(())

t_p = model(t_u, w, b)
t_p

Output:

1
2
tensor([35.7000, 55.9000, 58.2000, 81.9000, 56.3000, 48.9000, 33.9000,
21.8000, 48.4000, 60.4000, 68.4000])

而在這個步驟就已經算是前向傳播的部分了。將數據輸入模型,根據當前的權重產生輸出,就是前向傳播的定義。

接下來做檢查損失值的動作:

1
2
loss = loss_fn(t_p, t_c)
loss

Output:

1
tensor(1763.8846)

可以發現得出的損失值非常大,表示當前的參數跟實際值的差異極大,因此需要透過後續的優化過程來降低這個數值。

廣播機制(Broadcastings)的補充

廣播機制會從最後一個維度(末尾維度)開始向後比對。

以下是匹配 tensor 元素的規則:

  1. 對於由後往前數的每個索引維度,如果其中一個運算元在該維度上的大小為 1,則 PyTorch 會將該維度上的單一元素與另一個 tensor 在該維度上的每個元素進行配對。
  2. 如果兩個 tensor 的大小都大於 1,則它們必須相同,並使用自然比對。
  3. 如果一個 tensor 的索引維度比另一個 tensor 多,則另一個 tensor 的所有元素都會用來符合這些維度上的每個元素。

書中用一個示意圖來表示廣播機制的運作原理:

image

Source:“Deep Learning with PyTorch” P. 112

另外書中也舉了這樣的例子:

1
2
3
4
5
6
7
8
9
x = torch.ones(())
y = torch.ones(3,1)
z = torch.ones(1,3)
a = torch.ones(2, 1, 1)
print(f"shapes: x: {x.shape}, y: {y.shape}")
print(f" z: {z.shape}, a: {a.shape}")
print("x * y:", (x * y).shape)
print("y * z:", (y * z).shape)
print("y * z * a:", (y * z * a).shape)

Output:

1
2
3
4
5
shapes: x: torch.Size([]), y: torch.Size([3, 1])
z: torch.Size([1, 3]), a: torch.Size([2, 1, 1])
x * y: torch.Size([3, 1])
y * z: torch.Size([3, 3])
y * z * a: torch.Size([2, 3, 3])

形狀為 ()(純量,零維張量)與形狀為 (3, 1) 的張量相乘後,形狀的結果會是 (3, 1)

這個結果主要遵循上面的第三條規則。

接下來 (3, 1)(1, 3) 做相乘,得到的形狀會是 (3, 3)。這部分遵循上面第一條規則,兩個 tensor 在該維度的長度完全一致、其中一個維度長度為 1。如果一個張量的維度比另一個少,則會自動將缺失的維度視為長度 1 並進行擴展,這也是為什麼結果會是 (3, 3) 的原因。

沿著梯度下降(Down along the gradient)

在上一節有提及到如何優化來降低 loss function 的產生值,那這個優化的方法就叫做梯度下降(Gradient Descent)。

書中提供了轉鈕作為梯度下降的比喻。

想像面前有一台機器,上面有兩個標示為 ww (權重)和 bb (偏差值)的轉鈕,螢幕上顯示著損失值(Loss)。

目標是要把這個 Loss 降到最低,那因為不知道轉扭會對損失這件事情會有多大的影響,所以會微調轉扭,觀察 Loss 是增加還是減少,從而決定旋轉方向。

當接近最小值(損失變化變慢)時,會縮小調整幅度,避免錯過最低點或讓損失再次攀升。

總之,Gradient Descent 是在計算損失函數相對於每個參數的變化率,並朝著損失減少的方向修改參數的方法。

image

Source:“Deep Learning with PyTorch” P. 113 Figure 5.5

數值估計變化率(求導數)

為了知道如何轉動轉鈕(調整參數 wwbb),得要知道微調參數後損失會如何變化。在這邊書中的做法是給參數加一個極小值 delta δ\delta ,觀察損失在附近的變化。

1
2
3
4
5
delta = 0.1

loss_rate_of_change_w = \
(loss_fn(model(t_u, w + delta, b), t_c) -
loss_fn(model(t_u, w - delta, b), t_c)) / (2.0 * delta)

這段程式碼在計算當 ww 改變時,Loss Function 的變化幅度。

其實就是在求導數啦,這一段可以寫成這樣的數學公式: $$f’(w) \approx \frac{f(w + \delta) - f(w - \delta)}{2\delta}$$

這種叫做中心差分,就是前向差分 + 後向差分,可以想像往左一步也往右一步的感覺。

前向差分(導數定義): $$f’(w) \approx \frac{f(w + \delta) - f(w)}{\delta}$$

後向差分: $$f’(w) \approx \frac{f(w) - f(w - \delta)}{\delta}$$

中心差分在步長一樣小的情況下,近似通常會更準,因此書中採用中心差分的方式計算 Loss 值在附近的變化。

確定調整方向與幅度

得到變化率後,要決定調整參數的方向:

  • 方向選擇:
    • 變化率是正的,代表增加 ww 會讓損失增加,所以要減少 ww
    • 變化率是負的,則要增加 ww 以最小化損失。
  • 比例調整:更新的幅度應與損失的變化率成比例,這樣對損失影響較大的參數會得到較大的調整。

學習率(Learning Rate)

在實際更新參數時,不能直接看變化率調整,因為變化率在遠處可能會與當前的 ww 完全不同,不然怎麼叫做變化率嘛。因此需要一個較小的(可能 0.001)縮放因子(scaling factor)乘上這個變化率,在機器學習中稱為學習率(learning_rate:用 η\eta eta 表示)。

簡言之,Learning Rate 是要讓模型每一步要跨多大步的設定,專門控制它更新權重時的步伐大小。如果步伐跨的很大,則有可能會錯失掉最小值的點,在最小值附近亂跳或產生震盪,反之跨的太小,那這個模型不知道是要跑掉民國幾年才跑得完。

在這邊撰寫程式碼:

1
2
3
learning_rate = 1e-2

w = w - learning_rate * loss_rate_of_change_w

等號前面的 ww,代表著下一個 ww;後面的 ww 則為當前的 ww

ww 後面的負號是為了要讓 ww 做增加或減少的事情,例如得到的導數 loss_rate_of_change_w < 0,這時候 ww 是要做增加,因此前面加上一個負號讓式子變正的。

然後同樣的邏輯也適用於 bb

1
2
3
4
5
loss_rate_of_change_b = \
(loss_fn(model(t_u, w, b + delta), t_c) -
loss_fn(model(t_u, w, b - delta), t_c)) / (2.0 * delta)

b = b - learning_rate * loss_rate_of_change_b

經過反覆迭代這些數值評估,且假設 learning rate 選得夠小,最後肯定收斂到參數的最優值,使得最後估計出的 loss 最小。

由數值估計轉為「分析法」(Analytical)

原本的數值估計法是給 ww 增加一個微小的 δ\delta 值,並觀察 Loss 的變化率來估計梯度。但這種方法有兩個主要問題:

  1. 擴展性差:當模型有數百萬個參數時,對每個參數重複執行模型來探測行為是非常低效的行為。
  2. 精準度受限於 delta:擾動的大小(如 0.1)會影響估計的準確性。如果 Loss 變化太快,這種方法無法給出最正確的下降方向。

分析法(Analytical)則透過數學公式直接求導,相當於讓這個擾動量趨近於無窮小。

那分析法怎麼做呢?利用 chain rule(連鎖律),在此之前先對損失函數對參數的變化拆解為兩個部分:

  1. Loss 對其輸入(即模型輸出 tpt_p )的變化率。
  2. 模型輸出 tpt_p 對參數(如 ww)的變化率。

公式表示為:$$\frac{dLoss}{dw}=\frac{dLoss}{dt_p} \cdot \frac{dt_p}{dw}$$

這邊所對應的是書上這條:d loss_fn / d w = (d loss_fn / d t_p) * (d t_p / d w)

第一部分:Loss 對模型輸出的導數

先前的 Loss 定義為均方誤差 MSE:

1
2
3
def loss_fn(t_p, t_c):
squared_diffs = (t_p - t_c)**2
return squared_diffs.mean()

然後對某一個 tp,it_{p,i} 求偏導,得到其導函數為:

1
2
3
4
def dloss_fn(t_p, t_c):
# 除以 t_p.size(0) 是因為 loss 取了平均值 (mean)
dsq_diffs = 2 * (t_p - t_c) / t_p.size(0)
return dsq_diffs

原本 loss_fn 的公式是 $$loss = \frac{1}{N}\sum^N_{i=1}(t_{p,i} - t_{c,i})^2$$

當中 NN 是樣本數,除以 NN 就是取平均值。

lossloss 求偏導後得到: $$\frac{\partial loss}{\partial t_{p,i}} = \frac{1}{N} \cdot 2(t_{p,i} - t_{c,i})$$

t_p.size(0) 就等同於那個 NN

第二部分:模型輸出對參數的導數

模型是一個線性函數,長這樣:tp=wtu+bt_p = w \cdot t_u + b

wwbb 分別求導:

  • ww 求導:只有 tut_u 項與 ww 相關,結果為 tut_u
  • bb 求導:bb 的係數是 1.0,結果為 1.0。

寫成程式碼則會是:

1
2
def model(t_u, w, b):
return w * t_u + b
1
2
def dmodel_dw(t_u, w, b):
return t_u
1
2
def dmodel_db(t_u, w, b):
return 1.0

定義完整的梯度函數

將上述部分合起來,就可以得到 grad_fn 了。

這個函數會計算所有資料點上的偏導數,並做加總(廣播機制的逆向過程),最後回傳一個包含所有參數梯度的 tensor。

1
2
3
4
5
6
def grad_fn(t_u, t_c, t_p, w, b):
dloss_dtp = dloss_fn(t_p, t_c)
dloss_dw = dloss_dtp * dmodel_dw(t_u, w, b)
dloss_db = dloss_dtp * dmodel_db(t_u, w, b)
# 將每個樣本的梯度加總,得到整批數據的梯度
return torch.stack([dloss_dw.sum(), dloss_db.sum()])

將這個函數寫成數學式子就會是:

image

Source:“Deep Learning with PyTorch” P. 116 Figure 5.7

透過迭代去擬合模型(Iterating to fit the model)

在這邊會結合先前學到的損失函數與梯度計算做整合,再透過迭代讓模型真正學習。

什麼是訓練迴圈(Training Loop)?

當有了模型、損失函數和梯度函數後,還需要一個自動化的過程來不斷更新參數,直到損失降到最低為止,這就是訓練迴圈存在的意義。

這個過程包含以下兩個要素:

  • Epoch(訓練週期):機器學習術語,把資料集(data set)裡面的資料全部訓練過一次就是一個 Epoch。
  • 終止條件:迭代通常會持續到預設的 Epoch 結束,或是參數 wwbb 不再發生顯著變化為止。

完整的 training_loop 程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def training_loop(n_epochs, learning_rate, params, t_u, t_c):
for epoch in range(1, n_epochs + 1):
w, b = params

# 1. 前向傳播 (Forward pass)
t_p = model(t_u, w, b)
# 2. 計算損失值
loss = loss_fn(t_p, t_c)
# 3. 反向傳播 (Backward pass / 計算梯度)
grad = grad_fn(t_u, t_c, t_p, w, b)
# 4. 更新參數 (梯度下降)
params = params - learning_rate * grad
# 打印進度
print('Epoch %d, Loss %f' % (epoch, float(loss)))

return params
  • 前向傳播(model(t_u, w, b)):將輸入數據 t_u 丟進模型,得到預測值 t_p
  • 損失函數(loss_fn(t_p, t_c)):比較預測值與實際觀測值 t_c 的差距。
  • 反向傳播(grad_fn(t_u, t_c, t_p, w, b)):計算損失函數對參數的偏導數(梯度),找出讓損失下降的方向。
  • 更新參數(gradient descent):沿著梯度的反方向移動一小步(由 learning_rate 決定步長)。

overtraining : learning rate 設得太大

書中作者用 learning_rate = 1e-2 也就是 0.01 下去跑 100 Epoch 的時候,結果發現 Loss 不減反增,變成超大的 inf

如下程式碼及其輸出結果:

1
2
3
4
5
6
training_loop(
n_epochs = 100,
learning_rate = 1e-2,
params = torch.tensor([1.0, 0.0]),
t_u = t_u,
t_c = t_c)

Output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Epoch 1, Loss 1763.884644
Params: tensor([-44.1730, -0.8260])
Grad: tensor([4517.2969, 82.6000])
Epoch 2, Loss 5802485.500000
Params: tensor([2568.4014, 45.1637])
Grad: tensor([-261257.4219, -4598.9712])
Epoch 3, Loss 19408035840.000000
Params: tensor([-148527.7344, -2616.3933])
Grad: tensor([15109614.0000, 266155.7188])
...
Epoch 10, Loss 90901154706620645225508955521810432.000000
Params: tensor([3.2144e+17, 5.6621e+15])
Grad: tensor([-3.2700e+19, -5.7600e+17])
Epoch 11, Loss inf
Params: tensor([-1.8590e+19, -3.2746e+17])
Grad: tensor([1.8912e+21, 3.3313e+19])
tensor([-1.8590e+19, -3.2746e+17])

原因是過度訓練(overtraining) or 發散的問題,就是參數的更新幅度太大,導致模型在最小值的兩側劇烈擺動,每一次更新都越過了最小值並跳得更遠。

如圖:

image

Source:“Deep Learning with PyTorch” P. 118 Figure 5.8

解決方法就是把 learning rate 再調小一點,調成 learning_rate = 1e-4

調整完後再執行一次:

1
2
3
4
5
6
training_loop(
n_epochs = 100,
learning_rate = 1e-4,
params = torch.tensor([1.0, 0.0]),
t_u = t_u,
t_c = t_c)

Output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Epoch 1, Loss 1763.884644
Params: tensor([ 0.5483, -0.0083])
Grad: tensor([4517.2969, 82.6000])
Epoch 2, Loss 323.090546
Params: tensor([ 0.3623, -0.0118])
Grad: tensor([1859.5493, 35.7843])
Epoch 3, Loss 78.929634
Params: tensor([ 0.2858, -0.0135])
Grad: tensor([765.4667, 16.5122])
...
Epoch 10, Loss 29.105242
Params: tensor([ 0.2324, -0.0166])
Grad: tensor([1.4803, 3.0544])
Epoch 11, Loss 29.104168
Params: tensor([ 0.2323, -0.0169])
Grad: tensor([0.5781, 3.0384])
...
Epoch 99, Loss 29.023582
Params: tensor([ 0.2327, -0.0435])
Grad: tensor([-0.0533, 3.0226])
Epoch 100, Loss 29.022669
Params: tensor([ 0.2327, -0.0438])
Grad: tensor([-0.0532, 3.0226])
tensor([ 0.2327, -0.0438])

在這裡有個問題,就是雖然 Loss 穩定了,但是訓練到 Epoch 100 的時候,梯度還是很大,幾乎沒什麼降,就表示離最優解還很遠。

參數規模不一致

書中的作者觀察梯度發現了問題,就是權重 ww 的梯度比偏差值 bb 的梯度大了約 50 倍。

We can see that the first-epoch gradient for the weight is about 50 times larger than the gradient for the bias.

也表示說 wwbb 處於不同的空間尺度(scale)。

如果學習率大到足以讓 bb 更新,就會讓 ww 不穩定(爆炸);如果學習率小到能讓 ww 穩定,對 bb 來說就太小了,更新幾乎停滯。

輸入正規化(Normalizing inputs)

為了解決「學習率太高會導致損失值 inf」、「太低則會讓訓練極其緩慢甚至停滯」的問題,因此需要對輸入做正規化(Normalizing)的動作。

具體來說怎麼做呢?就是要把輸入資料的範圍大致落在 -1.01.0 之間。

在溫度計例子中,原始資料 t_u 的數值較大,於是乘以 0.1,得到了正規化後的資料 t_un

1
t_un = 0.1 * t_u

使用正規化後的資料 t_un 後,再執行一次 training_loop,把 learning rate 設回先前會導致不穩的 1e−2。

結果發現:

  • 穩定性大幅提升:不像之前 learning rate 調高的時候,會出現 inf 的狀況。
  • 梯度趨於平衡

最後再用這個正規化後的資料,執行 5000 輪的 Epoch 時,損失值最終降到了約 2.927。得到的權重 w 為 5.3671,偏差值 b 為 -17.3012

雖說這種規模的問題可能不用用到正規化的方式去優化,也可以在那邊手動調參數,但日後訓練龐大的神經網路,那些參數量是大的可怕,總不可能一個一個手動調,因此需要用到正規化的技巧來優化參數。

總整理

學習就是在做參數估計

在 ML / DL 中,「學習」本質上不是學規則,而是用資料反覆調整模型參數,讓輸入與輸出關係最符合資料分佈。

整個學習流程可理解成這樣:

Forward → 計算 Loss → Backward → 更新參數 → 重複前面步驟

模型本身只是函數形式,真正讓模型變聰明的是參數(weights, bias)的調整。

損失函數(Loss Function):把「好壞」變成可視化的數字

為什麼需要 Loss Function?因為電腦沒有辦法去理解一個模型的好壞,只能最小化一個數值。

為何選擇平方差(MSE)?

相較於絕對差:

  1. 可微:在最小值處導數為 0,適合梯度下降法。
  2. 平滑:數值穩定,利於優化。
  3. 懲罰離群值:鼓勵整體誤差變小。
  4. 凸函數(對於線性模型來說):保證只有一個全域最小值。

梯度下降(gradient descent):沿著最陡的下降方向走

梯度下降就是在算出「參數變一點點,Loss 會變多少」,然後往 Loss 下降的方向移動。

做到梯度下降基本上有三個要點:

  1. 梯度(Gradient):方向。
  2. 學習率(Learning Rate):步伐大小。
  3. 反覆迭代:逐步逼近最小值。

數值法 vs. 分析法

數值估計(差分法):

  • 原理直觀
  • 不具擴展性
  • 精度受 delta 影響

分析法(Chain Rule):

  • 直接算偏導
  • 高效、精準
  • 是 Backpropagation 的數學基礎

訓練迴圈(Training Loop):學習自動化

一個完整訓練流程固定包含:

  1. Forward
  2. 計算 Loss
  3. Backward(算梯度)
  4. 更新參數

learning rate 陷阱

  1. 太大 → 發散、Loss 爆炸(inf)
  2. 太小 → 幾乎不動,訓練停滯

輸入正規化(Normalization)

目的:讓所有特徵落在相近的數值尺度

效果:

  • 梯度平衡
  • 可用較大的 learning rate
  • 收斂更穩定、更快

專有名詞對照表

中文名詞英文名詞說明
學習Learning用資料估計參數,使模型表現變好
參數估計Parameter Estimation尋找最佳參數值的過程
模型Model描述輸入與輸出關係的函數
參數Parameters模型中可被學習的數值
權重Weight控制輸入影響力大小
偏差值Bias用來平移輸出的常數
擬合Fitting模型成功貼近資料
監督式學習Supervised Learning使用 (輸入, 正確輸出) 訓練
資料集Dataset用於訓練或測試的資料
輸入資料Input Data餵給模型的數值
正確答案Ground Truth希望模型輸出的真實值
噪聲Noise資料中的誤差或干擾
廣播機制Broadcasting自動擴展張量形狀以運算
前向傳播Forward Propagation / Forward Pass用目前參數計算輸出
模型輸出Prediction / Output模型預測結果
誤差評估Error Evaluation衡量預測與正解差距
反向傳播Backpropagation計算誤差對參數的影響
梯度GradientLoss 對參數的變化率
損失函數Loss Function將模型表現轉為數字
成本函數Cost FunctionLoss Function 的別稱
損失值Loss模型好壞的量化指標
均方誤差Mean Squared Error (MSE)常用回歸損失函數
絕對差Absolute Error使用差值絕對值
平方差Squared Error使用差值平方
離群值Outlier與其他資料差距極大的點
凸函數Convex Function只有單一全域最小值
導數Derivative函數的變化率
偏導數Partial Derivative對單一變數求導
變化率Rate of Change輸入改變造成輸出變化
中心差分Central Difference數值估計導數方法
前向差分Forward Difference往前估計導數
後向差分Backward Difference往後估計導數
分析法Analytical Method直接用公式算導數
梯度下降Gradient Descent沿梯度反方向降低 Loss
最小值MinimumLoss 最低的位置
收斂Convergence參數趨於穩定
發散Divergence參數失控、不穩定
學習率Learning Rate控制更新步伐大小
縮放因子Scaling Factor縮小梯度的倍率
訓練Training調整參數的過程
訓練迴圈Training Loop自動化訓練流程
訓練週期Epoch全資料訓練一次
過度訓練Overtraining步伐過大導致發散
正規化Normalization將數值縮放到合理範圍