# 論文閱讀 : QLoRA [論文連結](https://arxiv.org/pdf/2305.14314) ## 研究核心 - QLoRA 是一種高效的微調方法,允許在 單張 48GB GPU 上微調 65B 參數模型,同時保留接近 完整 16-bit 微調效能。 - 方法:將梯度反向傳播至 Low-Rank Adapters (LoRA),而非原始模型,後者是4-bit 量化的 frozen 預訓練模型。 - 所訓練的 Guanaco 模型系列 在 Vicuna benchmark 上表現出色,達到 ChatGPT 效能的 99.3%。 - 僅需 24 小時在單顆 GPU 上完成微調。 ### 技術核心 - 4-bit NormalFloat (NF4): - 為常態分布權重設計的資訊理論最佳 4-bit 數據類型。 - Double Quantization: - 將量化常數進行再次量化,進一步壓縮記憶體需求。 - Paged Optimizers: - 解決訓練過程中的記憶體尖峰問題。 ### 大規模實驗與分析 - 使用 QLoRA 微調超過 1,000 個模型,橫跨: - 8 個 instruction dataset - 多種模型架構(如 LLaMA、T5) - 多種模型規模(如 33B、65B) - 即使使用較小模型,配合高品質資料集,也能超越先前 SOTA 模型。 #### 評估與觀察 - 使用 GPT-4 評估 代替人類評估,發現兩者高度一致,可作為成本效益高的替代方案。 - 指出目前常見 chatbot benchmark 存在可信度問題。 ### Block-wise k-bit Quantization **給定傳統量化公式 Equation (1)** $$ \mathbf{X}^{\text{Int8}} = \text{round}\left( \frac{127}{\text{absmax}(\mathbf{X}^{\text{FP32}})} \cdot \mathbf{X}^{\text{FP32}} \right) $$ 其中: * $\mathbf{X}^{\text{FP32}}$:原始浮點數張量 * $\mathbf{X}^{\text{Int8}}$:量化後的整數張量 * $c = \frac{127}{\text{absmax}}$:量化常數(scale factor) **反量化** $$ \mathbf{X}^{\text{FP32}} = \frac{\mathbf{X}^{\text{Int8}}}{c} $$ ### 全域量化的問題:Outlier 影響 因此採用 Block-wise Quantization,將張量切成「小區塊(blocks)」,**每個區塊單獨計算自己的 absmax 與量化常數** #### 作法: 1. 假設輸入張量為 $\mathbf{X} \in \mathbb{R}^{b \times h}$。 2. 將它**展平成一維向量**,然後切成大小為 $B$ 的 $n$ 個連續區塊(block)。 $$ n = \frac{b \times h}{B} $$ 3. 每個 block 都**單獨使用 Equation (1)** 做量化,得到對應的量化常數 $c_i$。 ### 顯存需求 : LoRA 在訓練期間的效能與負載 - LoRA 的記憶體佔用非常低 - LoRA 的引入僅需極少量的參數(約為原始模型的 0.2%)。 - 在 LLaMA 7B 模型上,LoRA 參數僅佔 26 MB。 - 主要記憶體瓶頸在於梯度(activations gradients) - 即使使用 LoRA,訓練時仍需儲存 LoRA 輸入梯度: - 原始未優化:567 MB - 使用 gradient checkpointing 後可降低至:18 MB / 序列 - ➜ 仍然遠大於 LoRA 參數本身的大小 - 由於 LoRA 本身極輕量,可以增加更多 Adapter 以提高效能,而不會大幅增加訓練記憶體。 - 這對於恢復接近 full 16-bit 精度的效能非常關鍵。 ## 方法重點 - 目標:在 單台機器上穩定進行高效的 4-bit finetuning,同時保留接近 full-precision 效能。 - 三大技術 - 4-bit NormalFloat (NF4):一種為常態分布優化的量化格式 - Double Quantization:進一步壓縮記憶體 - Paged Optimizers:避免 gradient checkpointing 過程中的記憶體尖峰導致 OOM ### 訓練與量化流程架構 - 儲存格式:4-bit(低精度) - 運算格式:BFloat16(計算用) - 運算流程:使用時先 dequant 到 BFloat16,再進行 16-bit matrix multiplication ### 4-bit NormalFloat (NF4) - 建立於 Quantile Quantization:透過分位數讓每個 quantization bin 有等量的數值落入,是資訊理論上的最佳方式。 - 針對常態分布優化 - 多數神經網路權重具有 0 均值、標準差為 σ 的常態分布。 - 將所有 weight tensor 經過標準化(rescale 到標準常態分布),就可以精確地使用固定 quantile 值來量化。 - 過程 - 1. 將理論標準常態分布 $N(0, 1)$ 分成 $2^k + 1$ 段,取得其 quantile 值 - 2. 把這些 quantile 值正規化到 $[-1, 1]$ - 3. 將實際的 weight tensor 也正規化到 $[-1, 1]$,即可對應到這些量化 bin - 計算每個 bin 的代表值: $$ q_i = \frac{1}{2}\left( Q_X\left(\frac{i}{2^k+1}\right) + Q_X\left(\frac{i+1}{2^k+1}\right)\right) $$ #### Asymmetric NormalFloat * **問題**:對稱的 k-bit 量化無法保證剛好有「0」這個離散值,但這對於 padding 和零值元素至關重要(在 Padding token、Masking 的 zero 值、稀疏矩陣中本來就是 0 的元素,這些「本身就該是零」的數值,在量化時必須能夠被準確表示為零)。 * **解法**:分別對負值與正值區間取不同數量的 quantile(如負側 $2^{k-1}$,正側 $2^{k-1}+1$),合併後移除重複的 0。 * 最終結果:稱為 **NFk(NormalFloat-k)**,能保證: * 0 為可精確表示的值 * 每個 bin 期望落入等量數值 * 適合 zero-centered normal 分布,為資訊理論上最優的量化方案 ### Double Quantization - 目的:進一步降低記憶體佔用 - 雖然 4-bit 精準量化需要較小的 block size(如 64),但這會帶來額外的記憶體開銷,因為每個 block 都需要額外儲存一個 32-bit 的量化常數(scale)。 - 在 block size 為 64 的情況下,這等同於 每個參數多佔用 0.5 bits。 **記憶體節省效果** | 項目 | 計算方式 | 每參數佔用 (bits) | | ----------------------------- | ------------------------------ | ---------------- | | 原始 32-bit 常數(block size = 64) | $32 / 64$ | **0.5 bits** | | DoubleQuant 後 | $8 / 64 + 32 / (64 \cdot 256)$ | **≈ 0.127 bits** | 🔻 節省:**0.373 bits/參數** #### 量化「量化常數」本身 - 第一層量化: - 原始張量 $\mathbf{W}$ → 使用 4-bit 量化 - 會得到一組 **32-bit 的量化常數** $c_2^{\text{FP32}}$ - 第二層量化(DoubleQuant) - 將這些量化常數 $c_2^{\text{FP32}}$ 當作輸入 - 使用 **8-bit Float** + block size 256 進行再次量化: - 得到 **量化後的量化常數** $c_2^{\text{FP8}}$ - 以及 **新的量化常數** $c_1^{\text{FP32}}$ - 因為 $c_2^{\text{FP32}}$ 為正值,為了更有效率地量化,先 **做 mean subtraction**,使其中心化,再使用**對稱量化**(更節省 bits)。 ### 完整定義 ### Forward Pass 計算公式: $$ \mathbf{Y}^{\text{BF16}} = \mathbf{X}^{\text{BF16}} \cdot \text{doubleDequant}(c_1^{\text{FP32}}, c_2^{\text{k-bit}}, \mathbf{W}^{\text{NF4}}) + \mathbf{X}^{\text{BF16}} \cdot \mathbf{L}_1^{\text{BF16}} \cdot \mathbf{L}_2^{\text{BF16}} $$ 其中 | 項目 | 說明 | | ----------------------------- | ---------------------------- | | $\mathbf{X}^{\text{BF16}}$ | 輸入資料(已轉為 BFloat16) | | $\mathbf{W}^{\text{NF4}}$ | 儲存為 4-bit NormalFloat 的權重 | | $\text{doubleDequant}(\cdot)$ | 將權重從 NF4 經雙層反量化,轉回 BF16 精度 | | $\mathbf{L}_1, \mathbf{L}_2$ | LoRA adapter 的可訓練權重(BF16 精度) | | $\mathbf{Y}^{\text{BF16}}$ | 最終輸出結果,仍在 BF16 精度下 | #### Double Dequantization $$ \text{doubleDequant}(c_1^{\text{FP32}}, c_2^{\text{k-bit}}, \mathbf{W}^{\text{k-bit}}) = \text{dequant}(\text{dequant}(c_1, c_2), \mathbf{W}) $$ * 先將量化常數 $c_2^{\text{k-bit}}$ 使用 $c_1^{\text{FP32}}$ 做反量化 → 得到 FP32 scale * 再用這個 scale 去反量化 $\mathbf{W}^{\text{NF4}}$ → 得到 $\mathbf{W}^{\text{BF16}}$ | 元件 | Blocksize | 精度 | 理由 | | ------------ | --------- | --------- | ------------------- | | $\mathbf{W}$ | 64 | 4-bit NF4 | 提高量化精度 | | $c_2$ | 256 | FP8 | 減少儲存成本(DoubleQuant) | ### 實驗與分析 #### 核心問題與目標 - 問題:QLoRA 是否能在極低記憶體需求下,表現接近或等同 full-model finetuning? - 進一步探討: - NF4 資料型態 vs. 一般 4-bit 浮點數的表現差異 - 各元件(如 Double Quantization、PagedOptim)對效能的貢獻與限制 #### 實驗觀察 #### 模型與資料集 * 模型涵蓋:RoBERTa、T5(80M~11B)、LLaMA(7B~65B) * 任務資料集: * **GLUE**(文本分類) * **Super-NaturalInstructions**(指令式任務) * **MMLU**(5-shot 評估) * 評估指標: * GLUE:Accuracy * Super-NaturalInstructions:Rouge-L * MMLU:5-shot accuracy #### 資料型態比較 * Int4 * FP4(E2M1、E3M0 variants) * **NF4 + Double Quantization** * 所有模型尺寸:125M ~ 65B 1. 預設 LoRA 設定 無法達到 full finetuning 效能 - 常見做法只對 query / value 做 LoRA,對於大型模型(如 LLaMA 7B)來說 不夠用。 - 要達到 16-bit 全微調表現,需要對 所有 Transformer block 中的線性層都加入 LoRA。 - 投影維度$r$等超參數影響反而不大。 ![image](https://hackmd.io/_uploads/HkI7JwPLlg.png) 2. 圖表(Figure hyper)說明 - Stanford Alpaca 預設超參數 vs. QLoRA 全層 LoRA 超參數 - 發現 QLoRA 搭配合理超參數能接近甚至超越 full finetuning 3. NF4 > 其他 4-bit 資料型態 - 實驗資料:Common Crawl 子集(Perplexity 評估) - 使用模型:OPT, BLOOM, LLaMA, Pythia - | 資料型態 | 平均 Perplexity (PPL) | | ------------- | ------------------- | | Int4 | 34.34 | | Float4 (E2M1) | 31.07 | | Float4 (E3M0) | 29.48 | | **NF4 + DQ** | **27.41** | **NF4 + Double Quantization** 在保留精度與節省記憶體之間達到最佳平衡。 #### 可恢復 4-bit 量化帶來的效能損失 * 雖然 4-bit inference 通常會降低準確率,但透過 **adapter-based finetuning(如 QLoRA)** 可**完全恢復性能** * 在 GLUE 與 Super-NaturalInstructions 任務中: * **16-bit LoRA ≒ 8-bit ≒ 4-bit QLoRA(NF4) ≒ Full finetuning** * 在 LLaMA 7B~65B + MMLU 評估中: * **QLoRA(NF4+DQ)** 幾乎與 16-bit LoRA 相同 * 使用 **FP4** 則落後約 **1% 的準確率** #### 實驗表格 | 方法 | GLUE (Acc.) | T5-3B RougeL | T5-11B RougeL | | ------------------ | ----------- | ------------ | ------------- | | BF16 全微調 | 88.6 | 54.3 | 62.0 | | LoRA BF16 | 88.8 | 55.4 | 60.7 | | QLoRA Int8 | 88.8 | 56.5 | 60.7 | | QLoRA FP4 | 88.6 | 55.6 | 60.9 | | **QLoRA NF4 + DQ** | - | **55.3** | **60.9** | #### 不同資料型態下的 LLaMA 模型 MMLU 表現比較 * 比較 LLaMA 模型在不同參數規模(7B、13B、33B、65B)下,使用不同精度資料型態微調後,在 **5-shot MMLU** 測試的平均正確率。 * 微調資料集包含 **Alpaca** 與 **FLAN v2** * 資料型態包括: * BFloat16(全精度) * Float4(低精度) * **NormalFloat4 + Double Quantization(NF4 + DQ)** ### 表現結果(平均 MMLU Accuracy) | 資料型態 | 7B | 13B | 33B | 65B | 平均 | | ------------ | ------------- | ------------- | ------------- | ------------- | ---------- | | **BFloat16** | 38.4–45.6 | 47.2–50.6 | 57.7–60.5 | 61.8–62.5 | 53.0 | | **Float4** | 37.2–44.0 | 47.3–50.0 | 55.9–58.5 | 61.3–63.3 | 52.2 | | **NF4 + DQ** | **39.0–44.5** | **47.5–50.7** | **57.3–59.2** | **61.8–63.9** | **53.1** | 結論: * **NF4 + DQ 完全重現 BFloat16 的表現** * **Float4 consistently 落後約 1%** ![image](https://hackmd.io/_uploads/HyHb8vvLee.png) ### 主要結論 - 最佳模型僅用 約 9,000 條樣本訓練 - 支持「資料品質 > 數量」的觀點,與 LIMA, PALMS 一致 - 僅使用 Cross-Entropy(監督學習),無需 RLHF,即可達 SOTA 表現 - 在 MMLU 與聊天任務中甚至超越 16-bit 模型與商用系統 (MMLU 測的是知識與分類(如考試),Vicuna 測的是對話互動品質) - 33B 模型可在單張 24GB GPU 上 <12 小時完成