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 で使われる量子化方式のひとつ。
この名前にはそれぞれ意味がある:

部分意味
Q44ビット量子化(1つの重みを4ビットで表現)
_KK系列の量子化方式(精度と圧縮率のバランスが良い)
_MMバリアント(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_0INT8相当、精度高め
Q6_K精度とサイズのバランス良し
Q4_K_M△〜○4bit量子化の中で高精度、軽量
Q2_K×超小精度は大きく落ちるが超軽量

参考

うさぎでもわかるLLM量子化手法完全ガイド: q4_K_Mの謎を解く

5. 蒸留(Knowledge Distillation)でモデル自体を小さくする

蒸留の概念

蒸留は、大きな「教師モデル」から小さな「生徒モデル」へ知識を移す 手法です。

やることは本質的に:

  1. 教師モデルに入力を与え、出力分布(logits や soft label)を得る
  2. 生徒モデルに同じ入力を与え、「教師の出力」を模倣するように学習させる
  3. 場合によっては、中間層の表現もマッチさせる

こうして、パラメータ数・層数そのものを削減 するので、FP32 のままでもサイズは小さくなり、さらに BF16/INT8 などと組み合わせることができます。

サイズ圧縮のイメージ

  • 教師: 70B パラメータ LLM
  • 生徒: 7B パラメータ LLM

この時点で 10分の1 サイズ
さらに、生徒を BF16 で保存 → さらに 1/2
INT8 量子化 → 最大 1/4 まで圧縮可能。

つまり、
「元の教師 FP32 と比べると 理論上 40分の1 近く というレベルまで落とせる」ケースもあり得ます。

蒸留の本質的メリット

  • 単純にビット数を削るだけでは補えない「表現の再最適化」ができる
  • 小さい生徒が、特定タスクでは教師に匹敵する性能 を出すこともある
  • その上で 量子化をかけると精度劣化が抑えられる 場合も多い

6. 実務的な組み合わせ方のパターン

パターン1: まず BF16(or FP16)に落とす(いちばん安全)

  1. 学習中:
  • 可能なら BF16 で mixed precision training
  1. 推論用チェックポイント:
  • とりあえず BF16 で保存
  • モデルサイズは FP32 の 1/2、精度はほぼ維持

これは「安全な第一歩」としてほぼ必須に近い選択です。

パターン2: BF16 + INT8 量子化(現実的に多い)

  1. BF16 モデルをベースに
  2. 中間層の重み・アクティベーションを INT8
  3. 精度劣化が大きい層だけ BF16 を維持する

結果:

  • サイズは FP32 の 1/4〜1/3 程度
  • 推論速度も改善
  • うまくチューニングすれば、ほとんどのエンドユーザは精度低下に気づかないレベル

パターン3: 蒸留 + INT8(ガッツリ攻める)

  1. 大きい FP32/BF16 モデルを教師にして、小さいモデルを蒸留
  2. 生徒モデルを INT8 量子化
  3. 重要層だけ 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 を適用すると、掛け算的に効いてくる。

etc

Posted by eightban