# 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**