BF8・BF16・蒸留・量子化、「精度とサイズのトレードオフ」
BF8・BF16・蒸留・量子化は、全部「精度とサイズのトレードオフ」を別の角度から攻める技術です。
1. モデルサイズを小さくする4つの軸
- 軸A: 表現フォーマットを軽くする
- BF16, FP16, BF8, FP8 など「浮動小数のビット数」を減らす
- 目的: メモリ削減+計算高速化(主にGPU・NPU側の都合)
- 軸B: 重み自体を小さい整数に丸める
- INT8, INT4, FP4 など「量子化(Quantization)」
- 目的: メモリ削減+CPU/専用ハードでの高速推論
- 軸C: モデル構造そのものを小さくする
- 蒸留(Knowledge Distillation) で小モデルへ知識を移す
- パラメータ数そのものが減るので、フォーマットに関係なく効く
- 軸D: スパース化や構造的な圧縮
- プルーニング、LoRA 等
2. BF16(bfloat16)でサイズを小さくする
BF16のフォーマットと特徴
BF16 は Brain Floating Point 16-bit の略で、Google が TPU 向けに定義した16ビット浮動小数点形式です。
- ビット構成:
- 符号: 1 ビット
- 指数: 8 ビット
- 仮数(小数部): 7 ビット
- FP32 と比べると:
- FP32: 1 + 8 + 23 ビット
- BF16: 1 + 8 + 7 ビット
- → 指数部が同じなので、FP32 と同じダイナミックレンジ を持つが、精度(有効桁数)はかなり落ちる
つまり BF16 は、
「FP32 と同じくらい広い値の範囲を表現できるが、桁数はざっくり 3 桁程度」
というイメージです。
BF16にするとどれくらいサイズが減るか
- FP32 → BF16 にすると、同じ重み数で メモリ使用量はちょうど半分 になります。
- 多くのハードウェアやコンパイラは、FP32 モデルを入力して内部で自動 BF16 化 をサポートしています。
例:
パラメータ数 ( P ) のモデルで、FP32 なら必要メモリは約 ( 4P ) バイト。
BF16 なら約 ( 2P ) バイト。
→ 純粋に 2倍の圧縮。
BF16の用途と注意点
- 用途:
- 学習: 多くのタスクで BF16 だけで学習を完結できることが研究で示されている
- 推論: 学習後モデルを BF16 にしても精度への影響は小さいことが多い
- 注意点:
- 仮数部 7 ビットとやや粗く、数値の微妙な差を扱う部分で誤差が増える可能性
- とはいえ、FP16 よりオーバーフロー/アンダーフローに強く扱いやすいので、最近は 学習・推論どちらも BF16 主流 になりつつあります
3. BF8 / FP8でさらに小さくする
FP8/BF8の概要
FP8(8ビット浮動小数)は、さらに軽量 な浮動小数フォーマットで、NVIDIA の Blackwell 世代などがサポートしている形式です。
代表的なフォーマット:
- E4M3: 1ビット符号 + 4ビット指数 + 3ビット仮数
- E5M2: 1ビット符号 + 5ビット指数 + 2ビット仮数
これに BF16 のような発想を加えた BF8/FP8 変種 や、ブロック単位でスケールを変える MXFP8 等も使われます。
FP8にするとどれくらいサイズが減るか
- FP32 → FP8/BF8 なら、ビット数は 1/4
- メモリ使用量も理論上 1/4 になります。
- BF16 から見てもさらに 1/2。
例:
FP32 モデル 40 GB → BF16 なら 20 GB → FP8 なら 10 GB というイメージ。
FP8/BF8の使い方とトリック
- 用途:
- 主に 推論、または特定パスの学習(forwardだけFP8など)
- 課題:
- 8ビット浮動小数は ダイナミックレンジも精度もかなり厳しい。
- そのため、NVIDIA は 「マイクロスケーリング (microscaling)」 やブロック単位スケーリング(MXFP8)で、テンソルごと・ブロックごとのスケール係数を持たせて誤差を抑える。
実務イメージ:
- 重要な層(embedding や出力層)は BF16 を維持
- 中間の FFN / Attention の重みだけ FP8 にする
- もしくは、重み FP8 + スケール、アクティベーション BF16 等のハイブリッド構成
4. 量子化(Quantization)で整数に落とす
量子化の基本
量子化は、FP32 や BF16 の値をより少ないビット数で表現 することです。
- 代表例:
- FP32 → BF16 / FP16:浮動小数のままビット数だけ減らす
- FP32 → INT8 / INT4:整数に丸める
AMD の資料でも、BF16 や INT8 への変換を「モデル量子化」 として扱っています。
INT8 量子化でのサイズ削減
- FP32 → INT8
- 4バイト → 1バイト
- モデルサイズは 1/4。
- BF16 から INT8 でも 1/2。
例:
10 億パラメータのモデル(FP32) → 約 4 GB
INT8 量子化 → 約 1 GB
量子化の方法
- PTQ(Post-Training Quantization):
- 学習済みモデルに対して、データサンプルを流し、統計をとって後付けで量子化
- 速いが、精度劣化が大きく出る場合がある
- QAT(Quantization-Aware Training):
- 学習中から量子化の誤差をシミュレートして学習
- 手間は増えるが、INT8 でも FP32 にかなり近い精度 まで持っていける
- ミックス精度量子化:
- 重要層: BF16/FP16
- その他: INT8/FP8
- → 精度を守りつつ、サイズと速度を稼ぐ
量子化の精度劣化ポイント
- Embedding 層、最終出力層、LayerNorm など は、INT8 化すると精度が落ちやすいので BF16 に残す設計が多いです。
- シーケンス長が長い言語モデル ほど、誤差の累積が効いてくるので、どこを何ビットにするかの設計が重要。
GGUFとは?
GGUF(Grokking GGML Unified Format) は、llama.cpp などで使われる 軽量なモデル保存形式。
以前の .bin 形式(GGML)を進化させたもので、以下の特徴がある:
- 量子化済みモデルを効率的に保存・読み込み可能
- メタデータやトークナイザ情報も内包
- 複数の量子化方式に対応(Q4, Q5, Q8, INT4, FP16など)
Q4_K_M の意味を分解!
Q4_K_M は GGUF で使われる量子化方式のひとつ。
この名前にはそれぞれ意味がある:
| 部分 | 意味 |
|---|---|
Q4 | 4ビット量子化(1つの重みを4ビットで表現) |
_K | K系列の量子化方式(精度と圧縮率のバランスが良い) |
_M | Mバリアント(K系列の中でも特に精度が高い設計) |
K系列とは?
Q4_K,Q5_K,Q6_Kなどがある- 特徴は:
- ブロック単位でスケーリング(例:32個の重みごとにスケールとゼロ点を持つ)
- 精度が高く、INT8に近い性能を出せる
K_Mはさらに Mバリアントで、スケーリングの工夫や 誤差補正が入ってる
Q4_K_Mの特徴
- 精度: Q4系の中では最も高精度(Q4_0 < Q4_1 < Q4_K < Q4_K_M)
- サイズ: FP16の約1/4(4ビットなので)
- 用途: 精度をなるべく保ちつつ、メモリ4GB〜8GBのGPUやCPUでも動かしたいときに最適
- 対応: llama.cpp、text-generation-webui、koboldcpp などでサポート
| フォーマット | 精度 | サイズ | 備考 |
|---|---|---|---|
F16 | ◎ | 大 | 高精度、重い |
Q8_0 | ◎ | 中 | INT8相当、精度高め |
Q6_K | ○ | 小 | 精度とサイズのバランス良し |
Q4_K_M | △〜○ | 小 | 4bit量子化の中で高精度、軽量 |
Q2_K | × | 超小 | 精度は大きく落ちるが超軽量 |
参考
うさぎでもわかるLLM量子化手法完全ガイド: q4_K_Mの謎を解く
5. 蒸留(Knowledge Distillation)でモデル自体を小さくする
蒸留の概念
蒸留は、大きな「教師モデル」から小さな「生徒モデル」へ知識を移す 手法です。
やることは本質的に:
- 教師モデルに入力を与え、出力分布(logits や soft label)を得る
- 生徒モデルに同じ入力を与え、「教師の出力」を模倣するように学習させる
- 場合によっては、中間層の表現もマッチさせる
こうして、パラメータ数・層数そのものを削減 するので、FP32 のままでもサイズは小さくなり、さらに BF16/INT8 などと組み合わせることができます。
サイズ圧縮のイメージ
- 教師: 70B パラメータ LLM
- 生徒: 7B パラメータ LLM
この時点で 10分の1 サイズ。
さらに、生徒を BF16 で保存 → さらに 1/2、
INT8 量子化 → 最大 1/4 まで圧縮可能。
つまり、
「元の教師 FP32 と比べると 理論上 40分の1 近く というレベルまで落とせる」ケースもあり得ます。
蒸留の本質的メリット
- 単純にビット数を削るだけでは補えない「表現の再最適化」ができる
- 小さい生徒が、特定タスクでは教師に匹敵する性能 を出すこともある
- その上で 量子化をかけると精度劣化が抑えられる 場合も多い
6. 実務的な組み合わせ方のパターン
パターン1: まず BF16(or FP16)に落とす(いちばん安全)
- 学習中:
- 可能なら BF16 で mixed precision training
- 推論用チェックポイント:
- とりあえず BF16 で保存
- モデルサイズは FP32 の 1/2、精度はほぼ維持
これは「安全な第一歩」としてほぼ必須に近い選択です。
パターン2: BF16 + INT8 量子化(現実的に多い)
- BF16 モデルをベースに
- 中間層の重み・アクティベーションを INT8 に
- 精度劣化が大きい層だけ BF16 を維持する
結果:
- サイズは FP32 の 1/4〜1/3 程度
- 推論速度も改善
- うまくチューニングすれば、ほとんどのエンドユーザは精度低下に気づかないレベル
パターン3: 蒸留 + INT8(ガッツリ攻める)
- 大きい FP32/BF16 モデルを教師にして、小さいモデルを蒸留
- 生徒モデルを INT8 量子化
- 重要層だけ BF16 を残す
結果:
- パラメータ数 × ビット数の両方を削る
- Teacher からの蒸留により、小さいモデルでもタスク特化ではかなり強い
パターン4: FP8/BF8 を含むミックス精度(ハイエンドGPU前提)
- Blackwell 等 FP8 対応 GPU 前提の構成になります。
- 重み: FP8 + スケーリング
- アクティベーション: BF16
- さらに一部 INT8/FP4 なども混ぜる
7. まとめ(どう設計するかの指針)
- BF16:
- FP32 と同じダイナミックレンジでメモリ半分。
- 学習・推論どちらも現実的なデフォルト候補。
- BF8/FP8:
- メモリは FP32 の1/4まで落ちるが、誤差が大きい。
- 先端GPUでのミックス精度向け。スケーリング戦略が必須。
- 量子化(INT8 など):
- モデルサイズを 1/4 程度まで削減。一部層のみ高精度を維持する設計が鍵。
- QAT で精度を取り戻すのがベストプラクティス。
- 蒸留:
- パラメータ数そのものを減らす「構造的圧縮」。
- その後に BF16/INT8/FP8 を適用すると、掛け算的に効いてくる。











ディスカッション
コメント一覧
まだ、コメントがありません