---
# System prepended metadata

title: Optimizer
tags: [ML]

---

# Optimizer

### **📌 為什麼需要優化器？**
**更新權重 $w$ 來最小化損失函數 $L(w)$**，通常使用梯度下降（Gradient Descent）的方法。

## **1. 基礎：梯度下降（Gradient Descent）**
梯度下降的基本公式：
$$
w_{t+1} = w_t - \eta \nabla L(w_t)
$$
其中：
- $w_t$ 是當前權重
- $\eta$ 是學習率（Learning Rate）
- $\nabla L(w_t)$ 是損失函數的梯度

**梯度下降的挑戰**
- **學習率調整困難**：
    - Learning rate 小 → 收斂慢
    - Learning rate 大 → 發散
- **saddle points 與 local minimum**：
    - 梯度可能變得非常小，導致模型無法學習
- **high dimemsion data 收斂慢**：
    - 參數量巨大，梯度更新變得困難


## **2. Adam（Adaptive Moment Estimation）**
Adam 是目前最受歡迎的優化器之一，結合了 **Momentum** 和 **RMSprop** 的優勢。

### **🔹 Adam 公式**
Adam 使用了兩個指數加權移動平均：
- **一階動量（Momentum）**：$\beta_1$ 控制 **梯度的累積**
- **二階動量（RMSprop）**：$\beta_2$ 控制 **梯度平方的累積**
  
$$
m_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t
$$
$$
v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2
$$
$$
\hat{m}_t = \frac{m_t}{1 - \beta_1^t}, \quad \hat{v}_t = \frac{v_t}{1 - \beta_2^t}
$$
$$
w_{t+1} = w_t - \frac{\eta}{\sqrt{\hat{v}_t} + \epsilon} \hat{m}_t
$$

### **🔹 直覺理解**
1. **Momentum（動量）**：類似於 **物理上的慣性**，讓參數往相同方向移動，使收斂更快。
2. **RMSprop**：防止梯度更新過大，穩定學習過程。
3. **Bias Correction（偏差修正）**：解決指數加權移動平均的偏差問題。

### **hyperparameters**
- $\beta_1 = 0.9$（控制一階動量）
- $\beta_2 = 0.999$（控制二階動量）
- $\epsilon = 10^{-8}$（避免分母為 0）

### **Pros**
✅ 適用於大多數場景  
✅ 具備 Momentum（動量），加快收斂  
✅ 具備 RMSprop，能穩定梯度更新  
✅ 避免局部極小值，適用於非凸函數  

### **Cons**
❌ **學習率調整較敏感**（某些情況 Adam 可能不如 SGD 收斂得好）  
❌ **在 LLM 訓練時效能不一定最佳**（大型模型可能需要更進階的優化器）

### **🔹 Python Code**
```python
import torch
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
```

---

## **3. LAMB（Layer-wise Adaptive Moments for Batch Training）**
LAMB 是 **針對大批量訓練（Large Batch Training）** 設計的優化器，被 **Google 提出並用於 BERT pre-training**。

### **🔹 為什麼需要 LAMB？**
- 在 NLP 模型（如 GPT, BERT）訓練時，**使用大批量（Batch Size > 1024）訓練** 可以提高 GPU 計算效率，但 Adam 在大批量時不穩定，可能導致 **梯度爆炸或收斂變慢**。

### **🔹 LAMB 公式**
LAMB 修改了 Adam 的權重更新方式：
1. **先使用 Adam 計算梯度方向**
2. **再加上 Layer-wise Normalization，控制學習率變化**
$$
r_t = \frac{\| w_t \|}{\| \Delta w_t \|} 
$$ 
$$
w_{t+1} = w_t - \eta \cdot r_t \cdot \frac{\Delta w_t}{\| \Delta w_t \|}
$$
其中：
- $\Delta w_t$ 為 Adam 計算的梯度
- $r_t$ 是 Layer-wise Normalization

### **pros**
✅ **適用於大批量訓練（Batch > 1024）**  
✅ **提升 BERT/GPT 等 Transformer 的訓練效率**  
✅ **穩定性更高，不會因 batch size 變大而影響梯度更新**  

### **cons**
❌ **適用於特定場景（大模型預訓練）**  
❌ **批量太小時（<512）可能效果不佳**  

### **Python**
```python
from transformers import AdamW
from apex.optimizers import FusedLAMB  # NVIDIA Apex 支援 LAMB

optimizer = FusedLAMB(model.parameters(), lr=0.01)
```

---

## **4. Adafactor**
Adafactor 是 **針對大規模 Transformer 訓練的內存優化版本**，主要用於 **Google T5** 及大規模 LLM 訓練。

### **為什麼需要 Adafactor？**
- **問題：Adam 和 LAMB 需要存儲額外的梯度資訊**（一階和二階動量）
- **解決方案：Adafactor 減少內存開銷**
  - 它不存儲完整的動量，而是 **只存儲某些維度的動量**，降低內存使用。

### **Formula**
Adafactor 的核心思想是 **分解二階動量**，只存儲行或列的統計資訊：
$$
v_t = \frac{1}{m} \sum_{i=1}^{m} g_{t, i}^2 
$$
然後更新參數：
$$
w_{t+1} = w_t - \frac{\eta}{\sqrt{v_t} + \epsilon} g_t
$$

### **Pros**
✅ **適用於超大模型（T5, GPT）**  
✅ **減少內存開銷（適合 TPUs 和大規模分布式訓練）**  
✅ **對於 Transformer 類模型表現良好**  

### **Cons**
❌ **收斂速度可能比 Adam 慢**  
❌ **不適用於小模型訓練**  

### **Python**
```python
from transformers import Adafactor

optimizer = Adafactor(model.parameters(), scale_parameter=True, relative_step=True, warmup_init=True, lr=None)
```

---

# **📌 總結**
| Optimizer | 適用場景 | 內存開銷 | 主要特性 |
|-----------|--------|--------|--------|
| **Adam** | 一般場景（CNN, RNN, Transformer） | 高 | 動量 + RMSprop，適用於大多數情況 |
| **LAMB** | **大批量訓練（Batch > 1024）** | 高 | 適用於 BERT/GPT 等大型模型 |
| **Adafactor** | **超大規模 Transformer（T5, GPT-3）** | **低** | 省內存，適合 TPU 訓練 |

✅ **普通模型** → **Adam**  
✅ **大規模 NLP 訓練（BERT, GPT）** → **LAMB**  
✅ **超大模型（T5, GPT-3）** → **Adafactor**  