昨天談對齊(RLHF/DPO/Constitutional AI)、前天談微調(PEFT/LoRA/QLoRA),我們把一顆大模型訓練好、也調教得聽話了。但這顆模型往往有數百億參數、要好幾張 A100 才跑得動——放到手機、邊緣裝置或平價伺服器上根本不切實際。今天談的「模型壓縮」就是收尾的一步:在盡量不掉精度的前提下,把又大又貴的模型變小、變快、變便宜。這正是近期 DeepSeek、Qwen、Llama 等平價高能模型能普及的關鍵工程,也是「訓練 → 對齊 → 部署」這條鏈路最後、也最貼近真實產品的一環。
📖 學
為什麼要壓縮模型
一個 70B 參數的模型以 FP16 儲存,光權重就約 140GB,推論時還要加上 KV cache,動輒需要多張高階 GPU。壓縮的目標有三個:降低記憶體佔用(能塞進單張顯卡甚至消費級硬體)、加快推論速度(更少的資料搬運與運算)、降低成本與能耗(雲端帳單與電費)。壓縮不是把模型變笨,而是刪去「冗餘」——神經網路在訓練時往往過度參數化(over-parameterized),存在大量對輸出貢獻極小的權重與過高的數值精度,這些正是壓縮的空間。
知識蒸餾:teacher–student 與 soft labels
知識蒸餾(Knowledge Distillation,Hinton 2015 提出)的核心比喻是「師生傳承」:用一個又大又準的 teacher 模型去教一個小而快的 student 模型。
關鍵不在於讓 student 去背標準答案(hard labels,例如「這是貓」),而是學習 teacher 輸出的軟標籤(soft labels)——也就是完整的機率分佈:「90% 是貓、7% 是狗、2% 是狐狸」。這個分佈裡藏著 teacher 學到的「暗知識(dark knowledge)」:貓和狗比貓和汽車更像。這種類別間的相對關係,比單一硬答案資訊量大得多。
為了讓這些軟標籤更好學,會在 softmax 引入溫度(temperature, T)參數。T 越高,機率分佈越平滑、越「攤開」,那些原本接近 0 的次要類別會被放大,student 就能看見更豐富的暗知識。訓練時的損失通常是「蒸餾損失(student 逼近 teacher 軟標籤,KL 散度)」加上「一般的硬標籤損失」兩者的加權。在 LLM 上,蒸餾又分白箱(能拿到 teacher 的 logits/中間層)與黑箱(只能拿 teacher 生成的文字,如用 GPT-4 產資料再訓練小模型,即 sequence-level distillation)。
量化:用更少的位元表示權重
量化(Quantization)是把模型權重與/或激活值,從高精度數值型別換成低精度型別,直接減少每個數字佔的位元數。
- FP16 / BF16(16-bit):目前訓練與推論的常見基準,相對 FP32 已省一半。
- INT8(8-bit):把浮點權重映射到 8 位元整數,記憶體約再省一半,精度損失通常很小。
- INT4(4-bit):更激進,記憶體約為 FP16 的四分之一,但精度掉幅明顯較大,需要更聰明的演算法來救。
映射的核心是找一組 scale(縮放因子) 與 zero-point,把浮點區間對應到整數區間;推論時可再「反量化(dequantize)」回浮點運算。難點在於離群值(outliers):少數極大的激活值會撐大量化範圍,讓其他數值擠在一起、誤差爆增。
GPTQ、AWQ 與 QAT vs PTQ
量化按「何時做」分兩大路線:
- 訓練後量化(PTQ, Post-Training Quantization):模型訓練完才量化,快、不用重訓,是目前 LLM 主流。代表方法:
- GPTQ:逐層、逐行地量化權重,用二階資訊(Hessian)逐步補償量化誤差,讓每一步都最小化輸出偏差。權重壓到 INT4,推論時在融合核心(fused kernel)中即時反量化回 FP16,記憶體省約 4 倍。
- AWQ(Activation-aware Weight Quantization):觀察到「不是所有權重一樣重要」,依據激活值分佈找出關鍵的少數權重通道並加以保護(放大再量化),在相同位元數下通常精度更好、推論也很快。
- 量化感知訓練(QAT, Quantization-Aware Training):在訓練/微調過程中就「模擬」量化的捨入誤差,讓模型學會對低精度魯棒。精度天花板更高,但要動到訓練流程、成本高。QLoRA(前天提過)某種意義上就結合了 4-bit 量化與 LoRA 微調的精神。
一句話:PTQ 便宜快速、QAT 精度更好但貴。另外還有 GGUF 這種檔案格式(llama.cpp 生態),本身不是量化演算法,而是把各種量化變體打包、讓模型能在 CPU 與筆電上跑,是邊緣部署的常客。
剪枝與稀疏化(簡述)
除了蒸餾與量化,第三條路是剪枝(Pruning):直接刪掉不重要的權重或神經元。分兩種:非結構化剪枝把個別權重歸零,得到稀疏矩陣,壓縮率高但需要特殊硬體/核心才跑得快;結構化剪枝整條移除神經元、注意力頭或整層,模型直接變小、通用硬體就能加速,但通常掉精度較多。近年硬體(如 NVIDIA 的 2:4 稀疏)開始支援結構化稀疏加速,讓剪枝更實用。
蒸餾+量化:小模型如何逼近大模型
三種技術並非互斥,實務上堆疊使用效果最好。一條典型路線是:先用大 teacher 蒸餾出一個較小的 student(架構層面變小),再對這個 student 做 PTQ 量化(數值層面變小),必要時搭配剪枝。近期研究更把兩者融合成 量化感知蒸餾(Quantization-Aware Distillation)——在量化的同時用 teacher 的軟標籤把掉的精度「補回來」,讓 2–4 bit 的小模型也能逼近全精度大模型。這正是為什麼今天一顆 7B、經良好蒸餾與量化的模型,能在許多任務上追平一年前的 70B——不是魔法,是壓縮工程的累積。
代價與取捨
天下沒有白吃的午餐,壓縮永遠在精度、速度、記憶體、成本之間做權衡:位元越低省越多,但精度風險越高;蒸餾能救精度卻要額外訓練與一顆好 teacher;剪枝加速明顯卻可能傷害泛化。實務判斷不能只看 perplexity,還要用下游任務與真實 prompt 實測——有些量化在 benchmark 幾乎無損,卻在長文推理、程式生成或多語言上悄悄退化。壓縮的藝術,就是找到「使用者感受不到差異」的那條線。
🧠 記
- 模型壓縮的三大目的:省記憶體、加快推論、降低成本;本質是刪去神經網路的冗餘(過度參數化與過高精度)。
- 知識蒸餾用 teacher 的軟標籤(機率分佈)教 student,靠溫度 T攤平分佈以釋放「暗知識」,比背硬答案學得更多。
- 量化把權重從 FP16 降到 INT8/INT4,記憶體隨位元數等比下降;最大敵人是離群值撐大量化範圍。
- PTQ vs QAT:PTQ(GPTQ、AWQ)免重訓、快又主流;QAT 在訓練中模擬量化、精度更高但成本大。GGUF 是格式不是演算法。
- 剪枝分非結構化(稀疏、需特殊核心)與結構化(直接變小、通用硬體可加速),與蒸餾/量化可堆疊使用。
- 壓縮永遠是取捨:位元越低省越多但精度風險越大,務必用下游任務實測而非只看單一指標。
✍️ 實踐
-
用 Ollama 比較不同量化版本:安裝 Ollama 後,抓同一個模型的不同量化標籤(例如
ollama run llama3.1:8b-instruct-q4_K_M與q8_0),準備 5 題涵蓋推理、程式、中文摘要的 prompt,記錄各版本的回答品質、輸出速度(tokens/s)與記憶體佔用。實際感受「4-bit 到 8-bit」那條精度線在哪裡。 -
手算一次量化與蒸餾溫度:用紙筆或 Python 做兩個小實驗。其一:把一組 FP32 權重
[0.12, -0.87, 1.53, -2.10]以對稱 INT8 量化,算出 scale、量化後整數、再反量化,觀察誤差。其二:對一組 logits 分別用 T=1 與 T=4 跑 softmax,比較機率分佈如何被「攤平」,親眼看見溫度如何放大暗知識。
🔗 延伸學習
- Hugging Face — Quantization 概念指南:從零解釋量化原理與各方法差異。
- Hugging Face — GPTQ 文件:GPTQ 演算法與實作範例。
- Hugging Face — 如何選擇量化方法:GPTQ / AWQ / bitsandbytes 的取捨對照。
- AWQ 論文(arXiv 2306.00978):Activation-aware Weight Quantization 原始論文。
💬 問 AI
把今天學到的框架丟給 AI,讓它幫你為手上的實際場景挑一條壓縮路線:
我想把一個 [模型名稱/參數量,例如 Llama 3.1 8B] 部署到 [目標環境,例如 單張 16GB 消費級 GPU/樹莓派/CPU 伺服器],
主要任務是 [任務,例如 中文客服問答/程式碼補全],對延遲的要求是 [延遲需求,例如 每秒 30 tokens]。
請以「知識蒸餾、量化(PTQ/QAT、GPTQ/AWQ/GGUF)、剪枝」三種壓縮技術為框架,幫我:
1. 推薦一條具體的壓縮路線與位元數,並說明為什麼;
2. 列出這條路線可能的精度損失風險,以及我該用哪些 [下游任務] 來驗證;
3. 給我可直接執行的工具與指令(例如 Ollama 標籤或 Hugging Face 套件)。
請用繁體中文、條列說明,並在最後提醒我一個最常被忽略的取捨陷阱。