DGX Spark · part 37
[Benchmark] NVFP4 量化砍繁中比砍英文兇兩倍:gemma-4-12B 實測
❯ cat --toc
TL;DR
我把 Google 的 gemma-4-12B 量化成三種格式 —— BF16、FP8 dynamic、NVFP4 weight-only —— 在 DGX Spark GB10 上分別測 英文 MMLU 跟 繁中 TMMLU+。結論:NVFP4 weight-only 量化掉多少分,要看語言。 它讓英文掉 2.7 分、繁中卻掉 6.0 分(相對 −3.5% vs −12.6%)—— 繁中掉的分數大約是英文的兩倍。FP8 dynamic 兩邊都近無損(掉不到 0.4 分)。這篇是回頭補 Part 36 沒算到的帳:那篇說 NVFP4 weight-only 在速度、體積、保住多模態上全贏 —— 那三項它確實贏,但準度的代價是真的,而且砍在比較弱的語言上比較重。
白話版:量化省下來的,繁中付的比較多
量化就是把 AI 模型的數字壓到更少的位元,讓它變小、變快。一般直覺是這會掉一點點準度,而且各方面平均地掉。結果不是這樣:我把這顆模型壓成 4-bit 權重後,繁中掉的準度大概是英文的兩倍。比較溫和的 8-bit(FP8)則兩種語言都幾乎沒掉。所以最便宜、最激進的那種量化不只是「差一點」,而是差得不平均,而且它專挑模型本來就比較弱的那個語言下手。你主要服務英文可能一輩子不會發現;服務繁中就有差。
前言
Part 36 我選出了贏家。我在 GB10 上把 gemma-4-12B(Google 新的 omni 模型)量化,結論是 NVFP4 weight-only 該上線:7.7 GB、24.9 tok/s,而且跟 full W4A4 不一樣,它把圖片、語音、影片都保住了。速度、體積、模態,三個勾。
我那篇沒測到的是第四個面向 —— 準度。「保住多模態」只代表那些模態還會回應,沒說它的回答有沒有變笨。這篇就是回頭把準度這筆帳算清楚,順便拿英文跟繁中對照。一句話:用 NVFP4 weight-only 是有代價的,而且不同語言掉的分數不一樣。
數字:NVFP4 繁中掉 6 分,英文只掉 3 分
下面全是我自己在一台 DGX Spark(GB10、sm_121a)上跑的。每個格式我都用 lm-evaluation-harness 測 MMLU(英文,57 科)跟 TMMLU+(繁中,66 科),5-shot、套 chat template(為什麼要套等下講)、每科 limit=30(N ≈ 英文 1,710 / 繁中 1,980,標準誤 ±1.0 分左右)。
| 格式 | MMLU (EN) | TMMLU+ (TC) | EN 掉分 | TC 掉分 |
|---|---|---|---|---|
| BF16 | 78.30% | 47.21% | — | — |
| FP8 dynamic | 77.95% | 46.97% | −0.35 | −0.24 |
| NVFP4 W4A16 | 75.56% | 41.24% | −2.74 | −5.97 |
看後面兩欄。FP8 兩種語言都只是個 rounding error —— 當無損就好。NVFP4 weight-only 就不一樣了:英文掉 2.7 分、繁中掉 6.0 分。換成相對值是英文 −3.5%、繁中 −12.6%:繁中掉的分數是英文的 ~2.2 倍(絕對)、~3.6 倍(相對)。
哪個結論比較確定、哪個還有待商榷,先講清楚。繁中掉 6.0 分大約是 3.8 個標準誤 —— 這個是真的。英文掉 2.7 分大約 1.8 個標準誤 —— 比較小,確切幅度我不敢拍胸脯,但也不是零。所以誠實的講法不是「NVFP4 英文免費、繁中崩」,而是:兩種語言都會掉分,繁中掉的大概是兩倍。
FP8 是近無損、而且各語言掉分都差不多的選擇
FP8 那一列其實最穩。英文 −0.35、繁中 −0.24,兩個都在誤差範圍內,而且差不多一樣大。FP8 保留 8 bit 的權重精度、activation 依 token 動態量化,沒有對權重做激進的 rounding、也沒有一份 calibration 資料可能偏向某個語言。結果就是掉分小到你量不出來,而且英文繁中差不多。
真正有意思的是這個對照。掉分不平均的問題不在「量化」本身 —— 是這種激進的 4-bit 權重 rounding 才會專挑繁中。改用 8-bit 之後,這個差距就看不到了。
為什麼比較弱的語言掉比較多:一個「脆弱度」假設
機制我沒辦法只靠兩欄 benchmark 證明,所以這段標成假設。英文在預訓練資料裡佔比高到誇張。佔比高換來冗餘 —— 同一份知識被編碼在權重空間裡很多條部分重疊的方向上。當你把這些權重 round 到 4 bit,因為冗餘夠多,影響不大:留得住夠多的有效訊號。繁中拿到的預訓練切片小很多、薄很多,representation 冗餘少、比較不 robust。同一個 4-bit rounding,測英文幾乎沒感覺,測繁中準度卻掉一截。
這跟 4-bit 在 Part 36 對模態做的事是同一個調調。那邊 full W4A4(連 activation 也量化)把圖片、語音、影片整個搞壞,因為圖片/語音的 embedding 對一個用文字校準的 4-bit 範圍來說是 out-of-distribution。機制不同 —— 那是 activation 量化、這是權重量化 —— 但主題一樣:模型本來最弱的那個能力,切 4-bit 時通常最先崩。 W4A4 先壞的是非文字模態;weight-only NVFP4 先壞的是低資源語言。
給個尺度感:gemma-4-12B 繁中 47% 打平更大的 gemma-4-26B(我之前那篇 TMMLU+ 測 46.30%),遠遠落後 Qwen 3.6 35B(75.07%)。Gemma 家族繁中本來就弱,跟精度無關 —— 這是背景。這篇多補的,是疊在上面的量化掉分不對稱。
差點賠掉一個晚上的評測陷阱:沒套 chat template = 低於隨機
這實驗開頭差點就死了,而且死因值得偷學。
我第一次跑,每個格式整體都 ~23% —— 低於 四選一的 25% 隨機線。BF16、FP8、NVFP4 全部 ~23%。這看起來就是模型壞掉或量化壞掉,我一度信了。
兩個都不是。lm-eval 預設用 raw completion loglikelihood 測選擇題,沒套 chat template。一個 instruct / omni model 餵裸 completion prompt,它根本不會進入答題狀態 —— 沒在跟題目互動,A/B/C/D 的 loglikelihood 算出來比亂猜還差。解法就一組 flag:
lm_eval --model hf \
--model_args pretrained=<model>,trust_remote_code=True,dtype=bfloat16 \
--tasks tmmluplus --num_fewshot 5 --limit 30 --batch_size 4 \
--apply_chat_template --fewshot_as_multiturn \
--trust_remote_code
加上 --apply_chat_template --fewshot_as_multiturn,BF16 從 24.3% 跳到 46.1%。模型從頭到尾都好好的,是我餵錯格式。這邊的重點:instruct model 整體低於隨機,通常就是忘了套 chat template,不是模型壞。 怪權重之前先檢查這個。
還有一個這顆模型特有的坑:vLLM 的 /v1/completions(loglikelihood)路徑對 gemma4_unified 會 500、還把 engine 弄死,所以這個 eval 我根本沒辦法走 vLLM server。我改用 transformers 直接跑(--model hf),要夠新的 transformers 才認得 gemma4_unified —— 我跑的是從 main build 的 5.10.1(當時 PyPI 上的穩定版才 5.9.0,所以直接 pip install transformers==5.10.1 是抓不到的)—— 還要把 datasets pin 在 2.21,否則 TMMLU+ 的 builder script 載不進來。HF eager 很慢 —— 每次 forward 都要 dequant、沒有 native 4-bit kernel —— 但測準度慢沒關係,logits 是一樣的。
這趟學到什麼
最花時間的地方。 不是跑分,是踩到 chat template 那個坑。看著三個格式全部低於隨機、又不能馬上確定是模型、是量化、是 eval harness、還是這個全新架構出問題,這段卡我最久。跑分本身是過夜幾小時無人顧。
可以帶著走的排錯經驗。 有兩點其他模型也適用:(1) instruct model 整體低於隨機 → 先懷疑 chat template,別先懷疑權重;(2) 當某個 serving runtime 對新架構的 loglikelihood 路徑壞掉時,退回 transformers --model hf 測準度 —— 這樣跑比較慢,但算出來的分數是準的。還有一個關鍵的實驗設計:跑 benchmark 時,針對你懷疑的變因一定要設對照組。 只測單一語言,數字會是「NVFP4 掉 6 分」,我就當成普通掉分打發掉。把英文跟繁中擺一起跑,才看出背後真正的問題。
一句話原則。 4-bit 權重量化掉的準度不是平均分攤的 —— 會先掉在模型本來就最弱的地方。這次是低資源語言。你在意的變因一定要設對照組跑,不然看不出來。
結論
- FP8 dynamic 近無損、而且各語言掉分都差不多(gemma-4-12B 上英文 −0.35、繁中 −0.24)。準度掉不起就選這個。
- NVFP4 weight-only 不是免費的。 它還是贏速度(24.9 vs 15.9 tok/s)、贏體積(7.7 vs 13 GB)、保住多模態 —— 但代價是英文掉 2.7 分、繁中掉 6.0 分。
- 4-bit 掉分不平均。 繁中掉的絕對分數約是英文兩倍(相對 ~3.6 倍)。你服務的是非英文或低資源語言,上 4-bit 前先自己量。
- 看到 MMLU / TMMLU+ 整體低於隨機,先加
--apply_chat_template --fewshot_as_multiturn,再去怪模型或量化。 - 範圍:單一模型家族(gemma-4-12B omni)、單一量化配方(llmcompressor NVFP4A16 weight-only)、limit=30。當參考、不是定律 —— 但已經夠乾淨,足以改變我幫繁中為主的工作挑量化格式的方式。
本系列其他篇:Gemma 4 12B Omni:Weight-Only NVFP4 贏過 W4A4 · Qwen 3.6 vs Gemma 4 繁中對決(TMMLU+)
常見問題
- NVFP4 weight-only 量化會掉準度嗎?
- 會,而且分語言掉得不平均。gemma-4-12B 上,NVFP4 weight-only(W4A16)英文 MMLU 掉 2.7 分(78.3 → 75.6)、繁中 TMMLU+ 掉 6.0 分(47.2 → 41.2)。換算成相對值是英文掉 3.5%、繁中掉 12.6%。FP8 dynamic 則兩邊都近無損,掉不到 0.4 分。
- 量化要選 FP8 還是 NVFP4?
- 看你要什麼。NVFP4 weight-only 比較小(7.7 GB vs 13 GB)也比較快(GB10 上 24.9 vs 15.9 tok/s),但 gemma-4-12B 上的代價是繁中準度掉 6 分。FP8 dynamic 英文繁中都近無損。繁中(或其他低資源語言)為主的場景選 FP8 比較保險;主要服務英文又想要速度跟省記憶體,NVFP4 合理。
- 為什麼我跑 lm-eval MMLU 分數低於隨機(25%)?
- 幾乎都是因為你在用 raw completion loglikelihood 測一個 instruct / chat model,又沒套 chat template。加上 --apply_chat_template --fewshot_as_multiturn 就好。gemma-4-12B 上光這個 flag 就把整體分數從 24.3%(低於 25% 隨機線)拉到 46.1%。整體低於隨機是 chat template 沒套的招牌訊號,不是模型壞或量化壞。
- 4-bit 量化對非英文語言的傷害比較大嗎?
- 在這個實驗裡是。NVFP4 weight-only 砍 gemma-4-12B 的繁中,絕對分數約是英文的兩倍、相對值約是 3.6 倍。可能的原因是英文在預訓練資料裡佔比極高,表徵冗餘度夠、扛得住 4-bit rounding;低資源語言的表徵比較脆。這是單一模型單一量化配方,當參考、別當定律。