一個 70B 參數的模型,用 FP16 存放需要約 140GB 記憶體,單張消費級顯示卡根本裝不下;把權重壓成 INT4 之後,同一個模型只要約 35GB,一張 24GB 顯卡加上少量 offload 就能跑。這就是量化(Quantization)在做的事:用更少的位元數表示同一組數字,換取記憶體、頻寬與延遲上的巨大改善。今天聚焦在「模型權重量化」本身——它為什麼有效、有哪些主流做法、精度掉多少、以及對消費級硬體部署的實際意義。

📖 學(核心)

為什麼要量化:瓶頸不在算力,在記憶體頻寬

大型語言模型推理時,絕大多數時間並不是花在「乘法運算」上,而是花在「把權重從記憶體搬到運算單元」這件事上。生成每一個 token,GPU 都得把整個模型的權重讀過一遍;模型越大,這個搬運成本就越主導。這叫做 memory-bound(記憶體受限),而不是 compute-bound(算力受限)。

量化的核心洞見就在這裡:如果把每個權重從 16-bit 壓到 4-bit,要搬運的資料量直接少了四倍,記憶體頻寬的壓力也少了四倍。加上模型佔用空間變小,原本裝不下的模型現在裝得下了。所以量化帶來的好處是三重的——省記憶體、省頻寬(等於加速)、降低部署門檻。實測上,INT4 相對 FP16 可以帶來數倍的延遲改善與吞吐量提升。

數字怎麼存:FP16、BF16 與整數格式

要理解量化,得先理解浮點數怎麼存。一個 16-bit 浮點數由三部分組成:符號位、指數位(決定範圍)、尾數位(決定精度)。

  • FP16:1 符號 + 5 指數 + 10 尾數。尾數多,所以在有限範圍內精度較高,但指數只有 5 位,能表示的最大值約 65504,範圍很窄。
  • BF16:1 符號 + 8 指數 + 7 尾數。它其實是把 FP32 的指數位原封不動搬過來,所以動態範圍跟 FP32 一樣寬(可到 3.4×10^38),代價是尾數只剩 7 位、精度較差。

這個差異解釋了為什麼訓練普遍用 BF16:訓練時梯度可能非常大或非常小,寬廣的動態範圍能避免溢位(overflow)與下溢(underflow),而尾數精度的損失可以靠訓練過程容忍。FP16 範圍窄,更適合對精度敏感的推理場景。

而所謂的 INT8、INT4,則是完全不同的思路:不再用浮點表示,而是把一段連續的浮點數值域,線性映射到有限個整數上。INT8 只有 256 個階,INT4 只有 16 個階。把權重塞進這麼少的階,必然損失資訊——量化的所有技術難點,都在於「怎麼把損失降到最小」。

量化的基本機制:scale、zero-point 與 outlier

最基礎的做法是線性量化:找出一組權重的最大最小值,算出一個縮放係數(scale)把浮點區間映射到整數區間,推理時再用 scale 還原回近似的浮點值。這裡有兩個關鍵設計:

  • 粒度(granularity):是整個張量共用一個 scale(per-tensor),還是每一列、每一組權重各有 scale(per-channel / group-wise)?粒度越細,擬合越準、但額外開銷越大。現代 INT4 方法幾乎都採用 group-wise(例如每 128 個權重一組)。
  • 離群值(outlier):LLM 的權重與激活值裡常有少數數值特別大的「離群值」,它們會把 scale 拉大,導致其他正常值被壓得失去精度。怎麼處理離群值,是不同方法拉開差距的關鍵。

PTQ vs QAT:要不要重新訓練

量化技術大致分兩條路線:

訓練後量化(PTQ, Post-Training Quantization):對一個已經訓練好的模型直接動刀,不再訓練。通常會用一小批「校準資料(calibration data)」跑過模型,觀察各層激活值的分布,藉此調整 scale、把量化誤差降到最小。PTQ 的好處是快、便宜、不需要原始訓練資料與龐大算力,對超大模型幾乎是唯一實務可行的選擇,因此被廣泛採用。GPTQ、AWQ 都屬於 PTQ。

量化感知訓練(QAT, Quantization-Aware Training):在訓練(或微調)過程中就「模擬」量化——每次前向與反向傳播都插入量化/反量化操作,讓模型在訓練時就學會適應低精度帶來的誤差。QAT 的精度保留通常明顯優於 PTQ,尤其在極低位元(如 INT4 甚至更低)時差距更明顯。代價是它需要完整的訓練流程與大量算力/記憶體,對大規模模型往往不切實際。實務上的折衷,是只在小範圍(如 LoRA adapter)上做量化感知的微調。

一句話總結取捨:PTQ 便宜快速、資源允許時 QAT 精度更好。 多數人從 PTQ 開始,只有在精度掉太多、又有資源時才考慮 QAT。

主流方法:GPTQ、AWQ、GGUF、bitsandbytes

這四個名字常被並列,但它們其實不在同一個維度上——GPTQ/AWQ 是量化「演算法」,GGUF 是「檔案格式」,bitsandbytes 是「函式庫」。釐清這點很重要。

  • GPTQ:一種逐層、基於二階資訊(近似 Hessian)的 PTQ 演算法,逐一量化權重並補償誤差,能做到 INT4 且精度不錯。生態成熟,vLLM、Hugging Face Transformers、text-generation-webui 都支援,社群有大量 Llama、Mistral、Qwen 的 GPTQ 版本。
  • AWQ(Activation-aware Weight Quantization):核心觀察是「不是所有權重都一樣重要」。它根據激活值找出對輸出影響最大的少數權重加以保護,避免它們被激進量化。同樣 INT4 下,AWQ 的困惑度(perplexity)通常低於 GPTQ,在推理/邏輯任務上表現更好,代價是量化過程稍慢。
  • GGUF:由 llama.cpp 專案定義的檔案格式,把權重、metadata、tokenizer 打包成單一可攜的二進位檔。它最大的特色是為 CPU 執行而生,也支援 CPU/GPU 混合 offload,提供多種量化等級(Q4_K_M、Q5_K_M 等),是本機、消費級硬體跑模型的主流選擇。
  • bitsandbytes:Hugging Face 生態最常見的量化函式庫,靠 load_in_8bit / load_in_4bit(NF4)一行參數即可載入量化模型。它的 INT8 採用「混合精度分解」——把離群激活值留在 FP16,其餘用 INT8——上手最簡單,常用於 QLoRA 這類量化微調。

精度、速度、記憶體的三角取捨

沒有免費的午餐。INT8(如 SmoothQuant、bitsandbytes)通常能做到約 2 倍記憶體縮減與明顯加速,而精度損失很小,是相對安全的第一步。往 INT4 走,記憶體再減半、速度再上一個台階,但精度損失開始變得可感知——尤其在數學、程式碼生成、需要多步推理的任務上,低位元的錯誤會被放大。實務建議是:先上 INT8 驗證精度,真的需要更省更快時再壓到 INT4,並針對你的任務實測而非只看通用榜單。

權重量化 ≠ KV cache 量化

這是最容易混淆的一點。今天談的是權重量化——壓縮模型本身那組固定不變的參數,好處在載入時就決定了。而 KV cache 量化壓縮的是推理過程中隨對話累積、動態成長的鍵值快取,它的目的是讓長上下文不吃爆記憶體。兩者針對的是記憶體佔用的不同部分:權重是「模型多大」,KV cache 是「對話多長」。它們可以同時使用、彼此獨立,別把兩件事混為一談。

🧠 記

  • 量化的本質是「省記憶體與頻寬」,因為 LLM 推理多半是 memory-bound 而非 compute-bound。
  • FP16:高精度、窄範圍;BF16:寬範圍(同 FP32 指數)、低精度,訓練普遍用 BF16。
  • INT8/INT4 是把浮點值域線性映射到 256/16 個整數階,階數越少損失越大。
  • 關鍵設計:量化粒度(per-tensor vs group-wise)與離群值處理。
  • PTQ 不重訓、便宜、快、對大模型實務首選;QAT 重訓、精度更好、成本高。
  • GPTQ/AWQ 是演算法,GGUF 是檔案格式,bitsandbytes 是函式庫——不同維度。
  • AWQ 保護「重要權重」,同位元下困惑度通常優於 GPTQ。
  • GGUF 為 CPU/本機而生,是消費級硬體跑模型的主流。
  • 一般順序:先 INT8 驗證,再視需要下探 INT4;推理/數學/程式碼任務對低位元最敏感。
  • 權重量化壓「模型多大」,KV cache 量化壓「對話多長」,兩者獨立。

✍️ 實踐

  1. 選一個中型開源模型(如 7B/8B 的 Llama、Qwen 或 Mistral),先用原始 BF16/FP16 版本在你的硬體上跑一次,記錄記憶體佔用與生成速度(tokens/秒)作為基準。
  2. 用 bitsandbytes 做最快的 4-bit 實驗:在 Hugging Face from_pretrained 加上 load_in_4bit=True,對照基準看記憶體省了多少、速度如何。這是門檻最低的入門。
  3. 下載對應的 GPTQ 與 AWQ 版本(社群多半有現成的 INT4 quant),分別載入,用同一組提示詞比較輸出品質差異,特別測一題數學或程式碼題,感受低位元對推理任務的影響。
  4. 在消費級/本機場景試 GGUF:用 llama.cpp 或 Ollama 載入同一模型的 Q4_K_M 與 Q5_K_M,比較品質與速度,體會不同量化等級的取捨。
  5. 用小型評測驗證精度:別只憑感覺——跑一個你關心任務的小測試集(哪怕 20 題),量化前後各跑一次,把「省了多少資源」與「掉了多少品質」放在同一張表上做決策。

🔗 延伸學習


💬 問 AI

我想把一個 {模型名稱與參數量,例如 Qwen2.5-14B} 部署在 {你的硬體,例如 24GB 顯卡 / 純 CPU / Mac M 系列} 上,
主要用途是 {任務,例如 中文客服問答 / 程式碼生成 / 長文摘要}。

請幫我:
1. 判斷這張硬體在 FP16 / INT8 / INT4 下分別能不能裝下,並估算記憶體佔用。
2. 針對我的任務,建議該用 GPTQ、AWQ、GGUF 還是 bitsandbytes,並說明理由。
3. 建議一個具體的量化位元與粒度設定(例如 INT4 group-size 128),並指出這個任務對低位元最可能出問題的地方。
4. 給我一個能實測「量化前後品質差異」的最小驗證流程。

我可以接受的品質損失上限大約是 {例如 3% 準確率 / 幾乎不能掉},請以此為前提給建議。