実験日: 2026-08-24
GPU: RTX 5070 Ti 16GB / WSL2 / Ollama 0.32.15
同じ4Bモデルでも、OllamaにはQ4、Q8、FP16など複数の量子化variantがあります。数字が大きいQ8を選べば精度が上がりそうですが、必要なstorageとVRAMが増え、生成速度も変わります。
Q8の方が高精度に見えますが、その差に見合う容量と待ち時間なのかは実測が必要です。
Gemma 3 4Bのarchitectureとparameter数を固定し、Q4_K_MとQ8_0だけを変えて実測しました。Q8はQ4よりmodel fileが49%大きく、GPU使用量が33%増え、生成速度は25%低下しました。一方、固定四択probeではQ4の79/96に対しQ8は85/96でした。
ただし、96回答は独立な96問ではありません。24問の選択肢を4通りに回転したものです。Q8の6回答差を一般的な「品質が6.25ポイント高い」とは解釈できません。この記事の価値は、量子化比較で速度だけでなく、選択肢順への頑健性までどう測るかにあります。
Q4とQ8の差
| 指標 | Q4_K_M | Q8_0 | Q8の変化 |
|---|---|---|---|
| model file | 3.11GiB | 4.64GiB | +49.2% |
| peak GPU used | 4,806MiB | 6,372MiB | +32.6% |
| warm生成速度 | 180.6 tok/s | 135.1 tok/s | -25.2% |
| warm TTFC | 57.0ms | 54.0ms | ほぼ同じ |
| cold reload | 2.02秒 | 2.01秒 | ほぼ同じ |
| 固定四択probe | 79/96 | 85/96 | +6回答 |
| 順序一貫の問題 | 16/24 | 17/24 | +1問 |
このPCなら通常はQ4_K_Mから始めます。180 tok/sと高速で、Q8より約1.5GiB少ないVRAMで動くからです。四択probeのようなtaskでQ4の誤りが実害になると確認できた場合にQ8へ上げます。

量子化は何を削っているのか
ニューラルネットのweightは実数です。高精度なfloatで保存すると多くのbitが必要です。量子化では、weightを限られた離散値へ写像して少ないbitで表します。
単純化した対称量子化なら、block内のweight wをscale sで割ってintegerへ丸めます。
q = round(w / s)
w_hat = s × q
qのbit数を減らすほど保存容量は減りますが、復元値w_hatと元のwの差、つまり量子化誤差は一般に大きくなります。
今回のvariantです。
gemma3:4b-it-q4_K_M → Q4_K_M
gemma3:4b-it-q8_0 → Q8_0
どちらも同じGemma 3 4B instruction-tuned modelです。/api/showでarchitecture、4.3B parameter、templateを確認し、量子化levelだけが異なる組を使いました。
Ollama公式のGemma 3 tagsでは、4BのQ4_K_Mが3.3GB、Q8_0が5.0GB、FP16が8.6GBとして配布されています。この記事のGiB表記はAPIが返したbyte数を1024の3乗で割った値なので、公式の10進GB表記より小さく見えます。
なぜQ8はQ4の2倍のファイルではないのか
実測file sizeです。
Q4_K_M 3,338,801,804 bytes = 3.11 GiB
Q8_0 4,979,946,122 bytes = 4.64 GiB
Q8はQ4の1.49倍でした。名前だけを見ると8 bit対4 bitで2倍に思えますが、GGUF全体が一律4 bitまたは8 bitではありません。
- tensorによって保存形式が異なる
- blockごとのscaleなどmetadataがある
- normalizationなど高精度で残るtensorがある
- tokenizer、prompt template、vision encoderなども含む
したがって「bit数の比=ファイル容量の比」ではありません。比較するときはmodel名から暗算せず、実際のmanifest sizeを読みます。
実験条件
GPU NVIDIA GeForce RTX 5070 Ti 16GB
Ollama 0.32.15(WSL側)
model Gemma 3 4B instruction tuned
context 4,096
output limit 256 tokens
temperature 0
seed 42
thinking false
modelを取得します。
ollama pull gemma3:4b-it-q4_K_M
ollama pull gemma3:4b-it-q8_0
ollama list
性能測定では同じdata leakage解説promptを使いました。以下は主要要件で、完全な入力はraw JSONに保存しています。
data leakageを説明してください。
訓練・validation・testの役割、典型例、検出方法、予防策を
見出し付きで700字以上にまとめてください。
各variantで次を3 cycle繰り返しました。
keep_alive=0でunload
→ cold generate 256 tokens
→ 同じmodelを残してwarm generate 256 tokens
OllamaのGenerate APIが返すeval_count / eval_durationからtoken/sを計算しました。streamingの最初の本文到着はPythonのwall clockでTTFCとして測定しました。request中は50msごとにnvidia-smiでGPU全体のmemoryをsampleしています。
Q4は180.6 tok/s、Q8は135.1 tok/s
warm 3回の結果です。
Q4_K_M 180.0 ~ 180.7 tok/s 中央値 180.6
Q8_0 134.7 ~ 135.3 tok/s 中央値 135.1
Q8はQ4より約25.2%遅くなりました。同じ4.3B parameterでも、8 bit weightは読み出すdata量が大きくなります。LLMのtoken生成では各stepでweightを繰り返し読むため、memory bandwidthの影響を受けます。
ただし、この説明は今回のGPUとOllama実装に対する解釈です。GPU architecture、kernel、batch、prompt長、offload率が変われば比率も変わります。
warm TTFCはQ4 57.0ms、Q8 54.0msでほぼ同じでした。最初の1 token付近の短い処理では、256 token全体のdecode速度差ほど明確に離れませんでした。
GPU使用量は約1.5GiB増えた
ピークのGPU全体使用量です。
Q4_K_M 4,806 MiB ≒ 4.69 GiB
Q8_0 6,372 MiB ≒ 6.22 GiB
差 1,566 MiB ≒ 1.53 GiB
Q8は約32.6%増です。model fileの増加率49.2%より小さくなりました。nvidia-smiの総使用量には共通のruntime、KV cache、desktop側使用分が含まれ、それらすべてが量子化bit数に比例するわけではないためです。
どちらも16GBへ100% GPU offloadできました。4K contextならQ8でも約9.9GiBの余裕がありますが、長contextではKV cacheが増えます。「Q8が6.2GiBだから残りは自由」とは考えません。
cold reloadは両方約2.02秒だった
unload後のAPI load_duration中央値です。
Q4_K_M 2.019 s
Q8_0 2.015 s
Q8 fileは1.5GiB大きいのに、3回の中央値はほぼ同じでした。これは完全cold disk readではありません。直前に使ったpageがOS cacheへ残り、runner初期化やGPU memory allocationも混ざります。
普段のmodel切替待ち時間としては有用ですが、SSDの純粋な読込benchmarkにはなりません。download直後の初回値も除外しています。
品質差を1つの自由記述だけで決めない
同じprompt、temperature 0、seed 42でも、Q4とQ8の自由記述は完全一致しませんでした。256 token出力の文字列類似度は59.7%です。
Q4とQ8は冒頭の見出しから異なり、Q8は訓練・検証・テストの役割と対策を明示する構成でした。完全な出力はraw JSONで比較できます。
量子化誤差でlogitが少し変わると、greedy decodingでも途中で別tokenを選び、その後の文脈が分岐します。しかし文字列が違うことは、Q8の意味品質が高い証拠ではありません。片方だけ正しいfact、構成の完結性、task達成率などを別に評価する必要があります。
両方ともnum_predict=256へ達し、回答は途中で切れました。700字以上というprompt要求よりgeneration上限が優先されています。この自由記述は速度測定用であり、完成度の採点には使いません。
四択は選択肢順を4回変えた
最初は24問を1配置だけで測りました。しかし正解位置がA/Bへ偏り、modelがAを選びやすいだけでも高得点になります。
そこで各問題の選択肢をcyclicに4回回しました。1問につき正解がA、B、C、Dへ1回ずつ現れます。
for question in questions:
for rotation in range(4):
rotated = choices[rotation:] + choices[:rotation]
answer = ask_model(rotated)
問題は機械学習、algorithm、network、OS、database、floating pointなど情報科学基礎の24問です。回答はA/B/C/Dの1文字に制約しました。
24 questions × 4 choice orders = 96 responses / quantization
この設計なら、同じ知識を選択肢位置だけ変えて再検査できます。
Q4は79/96、Q8は85/96
Q4_K_M 79 / 96 = 82.3%
Q8_0 85 / 96 = 88.5%
Q4とQ8の回答が異なったのは6配置で、すべてQ8だけが正解でした。差が出たtopicは3問です。
- training loss低下・validation loss上昇をoverfittingと判断
- 見逃しを減らすときrecallを重視
- Bayesの定理で
P(B|A)P(A)を選ぶ
ただし「Q8は6.25ポイント高品質」と一般化してはいけません。96回答は24問を繰り返したpaired dataで、独立な96問ではありません。差はわずか3 topicに集中し、問題も筆者作成の小規模probeです。
ここから言えるのは、この具体的probeではQ8がQ4より6回答多く正解した、という範囲です。標準benchmarkや実際の研究taskでも再現するかは未確認です。
選択肢順に頑健だったのは16問と17問
同じ問題の4配置すべてで、同じ選択肢textを選んだ問題数です。
Q4_K_M 16 / 24 questions
Q8_0 17 / 24 questions
Q8も7問ではchoice orderにより選ぶ内容が変わりました。正解率が高い方でも、prompt上の順序に敏感です。
これはLLMでmultiple-choice評価をするときの落とし穴です。1つのchoice orderだけでは、知識とposition biasを混同します。少なくとも選択肢をshuffleまたはrotationし、結果が安定するか確認すべきです。
Q8を選ぶべき場合
Q8が合理的なのは次の場合です。
- 実taskの評価setでQ4より一貫して改善した
- 約1.5GiBの追加VRAMを許容できる
- 180.6から135.1 tok/sへの低下が問題にならない
- 他のGPU processや長contextと同居してもmemoryに余裕がある
逆に、chat UI、prompt開発、簡単な要約、何度も回すagent loopではQ4の速度が大きな利点です。Q4でtask scoreが十分なら、Q8へ上げても待ち時間とmemoryだけ増える可能性があります。
自分のPCで再現する
cd /mnt/c/Users/user/Documents/Codex/2026-08-24/ko
python3 work/ai_lab/experiment_gemma_q4_q8.py
scriptはPython標準libraryだけを使い、前記事のOllama streaming/GPU monitor helperをimportします。
出力です。
work/ai_lab/results/gemma_q4_q8.json
JSONには次を保存します。
- model fileのbyte数とquantization metadata
- cold/warm各runのAPI timing
- 50ms間隔のGPU memory/utilization sample
- 256 tokenの自由記述全文
- 24問×4順序のprompt、raw response、parse結果、正誤
- Q4/Q8 disagreement
- choice orderに対するquestion単位の一貫性
再現時はOllama version、model ID、GPU、context、temperatureを必ず一緒に記録してください。同じQ4という呼び方でもmodelとquantization方式が違えば結果は変わります。
今回の限界
- 四択は標準benchmarkではなく筆者作成24問
- 4 rotationは同じ問題の反復で、96 independent samplesではない
- Gemma 3 4Bだけを比較し、他familyへ一般化できない
- 日本語promptだけで、英語やcode生成は未評価
- contextは4Kだけ
- QAT、FP16、Q5、Q6は未比較
- 自由記述は256 tokenで打ち切り
まとめ
- Gemma 3 4B Q8_0はQ4_K_Mよりmodel fileが49.2%大きい
- peak GPU usedは約1.5GiB、32.6%増えた
- warm生成速度は180.6から135.1 tok/sへ25.2%低下した
- warm TTFCとOS cache下のreload中央値はほぼ同じだった
- 固定四択probeはQ4 79/96、Q8 85/96
- 差は3 topicの6配置に集中し、一般的な品質差とは断定できない
- choice orderへ完全に一貫したのはQ4 16/24、Q8 17/24だけだった
量子化の選択は「Q8の方が数字が大きいから」では決められません。自分のtaskでQ4とQ8をpaired評価し、得られた改善が約1.5GiBのVRAMと25%の速度低下に見合うかで決めるのが再現可能な方法です。
