- 16bit を 4bit に削っても文章が書ける 3 つの理由 — 重みの分布・行列積による誤差の打ち消し・重要な場所を守っていること
- 「4bit」と名乗るファイルが、実は全テンソル 4bit ではないこと。その実効ビット数
- 逆に量子化が壊れる 2 つの方向 — 活性化の外れ値と、層をまたぐ誤差の蓄積
- 「大きいモデルほど低ビットに強い」がどこまで正しいか。3bit 以下で何が起きるか
第 3 章で、量子化の手続きそのものは単純だと分かりました。値をスケールで割って整数に丸め、ブロックごとにスケールを持たせる。ここで残る疑問はひとつです。そんな乱暴なことをして、なぜモデルは動き続けるのか。この章はその一点だけを扱います。
問い — 情報を 1/4 に削って、なぜ壊れないのか
1 つの重みに 16bit を使えるなら、ビットの組み合わせは 2 の 16 乗 = 65,536 通りあります。4bit ならたった 2 の 4 乗 = 16 通りです。「65,536 段階の目盛りを 16 段階に置き換える」と言い換えると、直感はこれを拒否します。写真を 16 色に減色したときのことを思えば、当然の反応でしょう。
ところが実測はこうです。llama.cpp 公式の測定(Llama 3 8B、Wikitext-2、RTX 4090)で、FP16 のファイルは 14.97 GiB、perplexity は 6.2332。これを Q4_K_M にすると 4.58 GiB(計算例: 14.97 ÷ 4.58 ≈ 3.3 分の 1)、perplexity は 6.4071、公式表の ΔPPL 列は +0.1755 でした。perplexity(PPL、= 同じ文章を読ませたときの「次の語の当てにくさ」を表す指標。低いほど良い)の詳しい読み方は第 9 章で扱いますが、ここで押さえたいのは桁です。ファイルは 3 分の 1 以下になり、指標の悪化は 2.8%(同じ表の Mean PPL ratio が 1.028160)に留まります。
この不均衡には理由があります。この章では 3 つの「壊れない理由」と 2 つの「壊れる方向」を順に見ます。
- 理由 1: 重みの値が 0 のまわりに集まっている(分布が量子化に向いている)
- 理由 2: 行列積が多数の積の和なので、丸め誤差が打ち消し合う
- 理由 3: そもそも全部を 4bit にしていない(重要なテンソルは高精度で残す)
- 壊れる方向 1: 活性化の外れ値
- 壊れる方向 2: 層をまたぐ誤差の蓄積
理由 1 — 重みは 0 のまわりに集まっている
まず、量子化される対象そのものの性質です。QLoRA の論文はこう書いています。「事前学習済みニューラルネットの重みは、通常、標準偏差 σ の 0 中心の正規分布に従う」。しかも著者はこれを検定で裏取りしていて、「5% の有意水準で、非正規と判定されるニューロンは 7.5%。これは期待される偽陽性率より約 2.5% 多いだけ」と報告しています。ほぼ正規分布だが例外もある、という盛らない言い方です。
SmoothQuant の論文は同じことを別の角度から書いています。「重みの分布はかなり一様で平ら(quite uniform and flat)で、量子化しやすい」。ここでの「平ら」は「一部のチャネルだけ桁違いに大きい、ということがない」という意味です。
この 2 つが合わさると、実務上こうなります。ブロック内の絶対値の最大(absmax)が、異常な 1 個に引っ張られない。だから absmax から決めたスケールで作った 16 段の目盛りが、そのブロックに実際に存在する値の範囲をきちんと覆います。目盛りの本数は少なくても、置き場所が当たっているのです。
この性質をさらに突き詰めた例が NF4 という 4bit のデータ型です(型の作り方は第 5 章)。NF4 の 16 個の値は、正規分布の分位点から導かれています。0 の近くは 0 → 0.0796 → 0.1609 → 0.2461 と刻みが細かく、端は 0.7230 → 1.0 と粗い。値が集まっている場所に目盛りを寄せ、めったに値が来ない端は捨てている、という配分です。効果は数字で出ていて、QLoRA 論文の測定(125M〜13B の複数モデル平均、Pile Common Crawl の平均 PPL)では、同じ 4bit でも Int4 が 34.34、NF4 + Double Quantization が 27.41 でした。ビット数を増やさず、目盛りの置き場所だけを分布に合わせて改善した差です。
理由 2 — 行列積が誤差を平均してしまう
2 つめは、量子化された重みの使われ方の話です。LLM の計算はほぼ全部が行列積(= たくさんの掛け算をして、その結果を足し合わせる演算)です。出力 1 個を作るのに、数千個の「重み × 入力」を足します。
丸め誤差はこの数千個それぞれに乗ります。1 個あたりの大きさは、AWQ の論文が「丸め関数の誤差はおおよそ [0, 0.5] の一様分布で、平均は 0.25」と書いているとおり、目盛り幅の半分以内です。効いてくるのはその向きです。ある重みは目盛りの上へ、別の重みは下へ丸められる。符号が揃わないので、足し合わせるときに互いを消し合います。
出力 1 個の誤差 = (重み 1 の丸め誤差 × 入力 1) + (重み 2 の丸め誤差 × 入力 2) + … + (重み N の丸め誤差 × 入力 N)
計算例。誤差が独立で符号がランダムなら、N 項の合計の大きさは N 倍ではなく約 √N 倍に留まります。N = 4096 の内積なら、最悪ケース(全部の誤差が同じ向きに揃う)の 4096 倍に対して、実際は √4096 = 64 倍程度。最悪ケースの 64 分の 1です。出力そのものも符号のばらついた N 項の和なので、やはり √N のスケールで育ちます。誤差と出力が同じ √N で伸びる結果、「出力の相対誤差は、重み 1 個の相対誤差と同程度に留まる」ことになります。誤差が揃っていたら 64 倍に増幅されていた、という対比で読んでください。
ここで第 3 章の W4A16 をもう一度思い出してください。4bit に量子化しても、計算は 4bit で行われません。保存とメモリ転送が 4bit、演算は 16bit です。だから「4bit の桁数で計算して桁落ちする」という種類の崩壊は、そもそも起きません。この節の話にとって効くのは、足し込みが 16bit で行われるからこそ、上で見た誤差の打ち消しが実際に成立するという点です(速度の話は第 8 章)。
もっとも、誤差が完全に消えるわけではありません。上の計算例は誤差の独立性を仮定していますが、同じブロックの重みは同じスケールを共有するので、誤差には相関があります。実測の +0.1755 という劣化はその残りです。量子化手法がこの残りをどう削るかというと、「重みの値をどれだけ正確に再現したか」ではなく「その層の出力がどれだけ元と同じか」を直接の目標に据えます。GPTQ の目的関数は「元の重み × 入力」と「量子化した重み × 入力」の差を最小にする形で書かれています。誤差の効き方が出力側で決まる、という認識がそこに現れています(手法の詳細は第 5 章)。
誤差が薄まるもう 1 つの側面が冗長性です。AWQ の論文は「LLM の重みは等しく重要ではない。わずか 1% の重要な重みを守るだけで量子化誤差を大きく減らせる」と述べています。OPT-1.3B を INT3(128 個ごとに 1 つのスケール)に落とした測定(WikiText PPL、低いほど良い)では、FP16 が 14.62、そのまま丸めた RTN が 119.00 で崩壊するのに対し、活性化の大きさを見て選んだ 1% だけを FP16 に残すと 16.91 まで戻ります。逆に重みの大きさで選んだ 1% では 98.55、ランダムに選んだ 1% では 109.38 で、ほとんど戻りません。1% を正しく選べば戻る = 残りの 99% は多少ずれても構わない、という冗長性の直接的な証拠です。同時に「選び方を間違えると効かない」ことも分かります。
理由 3 — そもそも全部を 4bit にしていない
3 つめは、もっと素朴で、しかしいちばん見落とされている理由です。「4bit モデル」は全テンソルを 4bit にしていません。
llama.cpp の llama-quantize には --pure というオプションがあり、公式の説明は「k-quant mixtures を無効にして、すべてのテンソルを同じ型に量子化する」です。無効にするオプションがあるということは、既定では混ぜているということです。k-quants を導入した公式 PR の定義によれば、Q4_K_M は「attention.wv と feed_forward.w2 のうち半分を 6bit の Q6_K に格上げし、残りを 4bit の Q4_K にする」混合です。さらに「すべての量子化バリアントが output.weight テンソルに 6bit を使う。これにより例えば Q4_0 の perplexity が 7B で約 0.03 下がる」とも書かれています。
だから「4bit」の実効ビット数は 4.0 ではありません。llama.cpp 公式の実測(meta-llama/Llama-3.1-8B)で、Q4_K_M は 4.8944 bits/weight です。差はスケール等のメタデータと、この格上げ分です。名前の「4」は上限でも平均でもなく、主要部分に使われている型の呼び名にすぎません。「M」が何を指すかは第 6 章で分解します。
--pure で全部を同じ型にした場合、右が既定の混合。塗った 2 マスが格上げ分で、これが実効 bpw を 4.0 より太らせている。どのテンソルを守るかは原理から導かれたものではなく、実装が測って選んだ結果である。同じ発想は llama.cpp 以外にもあります。GPTQ の論文は OPT-175B を 3bit に量子化しても「埋め込み層と出力層は FP16 のまま保持する」と明記しています。bitsandbytes を使う BitsAndBytesConfig には「8bit に変換したくないモジュールの明示的リスト」である llm_int8_skip_modules があり、公式 docstring は「例えば CausalLM モデルでは最後の lm_head は元の dtype のまま保たれる」と書いています。llama.cpp のマルチモーダル対応も、投影器(mmproj)を含む「マルチモーダル部品は通常 bf16 や q8 のような高品質形式で保持される」としています。README が挙げる理由は「小さい quant を使ったときの速度・メモリへの影響は無視できるが、全体の品質は影響を受けうる」で、要するに削っても得がないからです。入口と出口は守る、という共通了解があります。
ただし「入口と出口が原理的に敏感」という一般法則が証明されているわけではありません。NVIDIA の量子化ホワイトペーパーが取っている手続きは実測ベースで、「1 層ずつ量子化して精度を測り、感度の高い順に並べ、目標精度に届くまで上位の層を量子化から外す」というものです。EfficientNet-b0 では「最も感度の高い 10 層を外すと相対的な top-1 精度低下が 0.65% に収まる」と報告される一方、BERT については「特定の層が精度低下に大きく寄与しているとは言えなかった」とも書かれています。守る場所は測って決める、というのが正確な理解です。
壊れる方向 1 — 活性化の外れ値
ここまでは「壊れない理由」でした。裏返すと、条件が崩れたところで量子化は壊れます。第一の崖は活性化(= 層から層へ流れていく中間の数値。重みと違って入力ごとに変わる)です。
SmoothQuant の観察はこうです。「活性化の外れ値は量子化を難しくする。外れ値の大きさは、大半の活性化値の約 100 倍」。重みが「平らで一様」だったのと正反対です。1 つの巨大な値がスケールを決めてしまうと何が起きるか、同論文が式で書いています。
チャネル i が実際に使える段階数 = 2^8 × (m_i ÷ m) (m_i = そのチャネルの最大絶対値、m = テンソル全体の最大絶対値)
計算例。あるチャネルの最大値が、テンソル全体の最大値の 100 分の 1 だとします。式に入れると 256 × (1 ÷ 100) ≈ 2.6 段。8bit で 256 段用意したのに、そのチャネルは実質 2〜3 段しか使えません。論文自身が「外れ値ではないチャネルの実効段階数は非常に小さく(2〜3)なり、大きな量子化誤差につながる」と書いています。LLM.int8() の論文はこれを「量子化分布の範囲が広すぎて、ほとんどの量子化ビンが空になり、小さな値は 0 に量子化されてしまう。本質的に情報が消える」と表現しています。
厄介なのは、この外れ値が「たまに出る」ものではなく決まった特徴次元に居座ることです。LLM.int8() の実測値を並べます。
| 観測項目 | 値(LLM.int8() 論文) |
|---|---|
| 外れ値の大きさ | 他の次元の最大値の 3〜20 倍 |
| 急に顕在化する規模 | 約 6.7B パラメータで相転移が起きる |
| 6.7B での外れ値の個数 | 1 シーケンスあたり 150,000 個 |
| それが集中している特徴次元の数 | わずか 6 次元(13B では 2048 トークンのシーケンスで最大 7 次元) |
| 全入力特徴量に占める割合 | 約 0.1% |
| その 0.1% を 0 にすると | アテンションの top-1 softmax 確率質量が 20% 以上減り、perplexity が 600〜1000% 悪化 |
| 同数の次元をランダムに消した場合 | top-1 確率の減少は 0.02〜0.3%、perplexity の悪化は約 0.1% |
「モデルが大きくなると顕在化する」ことも数値で出ています。C4 の validation perplexity(低いほど良い)で、13B を単純な absmax の INT8 にすると 19.08。FP32 の 12.45 より大幅に悪いだけでなく、同じ 8bit の 6.7B(14.59)より悪いのです。モデルを大きくしたのに品質が下がる、という異常な形で壊れます。
回避策は 2 系統あります。1 つは混合精度分解で、外れ値のある特徴次元だけを 16bit で計算し、残り 99.9% を 8bit で計算して足し合わせる(LLM.int8()。追加メモリは約 0.1%)。もう 1 つは数学的に等価な変換で難しさを重み側へ移す方法(SmoothQuant、AWQ)です。それぞれの中身は第 5 章で扱います。
ここが実務上いちばん安心できる点です。ローカル LLM で使う Q4_K_M や NF4 は重みだけの量子化(W4A16 = 重み 4bit・活性化 16bit)です。活性化は 16bit のまま流れるので、上の外れ値問題は最初から発生しません。外れ値との戦いが必要になるのは、計算まで 8bit にする W8A8 のようなスキーム(主にサーバー側の高スループット用途。第 7 章)の話です。
壊れる方向 2 — 誤差は層をまたいで積み上がる
第二の崖は、層の重なりです。NVIDIA の量子化ホワイトペーパーはこう書いています。「ある層の量子化は他の層の入力に影響するため、量子化する層の最適な組み合わせを見つけるには指数的な数の構成を評価する必要があり得る」。1 層あたりの誤差が小さくても、それが次の層の入力を汚し、その層がまた誤差を足す。
これが実在することは、GPTQ の実装が逆説的に証明しています。GPTQ は Transformer ブロックを 1 つずつ量子化していきますが、その際「現在のブロックの入力を、完全に量子化し終えたブロックにもう一度通して、次のブロックの量子化用の入力を作る」という手順を踏みます。論文の言葉では「量子化の処理は、full precision モデルにおける層の入力ではなく、すでに部分的に量子化されたモデルで実際にその層が受け取る入力に対して行われる。これが無視できるコストで明確な改善をもたらすことが分かった」。前段の誤差入りの入力で量子化した方が結果が良い、ということは、誤差が確かに下流へ流れているということです。
だから量子化手法の目的関数は、層の出力誤差の形で書かれます。第 5 章で見る GPTQ・AWQ・AutoRound はいずれも「重みを正確に写す」ではなく「この層を通った後の値を元と揃える」ことを目指しています。llama.cpp 側の対応物が imatrix(importance matrix。実データを流して重要な重みを測ったファイル)で、こちらは第 6 章で扱います。
経験則と限界 — 大きいモデルは強いのか、3bit で何が起きるのか
「大きいモデルほど低ビットに強い」はよく聞く経験則で、支持する一次データもあります。ただし単純な法則ではありません。
| 立場 | 一次情報 | 内容 |
|---|---|---|
| 強い | arXiv:2409.11055(1B〜405B、13 データセット) | 「小さいモデルは 4bit で深刻な精度低下を起こしたが、70B 級のモデルは安定した性能を保った」 |
| 強い | arXiv:2402.18158(125M〜180B) | 「モデルサイズが大きいほど、重み量子化への許容度が高い」。ただし活性化量子化は逆で、大きいほど許容度が下がる |
| 単純ではない | llama.cpp PR #1684 | 「相対的な量子化誤差は、ベースモデルの重み数が増えても減らない。13B は確かに量子化しやすいが、30B と 65B では 7B の水準に戻る」 |
| むしろ逆向き | arXiv:2411.04330 | 「学習後量子化による劣化は、より多くのデータで学習されたモデルほど大きくなる。最終的には追加の事前学習データが有害になる」 |
最後の項目は実測でも裏が取れています。llama.cpp 公式の測定で、同じ q4_K_M の KL ダイバージェンス(出力分布のズレ。第 9 章)は LLaMA 2 7B が 0.012686、Llama 3 8B が 0.031273 で、新しくよく学習されたモデルの方が約 2.5 倍壊れやすい。q2_K では 0.108903 対 0.445132 で差は約 4 倍に開きます。「大きければ大丈夫」ではなく「よく学習されたモデルは削りしろが少ない」と読むべきです。
もう一つの限界が3bit 以下の崖です。GPTQ 論文の WikiText2 perplexity(低いほど良い)を並べます。
| 手法 | ビット | OPT-13B | OPT-175B |
|---|---|---|---|
| 量子化なし | 16 | 10.13 | 8.34 |
| RTN(単純な最近傍への丸め) | 4 | 11.32 | 10.54 |
| GPTQ | 4 | 10.31 | 8.37 |
| RTN(単純な最近傍への丸め) | 3 | 3.4e3 | 7.3e3 |
| GPTQ | 3 | 11.61 | 8.68 |
4bit では単純な丸めでもまだ文章になりますが、3bit では 3,400〜7,300 という数値で、これは「文章にならない」水準です。同じ 3bit を GPTQ で処理すると 8.68 まで戻る。低ビットになるほど「どう丸めるか」が支配的になるということです。llama.cpp 側でも同じ形が見えます。Llama 3 8B の perplexity 増分は q4_K_M が +0.1755、q3_K_M が +0.6569、q3_K_S が +1.6322、q2_K が +3.5199 と、3bit 付近から加速します。そして q3_K_M は imatrix を使うと +0.5026 まで改善します(q4_K_M での改善は +0.1755 → +0.1513)。低ビットほどキャリブレーションの利得が大きい、という関係です。
では何ビットが良いのか。35,000 回以上の実験(19M〜176B、3〜8bit、複数のモデルファミリ)を行った研究の結論は「総ビット数とゼロショット精度の観点では、4bit 精度がほぼ普遍的に最適」でした。そして改善余地は「小さなブロックサイズ」と「データ型の選択(整数か浮動小数点か)」からしか来ない、とも述べています。第 3 章のブロックと、この章の理由 1(分布に合わせた型)が、そのまま名指しされているわけです。
つまずきポイント
「4bit だからファイルサイズはパラメータ数の半分」と計算してしまう
合いません。Q4_K_M の実効は 4.8944 bits/weight(llama.cpp 公式、Llama-3.1-8B 実測)で、8B のファイルは 4.58 GiB です。スケール等のメタデータと、重要テンソルの格上げ分が乗るためです。見積りの正しい式は第 8 章で扱います。
「4bit に量子化した = 4bit で計算している」と思ってしまう
重みだけの量子化では、使うたびに 16bit へ戻して行列積を行います(QLoRA 論文の記述どおり)。4bit なのは保存とメモリ転送だけです。だから「4bit の精度で足し算を繰り返して崩壊する」ことは起きません。逆に W8A8 は計算まで 8bit なので、まったく別の設計です。
「大きいモデルは低ビットに強いから、70B なら 2bit で平気」と読み替えてしまう
llama.cpp の一次データでは、相対的な量子化誤差は 30B・65B で 7B の水準に戻っています。さらに、よく学習された新しいモデルほど劣化が大きい傾向が公式実測にも論文にも出ています(Llama 3 8B は LLaMA 2 7B の約 2.5 倍の KLD)。サイズだけを根拠にビットを削らないこと。
「重要な重みを守れば守るほど良くなる」と思ってしまう
守りすぎると他が壊れます。AWQ の測定(OPT-6.7B)では、重要チャネルを守る倍率 s を 1 → 2 と上げると perplexity は 23.54 → 11.92 まで改善しますが、s = 4 では 12.36 へ悪化します。守った分だけ他のチャネルの誤差が増えるからです。量子化の難しさは消えず、移動するだけ、というのが一貫した構図です(第 5 章)。
理解度チェック
Q1. 16bit を 4bit にすると 1 つの重みで表せる値は 65,536 通りから 16 通りに減ります。それでも品質が保てる理由を、重みの分布の性質から 1 つ挙げてください。
事前学習済みの重みは 0 中心の正規分布に近く(QLoRA 論文)、しかも一部だけ桁違いに大きいということがない(SmoothQuant「平らで一様」)ためです。だからブロックの絶対値最大が異常値に引っ張られず、16 段の目盛りが実際に値が存在する範囲をきちんと覆います。
Q2. Q4_K_M の実効ビット数が 4.0 ではなく 4.8944 bits/weight になる理由を 2 つ挙げてください。
①ブロックごとのスケール等のメタデータが乗るため。②既定では k-quant mixtures によりテンソルごとに違うビット幅を混ぜており、attention.wv と feed_forward.w2 の半分および output.weight が 6bit に格上げされているため。--pure を付けるとこの混合を無効化できます。
Q3. 活性化に 1 つだけ 100 倍大きい値があると、8bit 量子化で何が起きますか。
スケールがその外れ値で決まるため、普通のチャネルが使える実効段階数は 2^8 × (1 ÷ 100) ≈ 2〜3 段になります。256 段のうち大半のビンが空になり、小さな値は 0 に丸められて情報が消えます。なお重みだけの 4bit 量子化では活性化が 16bit のまま流れるので、この問題は起きません。
Q4. なぜ量子化手法は「重みの値をどれだけ正確に再現できたか」を目標にしないのですか。
ある層の誤差が次の層の入力を汚し、層を重ねるほど積み上がるからです(NVIDIA ホワイトペーパー)。そのため GPTQ などは層の出力誤差そのものを最小化し、実装上も「すでに量子化されたブロックを通した入力」で次のブロックを量子化します。
まとめ
- 重みは 0 中心の釣鐘型で、桁違いの外れ値がない。だから少ない目盛りでも置き場所が当たる。分布に合わせて目盛りを配ると同じ 4bit でも品質が上がる(Int4 34.34 対 NF4+DQ 27.41)
- 出力は数千項の和なので、丸め誤差は符号がばらついて打ち消し合う。計算例では最悪ケースの約 64 分の 1(N = 4096)。ただし完全には消えず、実測で
Q4_K_Mは perplexity +0.1755 - 「4bit モデル」は全部 4bit ではない。既定で
attention.wv・feed_forward.w2の半分とoutput.weightが 6bit に格上げされ、実効 4.8944 bits/weight になる - 壊れるのは活性化の外れ値(6.7B 付近で顕在化、0.1% の次元が支配的)と、層をまたぐ誤差の蓄積。前者は重みだけの量子化なら回避され、後者は層の出力誤差を最小化する手法で抑える
- 「大きいほど低ビットに強い」は条件付き。よく学習された新しいモデルほど削りしろが少ない。3bit 以下では単純な丸めが崩壊し、キャリブレーションが必須になる
次章では、その「どう丸めるか」の競争史を追います。RTN・GPTQ・AWQ・NF4・HQQ・SmoothQuant が、この章で見た 3 つの理由と 2 つの崖のどこを攻めているのかを整理します。
参考リンク
- QLoRA: Efficient Finetuning of Quantized LLMs(重みの分布と NF4)
- SmoothQuant(重みは平ら・活性化は外れ値)
- LLM.int8()(外れ値特徴量と混合精度分解)
- AWQ(1% の重要な重みという冗長性の実証)
- GPTQ(層の出力誤差の最小化と 3bit の崖)
- Integer Quantization for Deep Learning Inference(層ごとの感度分析)
- The case for 4-bit precision: k-bit Inference Scaling Laws
- Exploring the Trade-Offs(1B〜405B のモデルサイズ別の劣化)
- Evaluating Quantized Large Language Models(重み量子化と活性化量子化で逆向き)
- Scaling Laws for Precision(よく学習されたモデルほど劣化が大きい)
- llama.cpp
tools/quantize/README.md(実効 bpw とオプション) - llama.cpp
tools/perplexity/README.md(Llama 3 8B の品質スコアボード)