メインコンテンツまでスキップ

三値量子化の実践: Bonsai 2 27B を 5.95 GB に収める

上級

2026 年 9 月 17 日、PrismML は Ternary Bonsai 2 27B を公開しました。270 億パラメータの モデルでありながら、重みは -1、0、+1 のみで、5.95 GB のファイルにパックされ、 Apache 2.0 でリリースされています。Hugging Face の GGUF リポジトリは 5 日で 250 万ダウンロードを突破しました。 どこでも見出しは同じでした — ノートパソコンに収まる 27B モデル。

その見出し自体は本当です。そこから導かれると人々が思い込んでいることの、ほとんどすべては違います。

素の llama.cpp はファイルを読み込み、エラーを出さずに流暢なナンセンスを生成します。 Ollama と LM Studio はそもそも受け付けません。5.95 GB のファイルはデフォルト設定でおよそ 12 GB の VRAM を必要とします。より大きい 7.21 GB ビルドはデータセンター GPU では速く、4090 では遅くなります。 そして広く引用される「フル精度の 98.2%」は 14 個のベンチマークの平均であり、マルチモーダル推論での 6 ポイントの崩壊と、ある独立テストでは低リソース言語での完全な失敗を覆い隠しています。

このページはその実践レイヤーです。三値量子化が実際に何をもたらすのか、出力を静かに壊さずに このモデルを動かす方法、そして圧縮の保持率という数字を誠実に読む方法。技術はモデルより長生きします — 同じ論理は、この後に続くあらゆる低ビットリリースに当てはまります。

What you'll learn
  • 三値の重みが、理論の約束する 1.58 ビットではなく実際には 1.75 ビットになる理由を理解する
  • 静かにゴミを吐く失敗モードを見抜く: 素のローダーは Hadamard 回転を無視し、エラーも出さない
  • PTQ1_0 と PQ2_0 を、ファイルサイズではなく帯域幅 vs アンパックのクロスオーバーで選ぶ
  • 実メモリを見積もる: 5.95 GB の重み、トークンあたり約 64 KiB のキャッシュ、そしてデフォルト設定が 12 GB を超えてしまう理由
  • 「98.2% の保持率」を正しく読む — どの能力が圧縮を生き延び、どれが静かに失われるのか

三値量子化とは実際に何なのか​

通常のモデルは各重みを 16 ビット浮動小数点として保存します。三値モデルは各重みを 3 つの値 — -1、0、+1 — のいずれかとして保存し、重みのグループごとに共有される FP16 スケールを 1 つ持ちます。 復元は w = scale_g * t で、t がトリット(trit)です。

3 状態には log₂(3) ≈ 1.58 ビットが必要です。これが研究文献の使う数字であり、 Microsoft の BitNet b1.58 以降ずっとそうです。しかしディスク上で得られる数字ではありません。

Bonsai 2 27B は最も密なビルドで重みあたり 1.75 ビットとして出荷されます。余分な 0.17 ビットは 誰も説明しない部分です:

  • グループスケール。 128 個の重みごとに 1 つの FP16 スケールは、128 重みにならした 16 ビット — 他を何も数えなくても重みあたり 0.125 ビットです。
  • パッキングの無駄。 トリットはバイトにきれいに割り切れません。密なパッキングは理論上の密度の 大部分を回収しますが、すべてではありません。
  • 量子化されない要素。 埋め込み、出力射影、正規化層は高い精度のまま残ります。27B モデルでは これらはパラメータ数としては小さな割合ですが、バイト数としては無視できない割合になります。

したがって実際の比率は 16/1.58 ≈ 10 倍ではありません。53.8 GB → 5.95 GB、およそ 9 倍です — これはモデルカードが報告している通りの数字です。

三値が速い理由、そしてそれは演算のおかげではない

多くの人が持つ直感は、三値の乗算が安いというものです。-1、0、+1 を掛けるのは符号反転、 スキップ、あるいは何もしないことです。確かにその通りですが、実ハードウェア上での勝ち筋はそこにはありません。

トークン生成はメモリ帯域幅バウンドであり、計算バウンドではありません。生成されるトークンごとに 重み行列全体をメモリからストリームする必要があります。バイト数を 9 分の 1 にすれば、支配的なコストが 9 分の 1 になります。演算はそもそもボトルネックではなかったのです。

これは実務上重要です。ネイティブな三値サポートを持たない CPU や GPU は、既存の積和演算ユニットを 使うために通常のフォーマットへデクオンタイズし直さなければならず、演算上の節約は失われる一方で 帯域幅の節約は残ります。だからこそ、選ぶパッキング形式が性能を一見逆向きに変えるのです — 後述します。

罠: 素の llama.cpp は読み込んで嘘をつく​

これはこのページで最も重要な一点であり、リリース報道のほとんどには登場しません。

Bonsai 2 の重みにはブロック単位の Hadamard 回転がストレージに畳み込まれています。対応する逆変換を 実行時に活性化側へ適用しなければなりません。この回転は低ビット量子化の標準的な小技で — ブロック内で 外れ値の大きさを分散させ、三値グリッドが失うものを減らします — しかしそれは、この仕組みを知らない ローダーにとって保存された重みがそのままでは使えないことを意味します。

素の llama.cpp ビルドはこの仕組みを知りません。バージョンによっては、テンソル型を拒否するか、 より悪いことにファイルの読み込みに成功し、流暢で自信に満ちた、まったく誤った出力を生成します。 エラーも、警告も、品質低下フラグもありません。モデルカードははっきり述べています。素の llama.cpp は これらのファイルを実行できず、標準ビルドは Hadamard の活性化変換が欠けているためゴミを生成する、と。

下流のツールはこの問題をそれぞれ違う形で引き継ぎます:

ランタイムBonsai 2 27B GGUF での挙動
PrismML の llama.cpp フォーク(ブランチ prism)動作する — 現時点で唯一のローカル GGUF 経路
素の llama.cppテンソル型を拒否する、または読み込んでナンセンスを出力する
Ollamaインポートが tensor size overflow エラーで失敗する
LM Studioggml テンソル型 142 と 143 を拒否する
MLX (Apple)別途 mlx-2bit ビルドが必要。フットプリントはより大きい

Ollama と LM Studio の失敗は安全な結果です。危険なのは素の llama.cpp が静かに成功することです。 ベンチマークスクリプトや評価ハーネスが、そのナンセンスを平然と結果として記録してしまうからです。

低ビットモデルを評価するなら、まずローダーを検証する

何よりも先に、答えの分かっているプロンプトを 1 つ流してください。HumanEval で 95 点以上を取るモデルが 「2+2 は何か」に一貫した答えを返せないなら、それはモデルの問題ではなくローダーの問題です。これは この形式に限らず、あらゆる特殊な量子化形式に当てはまります。

動かす​

Guided walkthrough1 of 6
  1. git clone https://github.com/PrismML-Eng/llama.cpp && cd llama.cpp を実行し、NVIDIA なら cmake -B build -DGGML_CUDA=ON && cmake --build build -j。Apple Silicon では CUDA フラグを外してください — Metal はデフォルトで有効です。AMD では -DGGML_HIP=ON を使います。デフォルトブランチは prism で、README は prism-v6 からビルドすること、およびこのフォークのライブラリを同じマシンの素の llama.cpp インストールと混在させることを明確に警告しています。

最小限のエンドツーエンド: ビルド、取得、サーブ、検証

# 1. Fork only — stock llama.cpp will silently produce garbage
git clone https://github.com/PrismML-Eng/llama.cpp && cd llama.cpp
cmake -B build -DGGML_CUDA=ON && cmake --build build -j

# 2. Fetch (PQ2_0 = 7.21 GB, faster on big GPUs; PTQ1_0 = 5.95 GB, fits 8 GB cards)
hf download prism-ml/Ternary-Bonsai-2-27B-gguf \
Ternary-Bonsai-2-27B-PQ2_0.gguf --local-dir .

# 3. Serve — always set -c explicitly, never leave it at 0
./build/bin/llama-server -m Ternary-Bonsai-2-27B-PQ2_0.gguf \
--alias bonsai-2-27b -ngl 99 -fa on -c 32768 \
--host 127.0.0.1 --port 8080

# 4. Verify the loader BEFORE trusting any output
curl -s http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"bonsai-2-27b","messages":[{"role":"user","content":"What is 2+2? Answer with one number."}]}'
# Coherent "4" => loader is correct. Fluent nonsense => wrong build, stop here.

PTQ1_0 対 PQ2_0: 逆さまに見えるクロスオーバー​

同じ重みの 2 つのビルド。PTQ1_0 はトリットを 1.75 ビットで密にパックします。PQ2_0 は各トリットに 独自の 2 ビットスロットを与え 2.13 ビットになります — ディスクは 21% 増えますが、スロットが バイト境界に揃うためアンパックがはるかに安くなります。

実測した生成スループット(トークン/秒):

GPUPQ2_0 (7.21 GB)PTQ1_0 (5.95 GB)勝者
RTX 5090129.9120.5PQ2_0
RTX 409081.291.1PTQ1_0
L4 (24 GB)29.832.1PTQ1_0
M5 Pro (Metal)28.1——

パターンは一般化できます: PTQ1_0 は Ada 世代とローエンド GPU で勝ち、PQ2_0 は H100、A100、 Blackwell で勝ちます。

これは「小さいほど速い」という量子化の一般的な経験則とは正反対です。理由は先ほどの帯域幅対アンパックの トレードオフです。帯域幅に飢えたカードでは、21% 少ないバイトを動かすことが支配的になり、密なパッキングが 勝ちます。巨大なメモリ帯域幅を持つカードでは、帯域幅が制約でなくなり、代わりに密なアンパックの ビットシャッフルコストがボトルネックになります — だから太くてバイト整列したフォーマットのほうが速く走るのです。

プロンプト処理はこの話をもっと大きな声で語ります: RTX 5090 では PQ2_0 が 3,893 tok/s でプロンプトを 処理するのに対し、PTQ1_0 は 1,805 — 倍以上です。プリフィルは計算バウンドで、アンパックコストが 最も強く効くからです。

経験則: VRAM が 12 GB 未満なら選択肢はなく、PTQ1_0 を取ります。それ以上なら PQ2_0 — ただし 4090 か L4 では PTQ1_0 が計測上明確に勝ちます。

ファイルサイズはメモリ要件ではない​

このモデルについては 3 つの異なる「サイズ」の数字が出回っています — 5.9 GB、7.2 GB、8.6 GB — そして 3 つとも正当です。測っているものが違うからです。実際の見積もりは次の通り:

  • 重み: 5.95 GB(PTQ1_0)または 7.21 GB(PQ2_0)。
  • ビジョンプロジェクター: 画像が必要なら +629 MB(Q8_0)または +931 MB(BF16)。
  • アテンションキャッシュ: おおよそトークンあたり 64 KiB。8K コンテキストで約 0.5 GB、 32K で約 2 GB、フルの 262K ウィンドウで約 16 GB。
  • 並列スロット: llama.cpp はキャッシュをスロットごとに確保します。デフォルトでは複数が確保されます。

ある独立テストは、デフォルト設定で 12 GB をわずかに超える VRAM を計測し、サーバーを単一の並列スロットに 制限すると約 8 GB まで下がったと報告しています。彼らが計測したディスクフットプリント — 約 7 GB — は PQ2_0 ビルドに対応しており、数字の混乱の一部はここから来ています。

カード別の実用的なコンテキスト余裕(特記なき場合は PQ2_0 使用):

VRAMビルド使えるコンテキスト
8 GBPTQ1_0約 16K トークン(ビジョン込みで約 6K)
12 GBPQ2_0約 56K トークン
16 GBPQ2_0約 118K トークン
24 GBPQ2_0約 240K トークン
32 GB 以上PQ2_0フルの 262K ウィンドウ

「ノートパソコンで動く」という主張はこれらすべてを生き延びます — ただし「8 GB の GPU と 16K の コンテキストを持つノートパソコンで動く」が誠実な言い方であり、それは実質的に別の製品です。

「98.2% の保持率」が隠しているもの​

PrismML は 14 個のベンチマークにわたり、フル精度のベースモデルの 86.32 に対して 84.78 という 集計値を報告しています — これが 98.2% という数字です。平均は圧縮のダメージが隠れる場所です。 ベンチマーク別の広がりは次の通り:

ベンチマークBonsai 2 27BFP16 ベース差分
AIME2695.8394.58+1.25
MATH-50098.8099.80−1.00
LiveCodeBench90.0790.05+0.02
HumanEval+95.1293.29+1.83
MMLU-Redux89.0991.46−2.37
MMMU-Pro75.4981.73−6.24

この表から読み取るべきことが 3 つあります。

第一に、ダメージは均一ではなく — 構造的です。 数学とコードは本質的に無傷です。知識の想起は落ちます (知識と推論の複合スコアはフル精度の 85.6 に対して 79.9 付近に着地します)。本当の打撃を受けるのは マルチモーダル推論です: MMMU-Pro は 6.24 ポイント落ち、OCR Bench v2 は 60.99 から 56.88 に下がります。 圧縮が奪うのは蓄えられた事実の幅であって手続き的スキルではありません — ロングテールの連想を 保存するための精度を潰せば、まさにそうなるはずです。

第二に、プラスの数字を疑うこと。 圧縮モデルが HumanEval+ で自分のフル精度ベースを 1.83 ポイント、 AIME26 で 1.25 ポイント「上回る」のは、圧縮が役に立つ証拠ではありません。これらのベンチマークに 数ポイントの実行間ばらつきがある証拠です。だとすれば、小さなマイナスの数字も割り引くべきです。

第三に、ベンダー自身の数字が完全には一致していません。 モデルカードのベンチマーク表は 84.78 に 集計されますが、PrismML のローンチ投稿は 83.9 という集計値を報告しています。どちらも同じ 98.2% の 保持率として説明されています。差は小さく、説明もありません。片方を選ぶのではなく、そのまま報告します。

ベンチマークが捉えられなかった失敗モード

ある独立した実地テストは、どのベンチマーク行も予測しない挙動を見つけました。タミル語を含む低リソース言語への 翻訳を求めたところ、モデルは反復ループに入り、タスクを完了できませんでした — 前世代の Bonsai より 悪い結果です。同じテストでは、実在するタイムゾーンのバグを特定したあと、自分で正しい結論から自分を 言いくるめてしまい、小さな HTML タスクで動くリセットボタンを 3 回の修正ラウンドでも作れませんでした。

これは積極的な量子化に特徴的なシグネチャです。集計スコアは維持される一方、ロングテール — 稀な言語、 長い地平での自己修正 — は実際に使ってみて初めて現れる形で劣化します。コミュニティの報告では、 広告されている 262K ウィンドウのうち、およそ 200K トークンを超えると想起と一貫性が劣化するとも 述べられています。

メインラインの話と、それが次のリリースにとって重要な理由​

三値 Bonsai を上流の llama.cpp に取り込もうという並行した動きがあり、その現状は低ビット形式が どのように分断するかを示す有益な教訓になっています。

PrismML は小型の Bonsai モデル向けにグループ 128 の三値パッキングを提案しました。llama.cpp の メンテナはグループサイズ 64 を支持して押し戻しました。追加メモリは 6% 未満で済むうえ、より多くの テンソル形状に対応でき、品質も良いという理由です。グループ 64 の Q2_0 が公式フォーマットとなり、 CUDA と Vulkan を含む複数のバックエンドにマージされました。PrismML はグループ 128 の派生をフォークに残しました。

そのため「llama.cpp は三値モデルをサポートしているか」には、正しくかつ正反対な 2 つの答えがあります:

  • はい — Q2_0_g64 ビルドはメインラインで各バックエンドにわたり動作し、フォーク自身の README も それらを可搬な経路として指し示しています。
  • いいえ、このモデルについては — 検証時点で、公開されている Ternary-Bonsai-2-27B-gguf リポジトリに含まれるのは F16、PQ2_0、PTQ1_0 と 2 つの mmproj ファイルです。27B の Q2_0_g64 ビルドは存在しません。フォークが唯一の経路です。

古い三値形式 TQ1_0 と TQ2_0 は既に ggml に存在しますが、グループサイズ 256 を使っており、 これらのモデルのネイティブなパック方式とは非互換です。TQ2_0 は ggml における最も詰まった忠実な 三値レイアウトでもあり、重みあたり約 2.06 ビットです — そして現在のメインラインでは CPU 専用の ドット積として実装されており、CUDA、Metal、Vulkan の経路はありません。変更履歴に「三値サポート」と 書いてあっても、あなたの GPU がそれを使うかどうかについてはほとんど何も分かりません。

次に評価する低ビットモデルについて問うべきは量子化されているかではなく、どのグループサイズか、 どのパッキングか、どのバックエンドにカーネルがあるか、可搬なビルドはあるかです — それが、あなたが メインラインで動かすのか、他人のフォークを保守することになるのかを決めるからです。

これが正しい道具になるとき​

価値があるのは:

  • 高い精度では 27B を載せられないハードウェア上で、有能な数学またはコーディングモデルが必要なとき。 そこは保持率がほぼ完璧で、価値が最も高い領域です。
  • 帯域幅に制約があるとき — ノート PC の GPU、エッジ機器、共有の L4 — で、トークンあたり 9 分の 1 の バイト数が使えるか使えないかの差になるとき。
  • エネルギーが問題になるとき。PrismML は RTX 4090 でトークンあたり 0.714 mWh を報告しており、 これはフル精度の 8B モデルより 40% 効率が良いとしています。
  • Apache 2.0 ライセンスと完全にローカルな実行が、好みではなく要件であるとき。

価値がないのは:

  • 作業が知識中心またはマルチモーダルであるとき。そこがまさに圧縮の請求書が届く場所です。
  • 英語以外のロングテール言語のカバレッジが必要なとき。ここでの独立した証拠は芳しくなく、 ベンチマークはそれを予測できませんでした。
  • フォークされた推論ランタイムを保守できないとき。Ollama と LM Studio は現時点で読み込めず、 素のビルドは声高にではなく静かに失敗します。
  • 262K という仕様を頼りに、コンテキスト約 200K トークンを超えて走らせるつもりだったとき。
Enter キーまたはスペースキーでカードを裏返します。左右の矢印キーでカードを移動できます。用語を表示しました。
1 / 10

理解度チェック​

Check yourself

0/5
  1. Ternary-Bonsai-2-27B-PTQ1_0.gguf をダウンロードし、最近の素の llama.cpp ビルドで動かしたところ、流暢だが微妙に誤ったテキストが生成されました。最も可能性の高い原因は?
  2. 24 GB の RTX 4090 を持っています。どちらの GGUF ビルドが高い生成スループットを出しますか?
  3. カードの VRAM は 8 GB。重みファイルは 5.95 GB。デフォルト設定で llama-server を起動するとメモリ不足になります。なぜ?
  4. 同僚が「フル精度性能の 98.2%」を引き合いに、圧縮モデルは文書理解パイプラインの差し替えとして使えると主張しています。最も強い反論は?
  5. 変更履歴に llama.cpp が「三値量子化をサポート」と書かれています。自分の GPU がそれを使うと仮定する前に、まだ確認すべきことは?

出典と参考文献​

次へ​