# 論文閱讀 : GPTQ
[論文連結](https://arxiv.org/pdf/2210.17323)
## 研究動機
- GPT/OPT 等大型預訓練語言模型雖然表現卓越,但 推論成本極高,常需多張高效能 GPU。
- 現有模型壓縮技術在應對這些 超大規模模型(如 GPT-175B)時效能與適用性受限。
- 方法核心
- GPTQ 是一種新的 一次性(one-shot)權重量化方法。
- 基於 近似二階資訊(approximate second-order information)。
- 能有效將 GPT-175B 的權重量化至 3 或 4 bit,且 準確率幾乎無損。
- 可在 約 4 小時 / 4 張 GPU 完成 175B 模型的量化。
- 壓縮效能
- 相比以往的 one-shot 量化方法,壓縮率提升超過 2 倍。
- 首次實現將 GPT-175B 單卡執行生成任務。
- 推論加速
- 相比 FP16 模型,推論加速比:
- NVIDIA A100:3.25 倍
- NVIDIA A6000:4.5 倍
- 極端量化:
- 也可應用在 2-bit 或 ternary(-1, 0, 1) 等極端情境,仍有可接受準確度。
### 現有壓縮技術的限制
- 傳統方法如稀疏化(sparsity)、剪枝(pruning)、或 retraining-based 量化成本過高,不適用於百億參數模型。
- 一次性(one-shot)後訓練量化(Post-Training Quantization, PTQ) 是一條可行方向:
- 無需 retraining。
- 但目前 PTQ 方案多數 僅能處理 8-bit 精度。
- 先前的 work 如 RTN(round-to-nearest)在高壓縮比(如 3-bit)下 準確度大幅下降。

## Related Work
### 量化方法分類
- 兩大類量化方法:
- 訓練中量化(Quantization-aware Training, QAT)
- 在 retraining / finetuning 時量化參數。
- 利用可微分的近似 rounding 操作(如 STE)。
- 成本高、不適合百億參數模型。
- 後訓練量化(Post-training Quantization, PTQ)
- 對 已訓練模型直接量化,只需少量資料與數小時計算。
- 適合 無法 retrain 的超大模型(GPTQ 聚焦此類方法)。
### 大型語言模型的量化方法現況
**目前主流應用於 GPT-175B 或 BLOOM 類大型模型的方案包括:**
| 方法 | 技術概述與限制 |
| -------------- | ------------------------------------------------------------------------------- |
| **ZeroQuant** | 使用 RTN(round-to-nearest)搭配 layer-wise distillation,但僅支持到 **1.3B** 模型;已耗時 \~3 小時 |
| **LLM.int8()** | 發現 activation outlier 是問題根源,保留部分 feature dimension 為高精度解決此問題 |
| **nuQmm** | 開發基於 binary-coding 的自定義 GPU kernel,以提升運算效率
## Background
### Layer-Wise Quantization(逐層量化)
- GPTQ 採用 逐層處理、層內優化 的後訓練量化策略,這與先前的 PTQ 方法類似(如 AdaRound、OBQ 等)。
- 基本目標為:對每個線性層,找到量化後權重 $\widehat{\mathbf{W}}$,使其對輸出誤差最小:
$$
\arg\min_{\widehat{\mathbf{W}}} \, \|\mathbf{W} \mathbf{X} - \widehat{\mathbf{W}} \mathbf{X}\|_2^2
$$
* 條件假設:
* 量化 grid(即可選取的值)在優化前就已固定。
* Quantization Grid : 定義「哪些值是允許的」。這些可被選擇的離散值
* GPTQ 的流程會先為每一層的權重矩陣 $\mathbf{W}$ 決定一組固定的 quantization grid,接下來就只能從這組值中選出近似的替代值。
* 權重可以自由移動至任一 grid 上的點(非固定 mapping)。
* 每個權重不是「被迫」選最接近的格點,而是可以選擇任一格點,以最小化整體輸出誤差(通常是 layer 的 output MSE)。由一個全局最小誤差策略來決定該選哪個。
### Optimal Brain Quantization (OBQ) 方法簡介
**GPTQ 的技術建立於 OBQ 方法之上**
#### OBQ 的基本邏輯
- 逐行(row-wise)處理權重矩陣 $\mathbf{W}$。
- 假設你有一個線性層的權重矩陣 $\mathbf{W}$,它的 shape 是 $(\text{out_features}, \text{in_features})$,也就是:
- 一共有很多行,每一行 $\mathbf{w}$ 是對應一個輸出神經元的權重向量。
- 先處理第 1 行 $\mathbf{w}\_1$(一個 output neuron 的權重),
- 再處理第 2 行 $\mathbf{w}\_2$,
- 以此類推。
- 對每一行 $\mathbf{w}$,每次只量化一個權重 $w_q$,並同時調整其餘尚未量化的權重(set $F$)以補償誤差。
1. 假設這一行 $\mathbf{w}$ 有 10 個權重:$[w_1, w_2, ..., w_{10}]$
2. 一開始都還是 full-precision 的(例如 float16),我們稱尚未量化的集合為 $F$(initially 是全體)。
3. OBQ 每次只挑選一個「最適合先量化的權重」$w\_q$,這個選擇是根據量化後造成的 **誤差與補償能力** 來決定的(透過 Hessian 計算)。
4. 一旦決定量化 $w\_q$,就會:
- 把 $w\_q$ 量化到 grid 上的某個點(例如從 0.37 → 0.5)。
- 同時根據公式計算一個補償量 $\boldsymbol{\delta}\_F$,**即時修正尚未量化的其餘權重**,讓整體 layer output 誤差最小化。
- 然後把 $w\_q$ 從 $F$ 中移除,進入下一輪,直到這一行的所有權重都被量化。
- 使用二階資訊(Hessian)來決定最佳要量化的權重與補償更新量:
$$
w_q = \arg\min_{w_q} \frac{(\text{quant}(w_q) - w_q)^2}{[\mathbf{H}^{-1}]_{qq}}
$$
$$
\boldsymbol{\delta}_F = - \frac{w_q - \text{quant}(w_q)}{[\mathbf{H}^{-1}]_{qq}} \cdot (\mathbf{H}^{-1})_{:, q}
$$
其中 $\mathbf{H} = 2\mathbf{X}\_F\mathbf{X}\_F^\top$ 是 Hessian。
- 每次量化完一個 $w\_q$ 後,更新 Hessian 的逆矩陣:
$$
\mathbf{H}^{-1}_{-q} = \left(\mathbf{H}^{-1} - \frac{1}{[\mathbf{H}^{-1}]_{qq}} \mathbf{H}^{-1}_{:, q} \mathbf{H}^{-1}_{q, :} \right)_{-p}
$$
## The GPTQ Algorithm
### **Step 1:任意順序量化的洞察(Arbitrary Order Insight)**
* **OBQ 做法**:原本是根據「當下誤差最小」的方式,**貪婪(greedy)地選擇下一個要量化的權重**。
* **GPTQ 發現**:其實對於大型、參數多的 layer,「照固定順序」量化的效果 **幾乎跟 greedy order 一樣好**。
* 解釋 : 被量化順序較後的「大誤差權重」,雖然最後才量化,但**此時已經沒剩多少可補償的權重**,所以效果也差不多。
* 只要固定任意順序(如按列順序量化),**整體誤差差不了太多**。
#### 好處
- 原本 OBQ 是「每一行(row)各自做量化順序決策」,所以會產生 **每行一套自己的未量化權重集合 $F$ 和對應的 Hessian $\mathbf{H}\_F$**。
- 改為 **所有行共用同一個量化順序**(例如「第 1 列的所有 row weight 先量化」→「再量化第 2 列的所有 row weight」……)。
- 因為 $\mathbf{H}\_F$ **只與輸入 $\mathbf{X}\_F$ 有關**(所有行共享同一組輸入),因此:
- $\mathbf{H}\_F^{-1}$ 可共用
- **只需做 $d\_\text{col}$ 次更新,而不是 $d\_\text{row} \cdot d\_\text{col}$ 次。**
#### 結果
* GPTQ 量化計算量由:
$$
O(d_\text{row} \cdot d_\text{col}^3) \quad \Rightarrow \quad O(\max\{ d_\text{row} \cdot d_\text{col}^2, \; d_\text{col}^3 \})
$$
* 計算量減少了 **$\min{d\_\text{row}, d\_\text{col}}$ 倍**,對大型模型來說是數個數量級的加速。
### 更新 Hessian 的實作瓶頸
### Compute-to-Memory Ratio 過低:
### 解決方法 : Lazy Batch Updates(延遲批次更新)
* 以公式:
$$
\mathbf{H}_{-q}^{-1} = \left( \mathbf{H}^{-1} - \frac{1}{[\mathbf{H}^{-1}]_{qq}} \mathbf{H}^{-1}_{:, q} \cdot \mathbf{H}^{-1}_{q, :} \right)_{-q}
$$
為例,
* 雖然每次只需做幾個 FLOPs,
* 但要對整個 $\mathbf{H}^{-1}$ 做更新(記憶體讀寫開銷大),導致 **運算速度被記憶體頻寬限制住**,GPU 無法發揮效能。
#### 作法
* 一次處理 $B = 128$ 個欄位(columns):
* 暫時**只更新 $B \times B$ 的區塊(block)**,在 $\mathbf{H}^{-1}$ 中只動用相關區域。
* 處理完這一批之後,再做一次完整的「全域」更新:
* 更新整體的 $\mathbf{H}^{-1}$ 和 $\mathbf{W}$(權重矩陣)。
#### 使用的多權重更新公式(Batch 版 OBQ 更新)
給定一批欄位索引集合 $Q$,更新如下:
#### 1. 多個權重的補償更新量(原來是單個 $\delta\_F$,現在是 vector):
$$
\boldsymbol{\delta}_F = -(\mathbf{w}_Q - \text{quant}(\mathbf{w}_Q)) \cdot ([\mathbf{H}_F^{-1}]_{QQ})^{-1} \cdot (\mathbf{H}_F^{-1})_{:, Q}
$$
#### 2. 多欄位的 inverse 更新:
$$
\mathbf{H}_{-Q}^{-1} = \left( \mathbf{H}^{-1} - \mathbf{H}^{-1}_{:, Q} \cdot ([\mathbf{H}^{-1}]_{QQ})^{-1} \cdot \mathbf{H}^{-1}_{Q, :} \right)_{-Q}
$$
這是原本 rank-1 的 outer product 更新,推廣成了 **rank-k 的更新(k 是 batch size)**
- 對於 GPT-175B 級別模型,實際速度提升約 10 倍(order of magnitude)
### Cholesky Reformulation
#### 觀察
* 在執行大模型(數十億參數以上)時,會出現:
* $\mathbf{H}^{-1}$(Hessian 的 inverse)**變成非正定矩陣(indefinite)**
* 導致量化過程中出現錯誤更新方向,**產生非常差的結果**
* 原因是:
* **不斷重複更新** inverse(例如 group update 的公式)會累積浮點誤差
* 尤其是涉及矩陣反轉與 outer product 的地方
* 在每次量化單個權重 $w\_q$ 時,我們其實**只需要 $\mathbf{H}\_F^{-1}$ 的第 $q$ 行**
* 所以不必儲存整個 $\mathbf{H}^{-1}$,而是可以:
* **預先使用更穩定的方法只算需要的部分**
* 並減少動態更新帶來的誤差
#### 實務觀察
* 小模型(< 1B 參數)可以透過簡單的 **對角線加小常數(dampening)** 避免這個問題
* 做法是將 $\mathbf{H}$ 改為:$\mathbf{H} + \lambda \mathbf{I}$
* 論文選擇 $\lambda = 0.01 \times \text{mean}(\text{diag}(\mathbf{H}))$
* 但對於大型模型(如 OPT-175B),這個方法已不足以保證穩定性
#### 關鍵 insight:
* 之前的 inverse 更新(inv-update):
$$
\mathbf{H}_{-q}^{-1} = \mathbf{H}^{-1} - \frac{1}{[\mathbf{H}^{-1}]_{qq}} \mathbf{H}^{-1}_{:, q} \mathbf{H}^{-1}_{q, :}
$$
實際上和 Cholesky 分解的行為非常接近。
* Cholesky 分解可以穩定地取出矩陣的各行資訊,尤其適合處理 **對稱正定矩陣 $\mathbf{H}$**
#### GPTQ 改進方式
* 使用 **Cholesky kernel** 預先分解 $\mathbf{H}$,產出所有需要的行(尤其是主對角線起始的每一行)
* 所得資訊足以支持量化所需的所有誤差與補償計算
* 搭配輕度 dampening(仍加 $\lambda$)

## 實驗驗證
GPTQ 實驗設計包含:
1. **小模型比較**(ResNet、BERT-base、OPT-125M)→ 驗證精度與其他高準確量化法一致。
2. **大型模型延展性** → 測試 GPTQ 能否處理 BLOOM / OPT 全系列(包含 175B)。
3. **Perplexity 評估** → 語言生成任務的量化效果。
4. **Zero-shot 任務測試** → 驗證量化後的泛化能力。
5. **GPU 實務表現** → 實測能在 **單張 A100 GPU 上完成整個量化流程**。
6. **校準資料(calibration data)**:
- 使用 C4 corpus 中的隨機 128 段文本(每段 2048 token)。
- 全為 **非任務特定(task-agnostic)** → 完全 zero-shot。
7. 每次只載入一個 Transformer block(6 層)進行 Hessian 累積與量化。
8. 每完成一個 block 的量化,就把資料傳回,用來產生下一個 block 的輸入 → 提升效能且不耗太多記憶體。
### 對照方法
| 方法 | 說明 |
| ------------------------------- | ---------------------------- |
| **RTN**(round-to-nearest) | LLM.int8() 使用的方法;速度快但精度一般 |
| **AdaRound / BRECQ / AdaQuant** | 高準確度、需大量 SGD 或優化步驟;在大型模型上不可行 |
| **OBQ** | GPTQ 的前身;精度高但不可擴展到數十億參數等級 |
| GPTQ | 同樣精度但可處理 175B 模型,只需幾小時 |
### 小模型測試結果(Quantizing Small Models)

| 模型 | GPTQ 表現 |
| ------------------------ | ----------------------------------------- |
| **ResNet-18 / 50** | 4-bit 準確率與最佳方法持平,3-bit 稍弱但仍可接受(見 Table 1) |
| **BERT-base / OPT-125M** | GPTQ 與 OBQ 精度接近,有時甚至略優 |
| **執行時間** | GPTQ 只需 **1 分鐘內**,其他方法通常需 **近 1 小時** |
### GPTQ 對大型模型的運行時間(Runtime)
| 模型 | GPTQ 量化時間(單張 A100) |
| ---------- | ------------------ |
| OPT-13B | 20.9 分鐘 |
| OPT-30B | 44.9 分鐘 |
| OPT-66B | 1.6 小時 |
| OPT-175B | 4.2 小時 |
| BLOOM-176B | 3.8 小時 |
與之對比:
* **ZeroQuant-LKD**(類似 LLM.int8)→ 1.3B 模型需 3 小時
* 若線性外推,175B 模型可能需要數百小時(甚至數週)
* **AdaRound / BRECQ** → 使用 SGD,開銷更高,不可行
GPTQ 為目前唯一能**在數小時內量化百億級模型**的高精度方法。
## 實驗:語言生成任務與 175B 級模型的表現
壓縮 OPT 與 BLOOM 全系列模型(最大至 175B / 176B)至 3-bit 和 4-bit,並在語言生成任務中比較 GPTQ 與傳統量化方法(如 RTN)的效能差異。
### 測試資料集
- WikiText-2
- Penn Treebank (PTB):小型英文語料庫
- C4:大規模網頁語料,較泛用
- LAMBADA(LAMB.↑):long-range 文本填空任務,指標為正確率 ↑
### GPTQ 對 OPT 模型的表現(WikiText-2)

結果可觀察
- 4-bit 模式下,幾乎無損失(0.03~0.2),RTN 則下降明顯。
- 3-bit 下,GPTQ 仍可用,而 RTN 幾乎全面崩潰(Perplexity 炸裂 > 1000)。
- 越大的模型(除了 OPT-66B)→ 越容易量化,這對於實際應用非常有利。
### GPTQ 對 BLOOM 模型的表現(WikiText-2)

結果可觀察
- GPTQ 在 3-bit 和 4-bit 下均優於 RTN。
- BLOOM 整體上 比 OPT 更容易量化,推測模型內部更穩定(例如較少 dead units)。
### 模型越大越容易壓縮?
結果顯示
- 大模型(如 OPT-175B、BLOOM-176B)比小模型更容易量化且維持精度。
- OPT-66B 是例外,因為前幾層存在許多 "dead units"(神經元沒有啟動),導致難以壓縮。
### 175B 級模型實驗總結

- GPTQ 在 4-bit 時幾乎與原始模型一致,甚至在某些任務(如 LAMBADA)上有微小提升。
- RTN 在高壓縮下精度快速惡化,甚至完全不可用(如 3-bit)。
## 實用性加速

### 案例:OPT-175B 在 3-bit 下的部署
* **總記憶體需求:63GB**
* 3-bit 量化權重
* Embedding + output layer 維持 FP16(未量化)
* 加上 2048 token 的 KV-cache:約 9GB
* 每次生成 1 個 token,需要大量的 matrix-vector 運算,瓶頸來自記憶體頻寬,不是計算單位
### token latency 實驗(序列長度 128)
- 越便宜的 GPU(如 A6000)頻寬越小 → GPTQ 的記憶體節省效果越明顯
### 零樣本任務效能分析

**任務**:
* LAMBADA(long-range completion)
* ARC-Easy / ARC-Challenge(推理與邏輯)
* PIQA(物理常識)
**結果:**
* **4-bit 下 GPTQ 與 RTN 都還可以使用**
* **3-bit 下只有 GPTQ 保持可用,RTN 完全崩潰**
* GPTQ 跨多種任務皆穩定
## 結論
- GPTQ 方法總結
- 基於近似二階資訊的後訓練量化,針對百億到千億參數級模型(如 OPT-175B、BLOOM-176B)。
- 可將模型精度壓縮至 3 – 4 bit,精度幾乎無損,並實現顯著的可用性與推理加速。
- 端到端加速:動態反量化核減少記憶體帶寬瓶頸,Token 生成速度提升 3× – 4.5×。
- 在 2-bit、甚至 ternary 情況下仍保持合理效能。
- 限制
- 未量化 activation,僅 focus 於權重;激活量化和運算核優化是後續可推進的方向。
## 附錄
## 背景複習
對一個 layer 的某一行權重 $\mathbf{w} \in \mathbb{R}^d$ 進行量化,使得 layer output 誤差最小。
目標誤差是:
$$
\min_{\widehat{\mathbf{w}}} \| \mathbf{w}^\top \mathbf{X} - \widehat{\mathbf{w}}^\top \mathbf{X} \|_2^2
$$
也就是:
$$
\min_{\widehat{\mathbf{w}}} \| (\mathbf{w} - \widehat{\mathbf{w}})^\top \mathbf{X} \|_2^2 = \| \Delta \mathbf{w}^\top \mathbf{X} \|_2^2
$$
令 $\Delta \mathbf{w} = \mathbf{w} - \widehat{\mathbf{w}}$ 是誤差向量。
---
## Step 1: 寫成二次誤差形式(Quadratic Loss)
$$
L(\Delta \mathbf{w}) = \| \Delta \mathbf{w}^\top \mathbf{X} \|_2^2 = \Delta \mathbf{w}^\top \mathbf{X} \mathbf{X}^\top \Delta \mathbf{w}
$$
這是標準的 quadratic form,對應的 Hessian 就是:
$$
\mathbf{H} = 2 \mathbf{X} \mathbf{X}^\top
$$
這邊取 2 是因為數學上 $L = \frac{1}{2} \Delta w^\top H \Delta w$ 時微分比較乾淨,不影響最小化目標。
---
## Step 2: 只量化一個 $w\_q$,其他還是 float
我們要選出一個「最該先量化的參數 $w\_q$」並補償其他沒被量化的權重 $w\_f$($f \in F$)。
所以要看:如果量化 $w\_q \rightarrow \hat{w}\_q$,會造成多少影響?我們希望挑那個「對總誤差影響最小」的 $w\_q$。
---
## Step 3: 推出哪個權重最值得先量化
考慮原始的 quadratic 誤差項,根據二階泰勒展開,若你只動一個權重 $w\_q$,造成的誤差會是:
$$
L \approx \frac{1}{2} (\text{quant}(w_q) - w_q)^2 \cdot H_{qq}
$$
但我們不想重算 $H$,所以改用逆矩陣 $H^{-1}$,我們可以得到一個標準化誤差:
$$
\frac{(\text{quant}(w_q) - w_q)^2}{[\mathbf{H}^{-1}]_{qq}}
$$
這就是 GPTQ/OBQ 用的 **最小化誤差選擇指標**。
越小,表示你能「很便宜地量化掉這個參數」,而且後面能補償得很好。
所以:
$$
w_q = \arg\min_{q} \frac{(\text{quant}(w_q) - w_q)^2}{[\mathbf{H}^{-1}]_{qq}}
$$
---
## Step 4: 計算如何補償剩下權重(誤差分散)
一旦量化了 $w\_q$,我們希望其他權重能做些微調,來彌補這次量化帶來的誤差。
「在保持 $\Delta w\_q$ 為已知值的情況下,如何調整其餘 $\Delta w\_f$ 來讓整體誤差最小?」
解法是:
$$
\boldsymbol{\delta}_F = - \frac{w_q - \text{quant}(w_q)}{[\mathbf{H}^{-1}]_{qq}} \cdot (\mathbf{H}^{-1})_{:, q}
$$
這是 **高斯消去法** + **最小平方誤差補償** 的結果。
意思 : 固定了 $w\_q$,其他權重怎麼調整才能讓誤差降低最快。