重點速覽
模型量化是把模型權重從 16 位元改成更少的位元儲存,檔案和記憶體用量會跟著縮小,代價是多少會有精度損失。GGUF 只是裝模型的單一檔案格式,Q4_K_M、Q8_0 這些才是檔案裡權重的量化型別。選法是先用顯存算出能放下的最大權重,再在放得下的型別裡挑位元數最高的;如果上下文要開很長,就再往下降一級。
模型量化(quantization)是把模型權重改用更少的位元儲存:原本每個權重用 16 位元,量化後可能只剩 4 到 8 位元左右。你在下載本地模型時看到的 Q4_K_M、Q8_0、GGUF 這些字串,講的都是這件事。這篇會回答三個問題:量化到底改了什麼、檔名上的型別怎麼讀,以及手上的顯存放得下哪一級。讀完之後,你可以自己用一條算式估出檔案大小,並照著流程挑出合適的量化等級。
這篇是原理與判斷方法,不教任何工具的安裝或下載步驟。文中的數字只有兩種來源:官方說明明寫的(會標出處),或由文中列出的算式推導出來的(會標「示範計算」與前提)。
模型量化是什麼?
大型語言模型(LLM,術語表)的主體是一大堆數字,這些數字叫權重(weights),權重的總數就是參數量。模型原本通常以 bf16 或 float16 儲存,每個權重佔 2 個位元組(byte)。Hugging Face 的官方指南給了一條經驗法則:載入一個有 X 十億參數的模型,bf16 或 float16 精度大約需要 2 × X GB 的顯存。顯存(VRAM)就是顯示卡上的記憶體。
量化做的事,是把這些高精度數字對應到一個小很多的整數集合。Hugging Face 的概念指南舉例:int8 只能表示 256 個值,int4 只能表示 16 個值,所以每種量化方法都一定會引入捨入誤差(rounding error)。最常見的做法叫仿射量化(affine quantization):取出一個 tensor(權重陣列)的最小值和最大值,把整數範圍拉伸去對應它。官方的算例是:一個值域從 -1.8 到 2.4 的 tensor 對應到 int8,其中 0.5 會被量化成整數 11,還原時得到約 0.494,誤差約 0.006。
縮放比例 S = (最大值 − 最小值) ÷ (整數最大 − 整數最小)
量化:q = round(x ÷ S + Z) 還原:x ≈ S × (q − Z)
x:原本的權重 q:量化後的整數 Z:零點(代表 0.0 的那個整數)
為什麼少存幾個位元就能更省資源?官方的記憶體估算很直接:Transformers 總覽寫到,8B 模型的權重在 bf16 約 16GB,8 位元約 8GB,4 位元約 4 到 5GB。另一個好處在速度面:概念指南說,一次生成一個 token(術語表,模型處理文字的基本單位)時,GPU 大部分時間在讀取權重而不是計算,讀 4 位元權重搬動的資料量只有 bf16 的四分之一,這個節省有機會超過還原(dequantize)所多花的運算。
量化不是什麼
量化不是微調。 微調(fine-tuning)是用新資料繼續訓練,會改變模型學到的內容。官方對訓練後量化(post-training quantization,PTQ)的定義是「量化一個已經訓練好的模型,而不改變它學到的東西」。量化只是換一種方式存同樣的權重,不會教模型任何新東西。
量化也不是壓縮檔。 zip 檔解開後會一模一樣,量化不會。概念指南明講,還原只能得到原值的近似(approximation),中間的差距就是捨入誤差。llama.cpp 的量化工具說明也寫了:量化可能引入一些精度損失,通常用困惑度(perplexity,ppl,衡量模型預測文字好壞的指標之一)或 KL 散度(Kullback–Leibler divergence,kld)來衡量。
另外,官方量化工具列出了一個明確的警告:對已經量化過的權重再量化(requantize)可能嚴重降低品質,建議從 16 位元或 32 位元的版本開始。所以「把別人量化好的 Q4 再轉成更小的檔」不是好主意。
GGUF 是什麼?
GGUF 是 ggml 函式庫(GGUF 規格就放在它的倉庫裡)及以它為基礎的執行工具所使用的模型檔案格式。ggml 的規格說明把它描述為二進位格式,設計目標是快速載入與儲存、容易閱讀。模型通常先用 PyTorch 等框架開發,再轉成 GGUF 使用。
規格列出的設計目標包括:
- 單一檔案:不需要額外的外部檔案就能發佈與載入。
- 可擴充:新增資訊不會破壞既有模型的相容性。
- 支援
mmap(把檔案直接對應進記憶體的載入方式),載入與儲存很快。 - 完整資訊:載入模型需要的資訊都在檔案裡,不用使用者另外提供。
檔案內容由三塊組成:標頭(header)、每個 tensor 的資訊,以及 tensor 資料本身。標頭有 GGUF 的魔術數字、版本、tensor 數量與 metadata 鍵值對的數量。metadata 是鍵值結構,放模型架構、超參數與描述資訊。每個 tensor 的資訊則包含名稱、維度、**型別(type)**與資料在檔案中的位置。
這裡有一個重點:量化型別是記錄在每個 tensor 上的屬性,不是整個檔案共用一個開關。規格的型別列表(ggml_type)同時包含 F32、F16、BF16 這些未量化的格式,也包含 Q4_0、Q8_0、Q4_K、Q6_K、IQ4_XS 等量化格式。規格也說,tensor 資料「應該接近或等同原始模型檔案的資料,但可能因量化或其他推論最佳化而不同」,這些差異要記錄在 metadata 裡;而只要有任何 tensor 被量化,就必須有 general.quantization_version 這個欄位。
所以 GGUF 與量化的關係是:GGUF 是容器,量化是裡面權重的儲存方式。一個 GGUF 檔案可以是 F16(未量化),也可以是 Q4_K_M。檔名慣例也反映這點:規格建議用 <BaseName>-<SizeLabel>-...-<Encoding>...gguf 的結構,其中 Encoding 欄位就是權重編碼方式,範例有 Hermes-2-Pro-Llama-3-8B-F16.gguf 與 Grok-100B-v1.0-Q4_0-00003-of-00009.gguf(最後那串是分成 9 個分片中的第 3 個)。規格也坦白說,這個慣例「不保證能完美解析」。
多模態模型有時還會有額外檔案。規格的檔名慣例中,mmproj 前綴代表多模態投影模組(視覺或音訊編碼器),要搭配主模型一起載入。llama.cpp 的說明提到,這類元件通常保留在 bf16 或 q8 這種高品質格式,因為它們比主模型小很多,用更小的量化省下的速度與記憶體可以忽略,卻可能影響整體品質。
Q4_K_M、Q8_0 的名稱怎麼讀
先講清楚範圍:llama.cpp 與 ggml 的官方說明,並沒有一段話逐字解釋 Q、K、S、M、L 各代表什麼。下面只寫能從官方說明直接讀出來的部分,不補官方沒寫的縮寫全名。
1. 數字是「約略」的位元數,實際更高。 官方針對 Llama-3.1-8B 列的 bits/weight(每個權重平均位元數)顯示:Q4_K_M 是 4.8944,Q8_0 是 8.5008,Q6_K 是 6.5633。官方沒有逐一說明這個差距的來源;Hugging Face 的概念指南提到,per-group 量化每一組權重各有一個縮放值,要額外佔儲存空間,這是常見的原因之一。總之,名字裡的 4 不等於真的每個權重 4 位元。
2. 名字裡有 _K 的是 k-quants。 llama.cpp 的說明把它們稱為 k-quants,並提到 --pure 選項會「停用 k-quant 混合配置,把所有 tensor 量化成同一種型別」。這句話透露了兩件事:k-quant 預設是「混合」的,也就是同一個檔案裡不同 tensor 可以用不同型別;以及 Q4_K_M 這個名字代表的是整個檔案的配置,不是單一種 tensor 型別。這也和規格一致:ggml_type 列表裡有 Q4_K,卻沒有 Q4_K_M;general.file_type 欄位的定義是「檔案中多數 tensor 的型別」。
3. 同一系列的 S、M、L 位元數遞增。 從官方表格可以直接看到:Q3_K_S 是 3.6429、Q3_K_M 是 3.9960、Q3_K_L 是 4.2979;Q4_K_S 是 4.6672、Q4_K_M 是 4.8944;Q5_K_S 是 5.5704、Q5_K_M 是 5.7036。所以同一個系列裡,換成後面的字母,檔案會更大。至於字母的原文縮寫,官方說明沒寫,這裡不補。
4. 名字裡有 IQ 的是另一系列。 官方背景連結把它們稱為 i-quants,表格裡的 IQ1_S 到 IQ4_NL 涵蓋較低的位元數(例如 IQ2_M 是 2.9294)。本文不展開它們的內部做法。
5. 沒有 K 也沒有 IQ 的 Q4_0、Q8_0。 官方說明沒有解釋它們的內部格式,這裡只用數字:Q8_0 在官方表格是 8.5008;Q4_0 不在那張表裡,但官方 llama-bench 範例輸出裡有一個 Q4_0 的 7B 模型(檔案 3.56 GiB、6.74 B 參數,下面會用它推導)。
比較表:型別 × 每權重位元數 × 相對 FP16 的大小
下表的數字來自 llama.cpp 量化工具說明針對 Llama-3.1-8B 列出的資料,這是官方對這一個特定模型的資料,不代表你的模型;不同模型的實際比例會有差異。最右欄是用算式推導的。
| 型別 | 每權重位元數 | 檔案大小(GiB) | 相對 F16 的大小比例 |
|---|---|---|---|
| F16 | 16.0005 | 14.96 | 100% |
| Q8_0 | 8.5008 | 7.95 | 53.1% |
| Q6_K | 6.5633 | 6.14 | 41.0% |
| Q5_K_M | 5.7036 | 5.33 | 35.6% |
| Q5_K_S | 5.5704 | 5.21 | 34.8% |
| Q4_K_M | 4.8944 | 4.58 | 30.6% |
| Q4_K_S | 4.6672 | 4.36 | 29.2% |
| IQ4_XS | 4.4597 | 4.17 | 27.9% |
| Q3_K_L | 4.2979 | 4.02 | 26.9% |
| Q3_K_M | 3.9960 | 3.74 | 25.0% |
| Q3_K_S | 3.6429 | 3.41 | 22.8% |
| Q2_K | 3.1593 | 2.95 | 19.7% |
| IQ2_M | 2.9294 | 2.74 | 18.3% |
| IQ1_S | 2.0042 | 1.87 | 12.5% |
推導算式(示範計算): 相對 F16 的比例 = 該型別每權重位元數 ÷ F16 的每權重位元數。以 Q4_K_M 為例:4.8944 ÷ 16.0005 ≈ 0.306,也就是約 30.6%。用檔案大小算也一樣:4.58 ÷ 14.96 ≈ 0.306。
Q4_0 沒有出現在這張官方表格裡。用 llama-bench 範例反推(示範計算,前提是範例輸出中的 3.56 GiB 與 6.74 B 參數指的是同一個檔案):3.56 × 2³⁰ × 8 ÷ (6.74 × 10⁹) ≈ 4.54 位元/權重,約為 F16 的 28.4%。這是推導出來的估計值,不是官方給的 bits/weight。
官方對單一模型的困惑度資料
量化工具的型別清單(原始碼中的說明文字,即 --help 看到的內容)對部分型別附上了 Llama-3-8B 的檔案大小與困惑度增加量。清單只寫「+x ppl」,這裡理解為相對未量化版本的困惑度增加;數字越小,表示量化帶來的增加越少。
| 型別 | 官方標示的大小 | 官方標示的困惑度增加量 |
|---|---|---|
| Q8_0 | 7.96G | +0.0026 |
| Q6_K | 6.14G | +0.0217 |
| Q5_K_M | 5.33G | +0.0569 |
| Q4_K_M | 4.58G | +0.1754 |
| Q4_K_S | 4.37G | +0.2689 |
| Q4_0 | 4.34G | +0.4685 |
| Q3_K_M | 3.74G | +0.6569 |
| Q2_K | 2.96G | +3.5199 |
請把這張表當成「一個模型、一種測量方式」的資料點,不要延伸成型別排名,也不要直接套到別的模型或你的任務上。它能佐證的結論只有兩個:同一個模型上,位元數降低時困惑度增加量整體會變大;以及檔案大小接近的型別(例如 Q4_K_S 的 4.37G 和 Q4_0 的 4.34G),困惑度增加量並不相同,所以不能只看名字裡的數字。官方說明另外提到,困惑度只是衡量方式之一,這個增加量可以搭配合適的 imatrix(importance matrix,重要性矩陣)檔案降低;怎麼做超出本文範圍,請以官方說明為準。
怎麼判斷該選哪一級
量化等級的選擇,本質上是在「放不放得下」與「精度損失」之間取捨。可以照下面的流程走。
第一步:算出權重能用的記憶體預算。 以顯存為例:預算 = 顯存總量 − KV 快取 − 其他執行開銷。KV 快取(key-value cache)是模型生成時儲存之前 token 計算結果的暫存區;Hugging Face 的說明指出,預設的快取會隨著生成的進行而成長。所以上下文越長,要留給它的空間越多。這些開銷怎麼估,請看依顯存選模型;顯存、記憶體與硬碟在載入時各自負責什麼,則見顯存、記憶體、硬碟的角色。
第二步:反推你能負擔的最高位元數。 公式如下:
檔案大小(位元組)≈ 參數量 × 每權重位元數 ÷ 8
最高可用位元數 ≈ 權重預算(位元組)× 8 ÷ 參數量
第三步:在放得下的型別裡,挑位元數最高的那個。 位元數越高,越接近原始精度,這是官方文字與上面那張單一模型資料都佐證的方向。
第四步:如果上下文也要開很長,往下降一級。 因為 KV 快取會吃掉預算,預算變小,最高可用位元數也跟著下降。
示範計算
前提: 假設模型有 80 億個權重(Llama-3.1-8B 的表格大小可反推約 8.03 B:14.96 × 2³⁰ × 8 ÷ 16.0005 ≈ 8.03 × 10⁹,這裡取整數 8 × 10⁹ 方便計算);以下的預算數字純屬假設,不是任何顯示卡的規格。
- 情境 A:權重預算 6 GiB。 最高可用位元數 = 6 × 2³⁰ × 8 ÷ (8 × 10⁹) ≈ 6.44。上表中不超過 6.44 的型別,位元數最高的是 Q5_K_M(5.7036);Q6_K 是 6.5633,超過了,放不下。
- 情境 B:同一張卡,但要開長上下文,預算縮到 5 GiB。 最高可用位元數 = 5 × 2³⁰ × 8 ÷ (8 × 10⁹) ≈ 5.37。Q5_K_S(5.5704)已經超過,位元數最高的是 Q4_K_M(4.8944)。這就是「往下降一級」的意思:從 Q5 系列降到 Q4 系列。
驗證一下算式是否合理:Q4_K_M 的檔案大小 ≈ 8.03 × 10⁹ × 4.8944 ÷ 8 ≈ 4.91 × 10⁹ 位元組,換算成 GiB 是 4.91 × 10⁹ ÷ 2³⁰ ≈ 4.58,與官方表格的 4.58 GiB 吻合。官方的 Memory/Disk 範例也一致:8B 模型的原始大小 32.1 GB(32 位元)量化成 Q4_K_M 後是 4.9 GB,4.9 ÷ 32.1 ≈ 0.153,而 4.8944 ÷ 32 ≈ 0.153。
品質只能定性說明
關於「Q5 比 Q4 好多少」,官方說明只提供單一模型的困惑度,沒有給你的任務的數字,所以這裡只能定性說。Hugging Face 的方法比較(Llama 3.1 8B 與 70B;注意這是 Transformers 支援的方法,不是 GGUF 型別)把結果分成三個區間:
| 位元數 | 記憶體相對 bf16 | 精度(官方描述) |
|---|---|---|
| 8 位元 | 約縮小 2 倍 | 非常接近 bf16 |
| 4 位元 | 約縮小 4 倍 | 高;AWQ 與 GPTQ 常居前,但需要校準 |
| 低於 4 位元 | 縮小超過 4 倍 | 有明顯下降,2 位元尤其明顯 |
官方還附了一句提醒:在決定之前,請用你自己的任務和硬體做效能與精度測試。這也是本文的建議,因為「能不能用」取決於你要它做什麼。Hugging Face 的最佳化指南也提到,如果顯存不是限制,往往不需要考慮量化;但很多顯示卡不量化就跑不動,這時 4 位元與 8 位元是很實用的工具。也就是說,放得下就不必為了省空間降太多。這個判斷的基礎是上面的趨勢,不是某個型別的保證。
其他種類的量化:不要混在一起
「量化」這個詞底下其實有好幾種不同的東西,常見的混淆來自把它們當成同一件事。
GGUF 這一系: 先把模型轉成 GGUF,再用 llama.cpp 的量化工具轉成目標型別;官方流程是兩個階段。Transformers 的比較表把 GGUF 列為「只能載入已量化檔案」的類型。要特別注意的是,Transformers 官方說明指出:大多數 GGUF 模型在載入時會被還原成完整精度,所以記憶體用量和未量化的模型一樣;只有特定情況(MPS 加上 kernels 套件,限定部分架構)權重才會維持壓縮狀態。如果你用的是 llama.cpp 這一系的工具,則是直接以量化型別執行;工具之間的行為不同,請以各自的官方說明為準。
訓練後量化函式庫: 在 Transformers 官方說明中有一長串,這裡只挑幾個說明差異。
| 方法 | 官方說明的特性 | 何時量化 |
|---|---|---|
| bitsandbytes | 4 位元或 8 位元;不需要校準資料,並支援微調 | 載入時 |
| GPTQ | 訓練後量化,每列權重獨立量化以最小化誤差;位元數有 2、3、4、8 | 載入時,需要校準資料集 |
| AWQ | 保留少部分對模型表現重要的權重,壓縮到 4 位元 | 只能載入已量化的檢查點 |
| GGUF | 位元數 1 到 8 | 只能載入已量化檔案 |
表中「校準」是什麼意思?概念指南說明:有校準資料的方法會拿一小批資料跑過模型,用啟動值(activations,模型中間層的輸出)來決定每一層怎麼量化。這通常在 4 位元以下精度較好,但要花幾分鐘到幾小時。沒有校準資料的方法則只靠權重本身算縮放比例,快到可以在載入模型時順便做。
還有一個不同層次的分法:訓練中量化(quantization-aware training,QAT)是在訓練時就模擬量化,讓模型學會容忍捨入誤差,通常在極低位元數下精度最好,但需要訓練。本文講的 GGUF 量化,流程是把已訓練好的模型轉成 GGUF 再量化,屬於訓練後量化的做法。
只量化權重,還是連啟動值也量化? 概念指南區分了只量化權重(weight-only)與權重加啟動值都量化兩類。只量化權重的方法省記憶體,但每次矩陣乘法前要先還原,所以不一定更快;它們在模型受限於記憶體頻寬時最有利。
KV 快取也可以量化,這是另一件事
KV 快取(上面提過的暫存區)是跟權重分開的東西,也可以另外量化。llama.cpp 的命令列工具說明列出了 -ctk 與 -ctv 兩個選項,分別設定 K 和 V 的資料型別,可選值包括 f32、f16、bf16、q8_0、q4_0、q4_1、iq4_nl、q5_0、q5_1,預設是 f16(選項名稱可能變動,以官方說明為準)。這代表:權重用 Q4_K_M,不會自動讓 KV 快取也變小,兩者要分開設定。
Transformers 這邊也有對應的量化快取(QuantizedCache),官方的警告是:如果上下文很短,而且顯存本來就夠用,量化快取反而可能增加延遲,要在記憶體效率與延遲之間找平衡。所以長上下文才是它派得上用場的時候,這也呼應了前面「往下降一級」之外的另一條路:與其降權重的等級,也可以評估把 KV 快取量化。至於哪個選擇對你的任務更划算,官方沒有給通用答案。
四個常見誤解
誤解一:位元數越低就一定越快
量化減少要讀的資料量,所以常常有幫助:llama.cpp 官方說明寫的是「可以加速推論」,用的是「can」。Transformers 的說明則更精確:只量化權重的方法省記憶體,但不一定更快,因為還原會增加運算。再看 llama.cpp 官方針對 Llama-3.1-8B 的表格(官方沒有標明測試硬體,所以只能看趨勢):F16 的文字生成速度是表中最低的,量化之後多半變快;但 3 位元的 Q3_K_S 的生成速度,反而低於 4 位元的 Q4_K_S。同一張表裡,速度不是位元數的單調函數。這裡刻意不抄表中的速度數字,因為它們只屬於那次測試的環境,拿來估你的速度只會誤導;要怎麼正確測速,見Token/s 怎麼看。
誤解二:量化就是把模型壓縮,之後可以還原
不能。量化是有損的,還原得到的是近似值(見上面的定義)。如果你需要最高精度,應該保留 16 位元的版本,量化只是從它產生較小的副本。
誤解三:量化一定讓模型笨到不能用,或者完全沒差
兩個極端都沒有官方依據。官方的資料指向中間:8 位元非常接近 bf16,4 位元精度高,低於 4 位元有明顯下降。單一模型的困惑度增加量,在高位元時很小、位元降低時變大(見前面的表)。至於這些差距在你的任務上算不算「笨」,答案取決於任務,需要自己試。
誤解四:檔案多大,就只需要多少顯存
檔案大小只是權重的部分。載入時還要留 KV 快取(隨上下文成長)以及其他執行開銷。Hugging Face 的指南也只在「輸入少於 1024 個 token」的前提下,才說記憶體需求主要由載入權重決定。如果你用的是 MoE(混合專家)模型,參數怎麼存、怎麼算大小,見MoE 混合專家模型;這篇的公式適用於「檔案裡所有權重」的總數。
實際使用工具時
如果你想看一個本地大模型工具實際怎麼用,可以參考Strata 與 PolyStrata 的比較。工具的安裝與設定不在本文範圍;你在這些工具裡看到的模型名稱後綴(例如 Q4_K_M),就是這篇講的東西。
延伸閱讀
- 依顯存選模型與顯存估算方法:先算出你的預算,再回到這篇挑量化等級。
- 顯存、記憶體、硬碟各扮演什麼角色:量化後的檔案載入時放在哪裡。
- MoE 混合專家模型:總參數與實際使用的參數不同,會影響估算。
- Token/s 怎麼看與正確的速度測試方法:量化對速度的影響要怎麼量。
- Strata 與 PolyStrata 的比較:本地大模型工具範例。
- 術語表:LLM、context window(上下文視窗)、token 等名詞的簡短定義。
常見問題
Q4_K_M 和 Q8_0 差在哪裡?
差在每個權重平均用多少位元儲存。llama.cpp 官方針對 Llama-3.1-8B 列出的數字,Q4_K_M 約 4.89 位元、Q8_0 約 8.50 位元,所以 Q8_0 的檔案大約是 Q4_K_M 的 1.7 倍。位元數越高通常越接近原始精度,但要放進顯存的東西也越多。
GGUF 是量化方法嗎?
不是。GGUF 是裝模型的單一檔案格式,裡面有 metadata(模型的描述資料)和每個 tensor(權重陣列)的名稱、維度與型別。量化型別是記錄在每個 tensor 上的屬性,所以 GGUF 檔案裡可以是 Q4_K_M,也可以是未量化的 F16。
量化後模型會變笨嗎?
會有精度損失,這是官方說明直接寫的,但損失多大要看量化等級、模型與任務。Hugging Face 的 Llama 3.1 比較中,8 位元方法與 bf16 非常接近,低於 4 位元則有明顯下降;實際影響請用你自己的任務確認。
位元數越低就一定越快嗎?
不一定。量化減少的是要讀取的資料量,文字生成常常受限於讀取權重的速度,所以通常有幫助;但 Hugging Face 的說明也指出,只量化權重的方法省記憶體卻不一定更快。llama.cpp 官方表格裡,3 位元的 Q3_K_S 生成速度還低於 4 位元的 Q4_K_S。
4 位元量化的 8B 模型大概要多少顯存?
先用公式估檔案大小:參數數量乘以每權重位元數再除以 8。以 llama.cpp 官方列的 Llama-3.1-8B Q4_K_M 為例,檔案是 4.58 GiB,這還沒算 KV 快取與其他執行開銷,所以顯存要留比檔案更大的空間。
量化可以讓我自己轉換任何模型嗎?
llama.cpp 官方流程分兩步:先把原始模型轉成 GGUF,再用量化工具轉成目標型別。官方也提醒,對已量化過的權重再次量化可能大幅降低品質,建議從 16 位元或 32 位元的版本開始。
留言
用 GitHub 帳號登入就能留言,留言會公開顯示在 GitHub Discussions。留言前請先看社群規則。