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