---
# System prepended metadata

title: 第三章：類神經網路訓練技巧
tags: [機器學習]

---

# 第三章：類神經網路訓練技巧
>上課筆記
* 上課影片連結
    * ==[**(一)： 局部最小值 (local minima) 與鞍點 (saddle point)**](https://youtu.be/QW6uINn7uGk)==
    * ==[**(二)： 批次 (batch) 與動量 (momentum)**](https://youtu.be/zzbr1h9sF54)==
    * ==[**(三)：自動調整學習速率 (Learning Rate)**](https://youtu.be/HYUXEeh3kwY)==
    * ==[**(四)：損失函數 (Loss) 也可能有影響**](https://youtu.be/O2VkP8dJ5FE)==
    * ==[**(五)： 批次標準化 (Batch Normalization) 簡介**](https://youtu.be/BABPWOkSbLE)==

---
---

# (一) 深度學習優化：探索臨界點
局部最小值 (local minima) 與 鞍點 (saddle point)

---

## Optimization 的重要性

*   在進行模型訓練的 **Optimization** 階段，我們的目標是調整模型參數，使得訓練損失 (training loss) 能夠不斷下降。
*   Optimization 的成敗直接影響著模型的最終性能，即使是深層網路，如果 Optimization 不佳，也可能無法超越較淺的模型。
*   有時訓練初期就會遇到問題，無論如何更新參數，損失函數的值都無法下降。

---

## Optimization 失敗的可能原因：梯度為零

*   過去常見的猜測是，模型訓練停滯是因為參數更新到了某個地方，這個地方的**參數對損失函數的微分（即梯度）為零**。
*   當梯度為零時，梯度下降 (gradient descent) 就無法再更新參數，訓練自然停止，損失也無法繼續下降。

---

## 常見的誤解：卡在局部最小值 (Local Minima)

*   提到梯度為零，人們通常最先想到的是 **局部最小值 (local minima)**。
*   過去常有人認為，深度學習使用梯度下降會卡在局部最小值，導致訓練失敗。
*   **然而，在撰寫深度學習相關論文時，應避免聲稱模型卡在局部最小值，因為梯度為零的點不只有局部最小值**。

---

## 鞍點 (Saddle Point)：另一種梯度為零的臨界點

*   除了局部最小值，還存在其他可能使梯度為零的點，例如 **鞍點 (saddle point)**。
*   **鞍點的梯度也為零，但它既不是局部最小值，也不是局部最大值**。
*   鞍點的形狀類似馬鞍，在某些方向上損失函數值較高，而在另一些方向上則較低。
*   **所有梯度為零的點，統稱為臨界點 (critical point)**。
*   因此，當損失函數不再下降時，我們只能說可能卡在了某個臨界點，而不能斷定是局部最小值。
![image](https://hackmd.io/_uploads/B1PCqOx2kl.png)

## 為什麼需要區分局部最小值與鞍點？

*   **如果是卡在局部最小值，可能難以找到更好的解，因為周圍的損失函數值都較高**。
*   **但如果是卡在鞍點，情況則不同，因為鞍點附近通常還有可以使損失函數值更低的方向**。
*   只要能夠逃離鞍點，就有可能繼續降低損失。
*   因此，**判斷當前所處的臨界點是局部最小值還是鞍點，是一個值得探討的問題**。

---

## 如何判斷臨界點的類型：Hessian 矩陣

判斷臨界點的類型需要用到一些數學工具，主要是微積分和線性代數的概念。

### 泰勒級數近似 (Taylor Series Approximation)

*   雖然我們無法完整知道整個損失函數的形狀，但在給定一組參數 $\color{blue}{\theta'}$ 附近，損失函數 $L(\theta)$ 可以用 **泰勒級數近似** 來表示：$$L(\theta) \approx L(\color{blue}{\theta'}) + (\theta - \color{blue}{\theta'})^T \color{green}{g} + \frac{1}{2} (\theta - \color{blue}{\theta'})^T \color{red}{H} (\theta - \color{blue}{\theta'})$$其中：
    *   $L(\color{blue}{\theta'})$ 是在 $\color{blue}{\theta'}$ 處的損失函數值。
    *   $\color{green}{g} = \nabla L(\color{blue}{\theta'})$ 是在 $\color{blue}{\theta'}$ 處的**梯度 (gradient)**，是一個向量，表示損失函數在每個參數方向上的變化率。
    *   $\color{red}{H}$ 是在 $\color{blue}{\theta'}$ 處的 **Hessian 矩陣**，是一個包含損失函數**二階偏微分**的矩陣，描述了損失函數的局部曲率。 其$\color{red}{H_{ij}} = \frac{\partial^2}{\partial \theta_i \partial \theta_j}L(\color{blue}{\theta'})$

### 在臨界點的情況

*   當我們走到一個臨界點時，**梯度 $g$ 為零向量**。
*   此時，損失函數的近似可以簡化為：$$L(\theta) \approx L(\color{blue}{\theta'}) + \frac{1}{2} (\theta - \color{blue}{\theta'})^T \color{red}{H} (\theta - \color{blue}{\theta'})$$
*   **我們可以根據第二項（與 Hessian 矩陣相關的項）來判斷 $\color{blue}{\theta'}$ 附近的 error surface 的形狀，進而判斷 $\color{blue}{\theta'}$ 是局部最小值、局部最大值還是鞍點**。

### 利用 Hessian 矩陣的性質判斷臨界點類型

*   為了方便表示，令 $v = \theta - \color{blue}{\theta'}$。 則第二項為 $\frac{1}{2} v^T \color{red}{H} v$。
*   **局部最小值 (Local Minima)**: 如果對於所有可能的 $v \neq 0$，都有 $v^T \color{red}{H} v > 0$，則 $\color{blue}{\theta'}$ 是一個局部最小值。這種矩陣 $\color{red}{H}$ 被稱為 **正定 (positive definite)** 矩陣，其**所有特徵值 (eigenvalue) 都是正的**。
*   **局部最大值 (Local Maxima)**: 如果對於所有可能的 $v \neq 0$，都有 $v^T \color{red}{H} v < 0$，則 $\color{blue}{\theta'}$ 是一個局部最大值。這種矩陣 $\color{red}{H}$ 被稱為 **負定 (negative definite)** 矩陣，其**所有特徵值都是負的**。
*   **鞍點 (Saddle Point)**: 如果對於某些 $v$，有 $v^T \color{red}{H} v > 0$，而對於另一些 $v$，有 $v^T \color{red}{H} v < 0$，則 $\color{blue}{\theta'}$ 是一個鞍點。此時，Hessian 矩陣的**特徵值有正有負**。

### 總結

*   **計算 Hessian 矩陣**。
*   **計算 Hessian 矩陣的所有特徵值**。
*   **如果所有特徵值都是正的，則是局部最小值**。
*   **如果特徵值有正有負，則是鞍點**。

---

## 史上最廢的網路範例

*   考慮一個簡單的網路 $y = w_1w_2x$ 和一個最廢的訓練數據集：當 $x=1$ 時，$y$ 的目標值 $\hat{y}=1$
![image](https://hackmd.io/_uploads/Hkh-Adl21g.png)
*   損失函數 (平方誤差) 為 $L(w_1, w_2) = (1 - w_1 w_2)^2$
*   我們可以窮舉 $w_1$ 和 $w_2$ 的所有可能值，繪製出 **error surface**。 從 error surface 可以觀察到，在原點 $(0, 0)$ 是一個臨界點，且是一條線上也存在一排臨界點。
*   通過更進一步的分析，可以發現 **原點 $(0, 0)$ 是一個鞍點**，因為沿某些方向損失函數值增大，而沿另一些方向損失函數值減小。 而那些山溝裡的一排臨界點則是 **局部最小值**。

### 使用 Hessian 矩陣分析範例

*   計算損失函數 $L(w_1, w_2) = (1 - w_1 w_2)^2$ 的梯度 $\color{green}{g}$：
    *   $\frac{\partial L}{\partial w_1} = 2(1 - w_1 w_2)(-w_2)$
    *   $\frac{\partial L}{\partial w_2} = 2(1 - w_1 w_2)(-w_1)$
*   在原點 $(w_1=0, w_2=0)$，梯度為零，因此是臨界點。
*   計算 Hessian 矩陣 $\color{red}{H}$：
    *   $\frac{\partial^2 L}{\partial w_1^2} = 2(-w_2)(-w_2) = 2w_2^2$
    *   $\frac{\partial^2 L}{\partial w_2^2} = 2(-w_1)(-w_1) = 2w_1^2$
    *   $\frac{\partial^2 L}{\partial w_1 \partial w_2} = -2(1 - w_1 w_2) + 2(-w_2)(-w_1) = -2 + 4w_1 w_2$
    *   $\frac{\partial^2 L}{\partial w_2 \partial w_1} = -2 + 4w_1 w_2$
*   在原點 $(0, 0)$，Hessian 矩陣為 $\color{red}{H} = \begin{bmatrix} 0 & -2 \\ -2 & 0 \end{bmatrix}$。
*   計算 Hessian 矩陣的特徵值，得到 $\lambda_1 = 2$ 和 $\lambda_2 = -2$。
*   由於特徵值有正有負，因此原點 $(0, 0)$ 是一個 **鞍點(Saddle Point)**。
![image](https://hackmd.io/_uploads/HyyKCdx2Jl.png)
![image](https://hackmd.io/_uploads/HyC-lYxhyl.png)

---

## 不必害怕鞍點？

*   **如果在訓練過程中停下來是因為卡在鞍點，或許不必過於擔心，因為還有機會逃離**。

### 利用 Hessian 矩陣的特徵向量逃離鞍點

*   假設 $u$ 是 Hessian 矩陣 $\color{red}{H}$ 的一個特徵向量，$\lambda$ 是對應的特徵值，即 $\color{red}{H}u = \lambda u$。
*   將 $v$ 替換為 $u$，$v^T \color{red}{H} v$ 會變成 $u^T \color{red}{H} u = u^T (\lambda u) = \lambda \|u\|^2$。
*   **如果特徵值 $\lambda$ 是負的，那麼 $\lambda \|u\|^2 < 0$**。
*   這意味著，如果我們沿著對應於負特徵值的特徵向量 $u$ 的方向更新參數 $\color{blue}{\theta'} \rightarrow \color{blue}{\theta'} + u$，損失函數值 $L(\color{blue}{\theta'} + u)$ 會比 $L(\color{blue}{\theta'})$ 小。
*   **因此，即使在梯度為零的鞍點，我們也可以通過找到 Hessian 矩陣的負特徵值及其對應的特徵向量，來找到使損失函數下降的參數更新方向**。

### 實作上的挑戰

*   **在實際應用中，很少直接計算並使用 Hessian 矩陣來逃離鞍點，因為計算二階微分以及特徵值和特徵向量的計算量非常大**。
*   存在其他計算量更小的方法來嘗試逃離鞍點。

---

## 鞍點 vs. 局部最小值：誰更常見？

*   如果鞍點比局部最小值更常見，那麼 Optimization 的問題或許沒有想像中那麼嚴重。

### 高維空間的特性

*   類比：從三維空間看是封閉的石棺，但在四維空間中可能有路可以進入。
*   **在高維的參數空間中（深度學習模型的參數通常非常多），error surface 的性質可能與我們在低維空間中的直覺不同**。
*   在二維空間中看起來是局部最小值的地方，在高維空間中可能只是鞍點，存在其他可以降低損失的方向。
*   **維度越高，可能存在的逃離路徑就越多**。

### 經驗研究 (Empirical Study)

*   研究表明，在實際訓練深度網路並達到梯度很小的臨界點時，**很少遇到所有 Hessian 矩陣的特徵值都是正的情況（真正的局部最小值）**。
*   實驗結果顯示，即使在訓練損失已經很低的時候卡住，Hessian 矩陣的特徵值通常也只有一部分是正的，另一部分是負的。
*   **Minimum Ratio** (正特徵值數量 / 特徵值總數量) 通常遠小於 1，這表示存在許多負特徵值，暗示著當前處於類似鞍點的平坦區域。
*   **從經驗上看，局部最小值可能並沒有那麼常見，多數時候訓練停滯是因為卡在了鞍點或鞍點附近的平坦區域**。

---

## 結論

*   **臨界點是梯度為零的點**。
*   **臨界點可以是鞍點或局部最小值**。
*   **Hessian 矩陣可以幫助判斷臨界點的類型**。
*   **有可能沿著 Hessian 矩陣特徵向量的方向逃離鞍點**。
*   **局部最小值可能比我們想像的要少見**。
*   **[較小的批次大小 (smaller batch size)](###小批次在測試-(Testing)-上的優勢) 和 [動量 (momentum)](###動量的好處) 有助於逃離臨界點** (將在後續討論)。

---
---

# (二) 深度學習訓練技巧：批次 (Batch) 與動量 (Momentum)

---

## 批次 (Batch)
> [第一章](https://hackmd.io/SeTphOa5SSOlfEzjBQA9Zg?view#%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D%E7%9A%84%E7%B4%B0%E7%AF%80)
### 為什麼要使用批次 (Why Batch?)

*   在訓練神經網路時，我們通常不會一次性地使用所有訓練資料來計算損失 (Loss) 並更新模型參數。
*   而是將所有訓練資料分割成許多小的群組，這些小群組就被稱為 **批次 (Batch)** 或 **小批次 (Mini-Batch)**。
*   每次更新參數時，我們只會從訓練資料中取一個批次的資料出來，計算這個批次的損失，然後根據這個批次的梯度 (Gradient) 來更新參數。
*   這個過程會重複進行，直到所有的批次都被處理過一次，這被稱為一個 **週期 (Epoch)**。

### 批次的運作方式

*   假設我們的批次大小 (Batch Size) 設定為 B。
*   在每一個訓練步驟中，我們從訓練集中選取 B 筆資料。
*   使用這 B 筆資料計算模型的損失函數值。
*   根據這個損失函數值，計算模型參數的梯度。
*   使用計算出的梯度來更新模型的參數。
*   這個過程會不斷重複，直到所有的訓練資料都被分成 B 筆一組的批次處理完畢。

### 洗牌 (Shuffle)

*   在將資料分成批次之前，通常會進行 **洗牌 (Shuffle)** 的操作。
*   洗牌的目的是為了讓每個週期 (Epoch) 中，資料被分到不同批次的可能性更高，避免模型過度學習到批次內資料的特定順序。
*   常見的做法是在每個 Epoch 開始之前，重新對整個訓練資料集進行一次隨機的排列，然後再重新分批。

### 使用批次的原因：比較極端案例

為了理解為什麼要使用批次，我們可以比較兩種極端的狀況：

*   **完整批次 (Full Batch) 或沒有使用批次:**
    *   批次大小等於訓練資料的總量 (N=20 的例子中，Batch Size = 20)。
    *   模型必須看完所有的訓練樣本才能計算出總體的損失和梯度。
    *   參數更新的頻率較低，看完所有資料後才更新一次。
    *   如同「蓄力時間長，技能冷卻時間長」，需要較長時間才能完成一次參數更新。
    *   但每次更新的方向是基於所有資料計算的梯度，因此方向比較穩定。

*   **批次大小為 1:**
    *   每次只看一筆訓練資料就計算損失和梯度，並更新參數。
    *   參數更新的頻率非常高，每看完一筆資料就更新一次 (N=20 的例子中，一個 Epoch 會更新 20 次)。
    *   如同「蓄力時間短，技能冷卻時間短」，每次更新的速度很快。
    *   但由於每次只根據一筆資料計算梯度，梯度會非常 **雜訊 (Noisy)**，參數更新的方向會呈現曲折不定的情況。
![image](https://hackmd.io/_uploads/r1FD8Yghyx.png)

### 批次對訓練帶來的幫助

使用批次的方法介於完整批次和批次大小為 1 之間，它試圖結合兩者的優點。

### 平行運算的考量 (GPU)

*   在沒有考慮平行運算的情況下，直覺上會認為大的批次需要更長的計算時間。
*   然而，由於現代的硬體 (例如 **GPU**) 具有 **平行運算** 的能力，計算一個較大批次的損失和梯度所需要的時間，**不一定比計算一個較小批次的要長很多**。
*   在一定的批次大小範圍內 (例如 MNIST 資料集上的實驗顯示，Batch Size 從 1 到 1000，計算梯度所需的時間幾乎一樣)，GPU 可以 **同時處理** 批次中的多筆資料。
*   但是，GPU 的平行運算能力仍然有其極限。當批次大小真的非常非常大的時候，計算時間還是會隨著批次大小的增加而逐漸增長。
*   因此，雖然大的批次在單次更新上不一定更耗時，但由於每次更新處理的資料量較大，**跑完一個完整的 Epoch (看過所有資料一次)** 所需的更新次數會減少，因此 **大的批次在每個 Epoch 上花費的時間通常比小的批次要短**。
![image](https://hackmd.io/_uploads/rJBsUFe21l.png)

### 雜訊梯度 (Noisy Gradient) 的優勢

*   一個看似違反直覺的現象是，**較小的批次所帶來的雜訊梯度，反而有助於模型的訓練**。
*   實驗結果顯示，在 MNIST 和 CIFAR-10 等影像辨識任務上，**較小的批次大小通常能獲得更好的驗證集 (Validation Accuracy) 表現**。
*   這並非過度擬合 (Overfitting) 的問題，因為小的批次在 **訓練集 (Training Set) 上的表現也通常更好**。
*   一個可能的解釋是，當使用 **完整批次** 進行參數更新時，模型可能會卡在 **局部最小值 (Local Minima)** 或 **鞍點 (Saddle Point)**。因為梯度為零，就無法再繼續更新參數。
*   但是，當使用 **小批次** 時，由於每個批次計算出的損失函數和梯度都有所不同，**每次參數更新的方向都帶有隨機性 (Noisy)**。
*   這種隨機性使得模型**更有可能跳出局部最小值或鞍點**。即使在一個批次上梯度接近於零，下一個批次計算出的梯度可能指向不同的方向，從而幫助模型繼續尋找更優的解。
*   如同之前討論局部最小值與鞍點時提到的，error surface 可能非常複雜，小的批次帶來的隨機性更新，有助於探索更廣泛的參數空間。

### 小批次在測試 (Testing) 上的優勢

*   更令人驚訝的是，即使大小批次在訓練集上達到相似的準確率，**小的批次通常在測試集上也能表現得更好 (泛化能力更強)**。
*   這可能與 **平坦最小值 (Flat Minima) 和尖銳最小值 (Sharp Minima)** 的概念有關。
*   據信 **大的批次大小傾向於使模型收斂到尖銳的局部最小值**，這些最小值在訓練資料上表現很好，但對未見過的測試資料的穩健性較差，因為當訓練集和測試集的資料分布略有不同時，損失函數值的變化會很大。
*   **小的批次大小則傾向於使模型收斂到更平坦的局部最小值**，這些最小值周圍的損失函數值變化較小，因此對資料分布的變動更具穩健性，泛化能力也更好。
![image](https://hackmd.io/_uploads/rJbewtxnJl.png)
![image](https://hackmd.io/_uploads/rkErwYe2yx.png)

### 小批次與大批次的比較總結

| 特性                 | 小批次 (Small Batch) | 大批次 (Large Batch) |
| :------------------- | :------------------- | :------------------- |
| 單次更新速度 (無平行) | 較快                 | 較慢                 |
| 單次更新速度 (有平行) | 相近                 | 相近 (除非非常大)     |
| 每個 Epoch 的時間     | 較慢                 | 較快 :+1:             |
| 梯度                 | 雜訊 (Noisy)         | 穩定 (Stable)         |
| 優化效果             | 較好 :+1:                | 較差                 |
| 泛化能力             | 較好 :+1:                | 較差                 |

### 魚與熊掌兼得？

*   由於大小批次各有優缺點，研究人員也在探索是否能夠結合兩者的優勢，例如使用大的批次大小進行訓練以提高效率，同時又能獲得好的訓練和測試結果。
*   許多研究論文提出了相關的技巧，例如使用大的批次進行訓練，並結合特定的學習率調整策略或其他優化方法。

---

## 動量 (Momentum)

### 克服梯度小的問題

*   動量 (Momentum) 是另一種常用的訓練技巧，旨在加速收斂，並有助於**克服梯度消失 (Small Gradient) 的問題**，以及**逃離鞍點或局部最小值**。
*   當損失函數的 landscape 存在平緩區域 (Plateau) 或梯度接近於零的臨界點時，標準的梯度下降法可能會移動緩慢甚至停滯不前。

### 物理世界的類比

*   動量的概念可以類比成物理世界中的慣性。
*   想像一個球從斜坡上滾下來，即使遇到一個小的坡度 (類似局部最小值) 或平坦區域 (類似鞍點)，如果它之前累積了足夠的 **動量 (Momentum)**，仍然可能繼續滾動，甚至翻過小坡。

### 標準梯度下降 (Vanilla Gradient Descent)

*   回顧一下，標準的梯度下降法在每次更新參數 $\theta$ 時，都只是簡單地沿著當前梯度 $g$ 的反方向移動一小步：$$\theta_{t+1} = \theta_t - \eta g_t$$其中 $\eta$ 是學習率 (Learning Rate)。
![image](https://hackmd.io/_uploads/r1t_dKghJe.png)

### 梯度下降 + 動量 (Gradient Descent with Momentum)

*   加入動量的梯度下降法的更新規則如下:
    *   首先，計算當前的梯度 $g_t = \nabla L(\theta_t)$。
    *   然後，更新一個 **動量項 (Momentum Term)** $m_{t+1}$，它結合了前一步的動量 $m_t$ 和當前的負梯度 $-\eta g_t$：$$m_{t+1} = \lambda m_t - \eta g_t$$其中 $\lambda$ 是一個 **動量因子 (Momentum Factor)**，通常是一個介於 0 和 1 之間的超參數，用於控制前一個動量項的影響。
    *   最後，根據這個動量項來更新參數 $\theta_t$：$$\theta_{t+1} = \theta_t + m_{t+1}$$![image](https://hackmd.io/_uploads/BJkquKlhyx.png)

### 動量的運作方式

*   在每次移動參數時，我們不僅考慮當前的梯度方向，還會考慮 **上一次參數移動的方向**。
*   如果上一次的移動方向與當前的梯度方向一致，那麼本次的移動步長會更大，加速了在該方向上的收斂。
*   如果上一次的移動方向與當前的梯度方向相反，那麼本次的移動步長會減小，有助於抑制震盪。
*   從數學上看，動量項 $m_t$ 可以被視為**過去所有計算出的梯度的加權和**。較早的梯度影響會隨著時間的推移而衰減，衰減的程度由動量因子 $\lambda$ 控制。

### 動量的好處

*   **加速收斂**: 在梯度方向一致的區域，動量可以累積速度，加快參數更新的速度。
*   **克服平緩區域**: 即使在梯度很小的平緩區域，由於之前累積的動量，參數仍然可以繼續移動。
*   **有助於逃離局部最小值和鞍點**: 類似於物理世界中的慣性，動量可以幫助模型越過較小的局部最小值或在鞍點附近找到下降的方向。即使當前梯度為零，如果之前累積了動量，參數仍然可以沿著之前的方向繼續移動。

---

## 結論

*   **批次大小** 是一個重要的 **超參數**，它影響著訓練的速度、梯度的雜訊程度以及模型的泛化能力。
*   **較小的批次** 通常能帶來更好的優化效果和泛化能力，但每個 Epoch 的訓練時間可能更長。
*   **較大的批次** 可以加快每個 Epoch 的訓練速度，但在優化和泛化方面可能存在劣勢。
*   **動量** 是一種通過考慮過去的梯度信息來加速訓練並幫助模型逃離臨界點的有效技巧。
*   **較小的批次大小和動量都有助於逃離臨界點**，這與我們之前討論的局部最小值和鞍點問題相關。雜訊梯度和累積的動量都有助於模型探索更廣闊的參數空間，避免困在不良的局部最優解中。

---
---

# (三) 深度學習訓練技巧：自動調整學習速率 (Adaptive Learning Rate)

---

## 固定的學習速率的限制

在訓練神經網路時，遇到的最大障礙不一定是 **critical point**。
*   即使在非常簡單的 **凸函數 (convex)** 的 **error surface** 上，使用固定的學習速率的 **梯度下降 (gradient descent)** 也可能難以有效地找到最小值。
    *   例如，當 error surface 在不同方向上具有非常不同的坡度時，一個固定的學習速率可能在坡度陡峭的方向上導致震盪，而在坡度平緩的方向上移動過於緩慢。
    *   實驗顯示，即使是凸函數的 error surface，若學習速率 $\eta$ 設定不當（過大或過小），梯度下降也可能無法收斂到最小值。
![image](https://hackmd.io/_uploads/r1tbu8b2Jl.png)

---

## 為什麼需要自動調整學習速率？

*   **不同的參數可能需要不同的學習速率**。
    *   有些參數對 loss 的影響較大，梯度變化較劇烈，可能需要較小的學習速率以避免震盪。
    *   有些參數對 loss 的影響較小，梯度變化較緩慢，可能需要較大的學習速率以加速收斂。
*   **同一個參數在訓練的不同階段可能需要不同的學習速率**。
    *   例如，在訓練初期，可能需要較大的學習速率以快速探索參數空間。
    *   在訓練後期，當接近最小值時，可能需要較小的學習速率以進行更精細的調整，避免越過最小值。
![image](https://hackmd.io/_uploads/HJFud8Wnke.png)
*   當訓練停滯時（loss 不再下降），並不一定是因為梯度很小，很可能只是在 error surface 的平緩區域移動緩慢，或者在山谷的兩側震盪。

---

## 參數相依的學習速率 (Parameter Dependent Learning Rate)

*   為了克服固定學習速率的限制，我們引入了為每個參數客製化學習速率的概念。
*   **原始**的梯度下降更新公式為：$$\theta_{i}^{t+1} \leftarrow \theta_{i}^{t} - \color{red}{\eta} g_{i}^{t}$$其中，$\theta_{i}^{t}$ 是第 $t$ 次迭代時參數 $i$ 的值，$\eta$ 是固定的學習速率，$g_{i}^{t} = \frac{\partial L}{\partial \theta_{i}}|_{\theta=\theta^{t}}$ 是參數 $i$ 在第 $t$ 次迭代時的梯度。
*   引入**參數相依**的學習速率後，更新公式變為：$$\theta_{i}^{t+1} \leftarrow \theta_{i}^{t} - \color{red}{\frac{\eta}{\sigma_{i}^{t}}} g_{i}^{t}$$其中，$\sigma_{i}^{t}$ 是一個為每個參數 $i$ 在每個迭代 $t$ 計算的值，用於調整該參數的有效學習速率。

### 常見的 $\sigma_{i}^{t}$ 計算方法

#### 均方根 (Root Mean Square, RMS) - Adagrad

*   **Adagrad** 是一種早期實現參數相依學習速率的方法。
*   在 Adagrad 中，$\sigma_{i}^{t}$ 被計算為過去所有參數 $i$ 的梯度平方的平均值的平方根：
$$\sigma_{i}^{t} = \sqrt{\frac{1}{t+1} \sum_{j=0}^{t} (g_{i}^{j})^2}$$
    *   第一次更新 ($t=0$): $\sigma_{i}^{0} = \sqrt{(g_{i}^{0})^2} = |g_{i}^{0}|$。
    *   第二次更新 ($t=1$): $\sigma_{i}^{1} = \sqrt{\frac{1}{2} ((g_{i}^{0})^2 + (g_{i}^{1})^2)}$。
    *   ...
*   **Adagrad 的效果**:
    *   對於**梯度值較小**的參數（坡度平緩），$\sigma_{i}^{t}$ 會較小，導致有效學習速率 $\frac{\eta}{\sigma_{i}^{t}}$ 較大，參數**更新的步長也較大**。
    *   對於梯度值較大的參數（坡度陡峭），$\sigma_{i}^{t}$ 會較大，導致有效學習速率 $\frac{\eta}{\sigma_{i}^{t}}$ 較小，參數更新的步長也較小。
*   **Adagrad 的問題**:
    *   由於 $\sigma_{i}^{t}$ 會不斷累積過去梯度的平方，對於長期梯度都很小的參數，$\sigma_{i}^{t}$ 會變得非常小，導致後期的學習速率變得非常大，可能引起參數的劇烈震盪甚至**爆走**。
    *   反之，對於經常更新的參數，$\sigma_{i}^{t}$ 會持續增大，導致學習速率過早地變得非常小，使得訓練停滯不前。
![image](https://hackmd.io/_uploads/BJoI5LWhJe.png)

#### RMSProp

*   **RMSProp (Root Mean Square Propagation)** 是一種改進 Adagrad 的方法，旨在解決 Adagrad 學習速率過快衰減的問題。
*   RMSProp 的關鍵思想是使用**指數衰減平均 (exponentially decaying average)** 的平方根來計算過去梯度:$$\sigma_{i}^{t} = \sqrt{\color{red}{\alpha} (\sigma_{i}^{t-1})^2 + \color{red}{(1 - \alpha)} (g_{i}^{t})^2}$$
    *   然後梯度下降更新公式為 $\theta_i^{t+1} = \theta_i^t - \frac{\eta}{\sqrt{(\sigma_i^t)^2 + \epsilon}} g_i^t$ (為了避免分母為零，通常會加上一個很小的 $\epsilon$)。
    *   其中，$\alpha$ 是一個介於 0 和 1 之間的超參數，控制著過去梯度信息的衰減速率。 通常 $\alpha$ 的值接近 1 (例如 0。9 或 0。99)。
    *   $\sigma_{i}^{0} = (g_{i}^{0})^2$ (作為初始值)。
*   **RMSProp 的效果**:
    *   通過引入 $\alpha$，RMSProp 更側重於**最近的梯度**信息，使得學習速率能夠更靈活地適應 error surface 的局部特性。
    *   當梯度突然增大時，$(\sigma_{i}^{t})^2$ 會迅速增大，從而減小學習速率，有助於穩定訓練。
    *   當梯度持續很小時，由於衰減項的存在，$(\sigma_{i}^{t})^2$ 不會無限減小，避免了 Adagrad 中學習速率過快增長的問題。

#### Adam

*   **Adam (Adaptive Moment Estimation)** 是目前最廣泛使用的優化演算法之一。
*   **Adam 本質上是 RMSProp + Momentum**。
*   它不僅使用梯度的平方的指數移動平均來調整學習速率（類似 RMSProp），還使用梯度的指數移動平均來獲得更新的方向（類似 Momentum）。
*   Adam 的更新公式涉及到一階矩（梯度的移動平均）和二階矩（梯度平方的移動平均），並進行偏差校正。 由於公式較為複雜，詳細內容可以參考[原始論文](https://arxiv.org/pdf/1412.6980.pdf)。
*   PyTorch 等深度學習框架都內建了 Adam 優化器，並提供了預設的超參數，通常在許多情況下都能取得不錯的結果。

---

## 學習速率排程 (Learning Rate Scheduling)

*   除了為每個參數調整學習速率外，我們還可以隨著訓練的進行而調整**整體學習速率** $\eta$，這稱為 **學習速率排程 (Learning Rate Scheduling)**。

### 學習速率衰減 (Learning Rate Decay)

*   **學習速率衰減 (Learning Rate Decay)** 是一種常見的排程策略，隨著訓練的進行，**逐漸減小**學習速率 $\eta^t$$$\theta_{i}^{t+1} \leftarrow \theta_{i}^{t} - \color{red}{\frac{\eta^t}{\sigma_{i}^{t}}} g_{i}^{t}$$
*   這樣做的直覺是，在訓練初期，我們可能需要較大的學習速率以快速接近最小值附近；而在訓練後期，為了更精細地搜索最小值，避免在最小值附近震盪，需要較小的學習速率。
*   常見的衰減方式包括階梯衰減 (step decay)、指數衰減 (exponential decay) 和餘弦退火 (cosine annealing) 等。
![image](https://hackmd.io/_uploads/Bkb2pUb3Jg.png)

### Warm Up

*   **Warm Up** 是一種在訓練初期**先逐漸增大**學習速率，然後再按照某種策略（如衰減）**減小**學習速率的排程方法。
*   這種方法起初看起來違反直覺，但已被證明在訓練某些大型模型（如 Transformer 和 BERT）時非常有效。
*   **可能的解釋**:
    *   在訓練初期，模型的參數是隨機初始化的，對 error surface 的估計（例如 $\sigma_{i}^{t}$ 的計算）可能不準確，方差較大。
    *   使用較小的初始學習速率可以讓模型在初始階段進行更穩定的探索，收集關於 error surface 的更可靠的統計信息。
    *   隨著訓練的進行，當對 error surface 的估計更加準確後，再逐漸增大學習速率可以加快訓練進程。
![image](https://hackmd.io/_uploads/SJI8ALb2Jx.png)

*   Transformer 模型中就使用了一種 Warm Up 的排程策略，其學習速率的設定遵循一個特定的函數，先增大後減小。

---

## 總結與展望
* 自動調整學習速率的方法，例如 Adagrad、RMSProp 和 Adam，以及學習速率排程策略，例如學習速率衰減和 Warm Up，都是為了更有效地訓練神經網路，克服固定學習速率的局限性，使得訓練過程更加穩定和高效。
* 這些技術通過動態地調整每個參數或整體的學習速率，以適應 error surface 的不同特性，從而加速收斂並獲得更好的模型性能。

---
---

# (四) 深度學習訓練技巧：損失函數 (Loss) 也可能有影響

*   本次討論的是分類問題的快速入門。
*   存在較長的版本，可參考過去的上課錄影[2017上篇](https://youtu.be/fZAZUYEeIMg)和[2017下篇](https://youtu.be/hSXFuypLukA)，當時可能花費 2-3 小時討論分類。
*   本課程將直接介紹分類的做法。

---

## 分類問題(Regression)回顧
> [第一章](https://hackmd.io/SeTphOa5SSOlfEzjBQA9Zg#%E6%A9%9F%E5%99%A8%E5%AD%B8%E7%BF%92%E6%A6%82%E8%AB%96)
*   在分類問題中，我們的目標是將輸入資料 (通常是一個向量) 分配到預先定義的類別中。
*   與迴歸問題輸出一個數值不同，分類問題的輸出通常代表了資料**屬於哪個類別**的可能性。

---

## 將分類(Classification)視為迴歸(Regression)？

一個初步的想法是將分類問題視為迴歸問題。
*   我們可以將每個類別指定一個數字編號，例如 Class 1 為 1，Class 2 為 2，Class 3 為 3，然後訓練一個模型，使其輸出值盡可能接近正確類別的編號。
*   **問題點：** 這種方法存在潛在的瑕疵。 如果類別之間本身沒有固有的順序或距離關係，那麼使用數字編號會引入不必要的假設。 例如，假設我們有三個類別：貓、狗、鳥。將它們編號為 1、2、3 並不能合理地表示貓和狗比貓和鳥更「接近」。

---

## One-hot 向量表示類別

更常見的做法是使用 **One-hot 向量** 來表示類別。
*   如果我們有 $K$ 個類別，那麼每個類別都會被表示成一個 $K$ 維的向量，其中只有對應類別的那個元素是 1，其餘元素都是 0。
    *   例如，若有三個類別，則其 One-hot 向量可能表示為：
        *   Class 1: $\hat{y} = \begin{bmatrix} 1 \\ 0 \\ 0 \end{bmatrix}$
        *   Class 2: $\hat{y} = \begin{bmatrix} 0 \\ 1 \\ 0 \end{bmatrix}$
        *   Class 3: $\hat{y} = \begin{bmatrix} 0 \\ 0 \\ 1 \end{bmatrix}$
*   使用 One-hot 向量的好處是，它避免了在類別之間引入任何不必要的距離或相似性假設。 如果我們計算兩個不同 One-hot 向量之間的距離（例如歐氏距離），它們之間的距離都是相等的。

---

## 網路輸出與 Softmax 函數

如果我們的目標標籤 $\hat{y}$ 是一個向量 (例如 One-hot 向量)，那麼我們的神經網路的輸出 $y$ 也應該是一個相同維度的向量。
![image](https://hackmd.io/_uploads/rkginzDW2yl.png)
在分類問題中，我們通常會在網路的最後一層之後接一個 **Softmax 函數**，將網路的原始輸出 $y$ 轉換成 $y'$。

### Softmax 的作用：
*   將 $y$ 中的每個元素的值都縮放到 0 到 1 之間。
*   使得 $y'$ 中所有元素的總和等於 1。 這樣，$y'$ 可以被解釋為模型預測的各個類別的機率分佈。
![image](https://hackmd.io/_uploads/SyNBQP-nJx.png)

### Softmax 的數學表示：
對於一個輸入向量 $y = \begin{bmatrix} y_1 \\ y_2 \\ y_3 \end{bmatrix}$，Softmax 函數的輸出 $y' = \begin{bmatrix} y'_1 \\ y'_2 \\ y'_3 \end{bmatrix}$ 的每個元素計算方式如下：$$y'_i = \frac{e^{y_i}}{\sum_{j} e^{y_j}}$$例如：$$y'_1 = \frac{e^{y_1}}{e^{y_1} + e^{y_2} + e^{y_3}}$$$$y'_2 = \frac{e^{y_2}}{e^{y_1} + e^{y_2} + e^{y_3}}$$$$y'_3 = \frac{e^{y_3}}{e^{y_1} + e^{y_2} + e^{y_3}}$$
* Logit：Softmax 函數的輸入 $y$ 有時也被稱為 **logit**。
### 舉例：
:::info
* 今天要做一個關於動物的分類，分類結果有鳥類、哺乳類、魚類，將分類結果編號並做one-hot vector→有3個結果，做成3個 3 * 1 維陣列
    * 鳥類 = [1,0,0]
    * 哺乳類 = [0,1,0]
    * 魚類 = [0,0,1]
* input = $y_1, y_2, y_3$ = [3, 1, -3]
* output = [20, 2.7, 0.05]
* 通過Softmax → $y_1', y_2', y_3'$ = [0.88, 0.12, 0]
可發現與鳥類最接近
:::
### 二元分類與 Sigmoid：
在二元分類問題中，雖然也可以使用 Softmax 函數，但更常見的做法是使用 **Sigmoid 函數**。 對於兩個類別的情況，Sigmoid 和 Softmax 本質上是等價的。

---

## 分類問題的損失函數

定義好模型的輸出 $y'$ (經過 Softmax) 和真實標籤 $\hat{y}$ (One-hot 向量) 之後，我們需要一個 **損失函數** 來衡量模型預測與真實標籤之間的差距。 我們的目標是最小化這個損失函數，從而訓練出更好的模型。
*   常見的分類損失函數有以下兩種：

    ### 均方誤差 (Mean Squared Error, MSE)

    *   如同迴歸問題，我們也可以使用 **均方誤差 (MSE)** 來衡量 $y'$ 和 $\hat{y}$ 之間的距離。
    *   對於一個有 $K$ 個類別的分類問題，MSE 的計算方式如下:
        $$MSE = \sum_{i=1}^{K} (\hat{y}_i - y'_i)^2$$
    *   雖然可以使用 MSE，但在分類問題中，它並非最常用的選擇。

    ### 交叉熵 (Cross-entropy)

    *   在分類問題中，**交叉熵 (Cross-entropy)** 是一個更常用且更有效的損失函數。
    *   交叉熵的計算方式如下:
        $$Cross-entropy = - \sum_{i} \hat{y}_i \ln(y'_i)$$
    *   **最小化交叉熵與最大化似然性 (Likelihood) 的關係：** 最小化交叉熵在數學上等價於最大化似然性 (maximize likelihood)。儘管課程中沒有深入探討似然性，但了解這兩者是同一件事的不同表述是很重要的。

---

## 為什麼交叉熵更適合分類？(從優化的角度)

從 **優化 (optimization)** 的角度來看，**交叉熵比均方誤差更適合用於分類問題**。
*   **Error Surface 的影響：** 考慮一個三分類問題，真實標籤是 $\hat{y} = \begin{bmatrix} 1 \\ 0 \\ 0 \end{bmatrix}$，網路的輸出在經過 Softmax 後得到 $y' = \begin{bmatrix} y'_1 \\ y'_2 \\ y'_3 \end{bmatrix}$。 我們觀察當網路的原始輸出 $y_1$ 和 $y_2$ 變化時，使用 MSE 和交叉熵計算出的誤差平面 (Error surface) 的差異。
*   **MSE 的問題：梯度消失 (Vanishing Gradient)**
    *   當模型的預測非常不準確時（例如，$y_1$ 很小，$y_2$ 很大，導致 $y'_1 \approx 0$，$y'_2 \approx 1$，遠離真實標籤 $\begin{bmatrix} 1 \\ 0 \\ 0 \end{bmatrix}$），使用 MSE 計算出的誤差可能很大。
    *   然而，關鍵的問題是，在這種誤差很大的區域，**MSE 的梯度可能非常平緩，趨近於 0**。 這意味著在訓練初期，如果模型的預測很差，梯度下降法可能因為梯度太小而難以更新參數，導致**訓練停滯不前 (train 不起來)**。
    *   雖然使用一些優化器 (如 Adam) 可能能在梯度很小的地方自動調整學習速率，但使用 MSE 會使訓練更加困難，起步更慢。
*   **交叉熵的優勢：提供更有效的梯度**
    *   與 MSE 不同，即使在模型的預測與真實標籤相差很遠的情況下，**交叉熵的誤差平面仍然具有較大的斜率 (gradient)**。
    *   這使得梯度下降法能夠有效地更新參數，朝著正確的方向移動，從而更容易進行訓練。
    *   改變損失函數就像「直接把 error surface 炸平」，使得優化變得更容易。
![image](https://hackmd.io/_uploads/ryA_NP-hkl.png)

---

## PyTorch 中的交叉熵與 Softmax

*   在深度學習框架 PyTorch 中，**交叉熵損失函數通常會內建 Softmax 操作**。
*   這意味著當你在 PyTorch 中使用 `CrossEntropyLoss` 這個損失函數時，它會自動在你的網路輸出的最後一層應用 Softmax 函數，然後再計算交叉熵損失。
*   因此，如果在定義你的網路結構時，你已經在最後一層加入了 Softmax，那麼在使用 `CrossEntropyLoss` 時就會變成應用了兩次 Softmax，這是需要避免的。

---

## 結論

*   **損失函數的選擇對於分類模型的訓練至關重要**。
*   雖然均方誤差 (MSE) 也可以用於衡量預測與真實標籤之間的差距，但 **交叉熵 (Cross-entropy) 通常更適合分類問題，尤其是在多分類的情況下**。
*   交叉熵能夠在優化過程中提供更有效的梯度信息，即使在模型預測不準確的初期，也能夠引導模型進行有效的學習，避免訓練停滯等問題。
*   因此，在設計分類模型的訓練流程時，仔細選擇和理解損失函數的特性是非常重要的。

---
---

# (五) 深度學習訓練技巧：批次標準化 (Batch Normalization) 簡介

---

## 回顧：改變 Error Surface

*   我們在前幾節討論過，模型的訓練過程受到 **Error Surface (誤差平面)** 的影響。
*   崎嶇的 Error Surface 會使得訓練更加困難，例如，不同方向上的斜率差異很大時，固定的學習率可能難以取得好的效果。
*   **批次標準化 (Batch Normalization)** 的核心思想之一就是 **改變 Error Surface 的 landscape，使其更平滑，更容易訓練**。 這就像是把崎嶇的山路剷平，讓模型更容易找到最佳解。

---

## 問題的起點：不同維度的數值範圍差異

在一個簡單的線性模型中 ($y = W_1x_1 + W_2x_2 + b$)，如果輸入特徵的不同維度 ($x_1$ 和 $x_2$) 的數值範圍差異很大，可能會導致 Error Surface 在不同方向上的斜率差異也很大。
*   例如，如果 $x_1$ 的值都很小，那麼 $W_1$ 的微小變化對 Loss 的影響也會很小，導致在 $W_1$ 方向上的斜率很小。
*   相反地，如果 $x_2$ 的值都很大，那麼 $W_2$ 的微小變化就可能對 Loss 產生很大的影響，導致在 $W_2$ 方向上的斜率很大。

這種不同方向上坡度差異很大的 Error Surface 會使優化變得困難，需要仔細調整學習率等超參數。

---

## 特徵標準化 (Feature Normalization)

為了解決不同維度數值範圍差異過大的問題，一個常見的方法是進行 **特徵標準化 (Feature Normalization)**，目標是讓不同維度的特徵擁有**相似的數值範圍**，這樣有助於製造比較好的 Error Surface，使訓練更容易。
![image](https://hackmd.io/_uploads/BJUhMYb3ke.png)

*   **標準化 (Standardization)** 是一種常見的特徵標準化方法。
    *   對於第 $i$ 個維度的所有訓練資料，計算其**平均值 ($\mu_i$)** 和**標準差 ($\sigma_i$)**。
    *   然後，對於該維度的每一個數值 $x^{j}_i$，使用以下公式進行標準化：$$\tilde{x}^{j}_i = \frac{x^{j}_i - \mu_i}{\sigma_i}$$其中 $\tilde{x}^{j}_i$ 是標準化後的數值。
    *   經過標準化後，該維度的數值**平均值會接近 0，變異數會接近 1**。
![image](https://hackmd.io/_uploads/rkfMmKb3kl.png)

*   在深度學習中，通常會在將特徵輸入到網路之前進行特徵標準化。

### 深度學習中的考量

*   即使輸入特徵做了標準化，當資料通過神經網路的各個層時，每一層的輸出 (例如激活函數之前的 $z$ 值或激活函數之後的 $a$ 值) 的不同維度之間，其數值分布仍然可能存在很大的差異。
*   如果第二層的權重 ($W_2$) 所接收的輸入 ($a_1$ 或 $z_1$) 的不同維度之間數值分布差異很大，那麼訓練 $W_2$ 時也可能會遇到類似的問題。
*   因此，我們也可以考慮對神經網路**每一層的輸出**進行標準化。 實作上，在激活函數**之前或之後進行標準化差異不大**。
![image](https://hackmd.io/_uploads/HJeImY-2Jg.png)

---

## 批次標準化 (Batch Normalization) 的概念

*   **批次標準化 (Batch Normalization)** 就是在深度神經網路的每一層中，對該層的輸入進行標準化。
*   與傳統的特徵標準化在整個訓練集上計算均值和標準差不同，批次標準化是**在每一個 mini-batch 內部**計算每個特徵維度的均值和標準差。
*   假設對於某一層的輸入 $z = [z_1, z_2, 。。。, z_m]$ (一個 batch 中 $m$ 個樣本的某個特徵維度的值)，批次標準化的計算步驟如下:
    1.  **計算 batch 的均值 ($\mu_B$)**:
        $$\mu_B = \frac{1}{m} \sum_{i=1}^{m} z_i$$
    2.  **計算 batch 的變異數 ($\sigma^2_B$)**:
        $$\sigma^2_B = \frac{1}{m} \sum_{i=1}^{m} (z_i - \mu_B)^2$$
    3.  **對 $z$ 進行標準化 ($\hat{z}_i$)**: 為了避免除以零，通常會在分母加上一個很小的常數 $\epsilon$。
        $$\hat{z}_i = \frac{z_i - \mu_B}{\sqrt{\sigma^2_B + \epsilon}}$$
*   **批次標準化將一個 batch 內的每個特徵維度的數值都轉換為平均值接近 0，變異數接近 1 的分布**。

### 可學習的參數 $\gamma$ 和 $\beta$

*   在進行標準化之後，批次標準化通常還會引入兩個**可學習的參數：$\gamma$ (縮放因子)** 和 **$\beta$ (平移因子)**。 這些參數對於每一個特徵維度都有獨立的值。
*   標準化後的數值 $\hat{z}_i$ 會進一步轉換為：
    $$y_i = \gamma \hat{z}_i + \beta$$
*   **引入 $\gamma$ 和 $\beta$ 的原因**是，有時我們並不希望每一層的輸出都嚴格地遵循均值為 0，變異數為 1 的分布。 網路可以學習到在某些層保留原始的分布可能更有利於後續的學習。
*   在訓練的初期，**$\gamma$ 通常會初始化為 1，$\beta$ 初始化為 0**。
![image](https://hackmd.io/_uploads/ByDbrtbnkl.png)

### 批次標準化在測試 (Inference) 階段

在測試階段，我們通常**一次只處理一個或少數幾個樣本**，而不是一個完整的 batch。 因此，我們無法在測試階段計算 batch 的均值和變異數來進行標準化。
*   **解決方案**：在**訓練過程中，記錄每一個 batch 計算出的均值 ($\mu_B$) 和變異數 ($\sigma^2_B$) 的移動平均 (moving average)**:$$\bar{\mu} \leftarrow p\bar{\mu}+(1-p)\mu^t$$
*   在測試階段，我們就使用這些**移動平均的均值 ($\bar{\mu}$) 和變異數 ($\bar{\sigma}^2$)** 來進行標準化：
$$\hat{z}_{test} = \frac{z_{test} - \color{blue}{\bar{\mu}}}{\sqrt{\color{blue}{\bar{\sigma}}^2 + \epsilon}}$$然後再進行縮放和平移：
$$y_{test} = \gamma \ \hat{z}_{test} + \beta$$注意，這裡的 $\gamma$ 和 $\beta$ 是在訓練過程中學習到的參數。

### 批次標準化的優點

*   **加速訓練**：批次標準化可以使 Error Surface 更平滑，**允許使用更高的學習率**，加快收斂速度。
*   **提高模型的穩健性(robustness)**：批次標準化有助於**減少內在變項偏移 (Internal Covariate Shift)** 的影響，使得網路的每一層都能夠更穩定地學習 (儘管關於 ICS 是否是 BN 主要優勢的觀點存在爭議)。
*   **減少對初始化的依賴**：批次標準化可以減輕網路對參數初始化的敏感性。
*   **可能有一定的正規化效果**：由於每個 batch 的統計量都存在一定的隨機性，批次標準化可以被認為是一種輕微的正規化方式，有助於提高模型的泛化能力。
*   **可以更容易訓練更深的網路**。
![image](https://hackmd.io/_uploads/rksVut-2yl.png)

---

## 關於內在變項偏移 (Internal Covariate Shift) 的討論

*   **原始的批次標準化論文** 提出，訓練深度網路時，由於前幾層參數的更新，後續層接收到的輸入分布會發生變化，這被稱為 **內在變項偏移 (Internal Covariate Shift, ICS)**。 BN 的作者認為，通過標準化每一層的輸入，可以減輕這種偏移，從而加速訓練。
![image](https://hackmd.io/_uploads/HyE7FYb2yl.png)

*   然而，**後續的研究** (例如 "[How Does Batch Normalization Help Optimization?](https://arxiv.org/abs/1805.11604)") 對 ICS 的觀點提出了質疑。 這些研究認為，**批次標準化更主要的優勢在於它平滑了 Error Surface，使得優化更容易**。 實驗結果也支持了 BN 可以改變 Error Surface 的 landscape。
*   作者甚至認為，BN 的積極影響可能在某種程度上是 **"serendipitous" (意外發現(有好結果)的、僥倖的)**，就像盤尼西林的發現一樣，儘管其確切機制仍在討論中，但它確實是一個有用的方法。

---

## 其他標準化方法

批次標準化並非唯一的標準化方法，還有其他變體和相關技術，例如：
*   **層標準化 ([Layer Normalization)](https://arxiv.org/abs/1607.06450)**
*   **實例標準化 ([Instance Normalization)](https://arxiv.org/abs/1607.08022)**
*   **群組標準化 ([Group Normalization)](https://arxiv.org/abs/1803.08494)**
*   **權重標準化 ([Weight Normalization)](https://arxiv.org/abs/1602.07868)**
*   **批次再標準化 ([Batch Renormalization)](https://arxiv.org/abs/1702.03275)**
*   **譜歸一化 ([Spectrum Normalization)](https://arxiv.org/abs/1705.10941)**

這些方法在不同的場景和網路結構中可能會有不同的效果。

---

## 總結

*   **批次標準化 (Batch Normalization) 是一種在深度神經網路中廣泛使用的技術**。
*   **它的主要目的是通過在每個 mini-batch 內部對每一層的輸入進行標準化，來加速訓練並提高模型的穩定性**。
*   **批次標準化還引入了可學習的縮放 $(\gamma)$ 和平移 $(\beta)$ 參數，使得網路可以靈活地調整每一層輸出的分布**。
*   **在測試階段，使用訓練過程中計算的均值和變異數的移動平均進行標準化**。
*   **儘管關於其有效性的確切原因仍在討論中，但實驗證明批次標準化是一種非常有用的技術，可以顯著改善深度學習模型的訓練過程**。

---

回[主目錄](https://hackmd.io/@Jaychao2099/aitothemoon/)