三値 LLM の重みを -1、0、+1 の 3 状態で保存するとき、保存形式の比較結果はモデルごとのゼロ率によって変わります。BITCOS は、ゼロか非ゼロかを表す presence bitmap と、非ゼロ重みの正負を表す sign vector に分ける方式です。ゼロ率を z とすると、三値記号部分の保存量は 2 - z bit/weight になります[1]。
128 重みを 1 グループとして five-trit packing と比較する場合、実効値は 1.625 bit/weight です。この条件では、BITCOS の保存量が小さくなる境界はゼロ率 37.5% です。つまり、対象モデルのゼロ率を測れば、保存量だけについては採用条件を数式で判定できます。
five-trit packing の実効 bit/weight を計算する
三値は 3 状態なので、情報量だけを見れば log2(3) ≈ 1.585 bit/weight です。一方、実際の保存形式ではビット列を有限の単位へ詰める必要があります。
five-trit packing は、5 個の三値を 1 byte に格納します[1]。5 個単位だけを見れば、保存量は次の値です。
8 / 5 = 1.6 bit/weight
ただし、128 重みを 1 グループとして保存すると、必要な byte 数は 25.6 byte ではなく 26 byte です。
ceil(128 / 5) = 26 byte
26 * 8 / 128 = 1.625 bit/weight
この 1.625 bit/weight が、128 重み単位で BITCOS と比較するときの基準になります。1.6 は 5 個単位で端数が生じない場合の値であり、グループ単位で比較するときは端数を含む実効値を使います。
BITCOS の保存量をゼロ率から求める
BITCOS は、各重みについて 1 bit の presence bitmap を持ちます。非ゼロ重みにだけ sign vector の 1 bit が必要です[1]。
ゼロ率を z とすると、非ゼロ率は 1 - z なので、三値記号部分の保存量は次の式になります。
1 + (1 - z) = 2 - z bit/weight
たとえば、ゼロ率 40% のモデルでは次の値です。
2 - 0.40 = 1.60 bit/weight
ゼロ率が高いほど sign vector に必要な bit 数が減るため、BITCOS の保存量も小さくなります。BITCOS の論文では 29 個の三値 LLM を調べ、ゼロ率が最大 51.5% に達し、最も疎なモデルで 1.485 bit/weight になったと報告しています[1]。
37.5% を損益分岐点として判定する
128 重み単位の five-trit packing は 1.625 bit/weight です。BITCOS がこれより小さくなる条件は、次の不等式で求められます。
2 - z < 1.625
z > 0.375
したがって、ゼロ率 37.5% が保存量の損益分岐点です。
| ゼロ率 | BITCOS | five-trit packing | 保存量の比較 |
|---|---|---|---|
| 30.0% | 1.700 bit/weight | 1.625 bit/weight | five-trit packing が小さい |
| 37.5% | 1.625 bit/weight | 1.625 bit/weight | 同じ |
| 40.0% | 1.600 bit/weight | 1.625 bit/weight | BITCOS が小さい |
| 51.5% | 1.485 bit/weight | 1.625 bit/weight | BITCOS が小さい |
論文では、調査した 29 モデルのうち 26 モデルで BITCOS が five-trit packing より小さい保存量になっています[1]。この結果は、三値という状態数だけで保存形式を決めるより、実際の記号分布を測って判断する余地があることを示しています。
Python でゼロ率から保存量を判定する
Python 3.9 以降の標準ライブラリだけで、ゼロ率とグループサイズから両方式の保存量を比較できます。
import math
def compare_storage(zero_rate: float, group_size: int = 128) -> tuple[float, float, str]:
if not 0.0 <= zero_rate <= 1.0:
raise ValueError("zero_rate must be between 0.0 and 1.0")
if group_size <= 0:
raise ValueError("group_size must be positive")
bitcos_bpw = 2.0 - zero_rate
five_trit_bytes = math.ceil(group_size / 5)
five_trit_bpw = five_trit_bytes * 8 / group_size
if bitcos_bpw < five_trit_bpw:
result = "BITCOS"
elif bitcos_bpw > five_trit_bpw:
result = "five-trit packing"
else:
result = "same"
return bitcos_bpw, five_trit_bpw, result
for zero_rate in (0.30, 0.375, 0.40, 0.515):
bitcos, five_trit, result = compare_storage(zero_rate)
print(
f"z={zero_rate:.3f} "
f"BITCOS={bitcos:.3f} "
f"five-trit={five_trit:.3f} "
f"smaller={result}"
)
実行結果は次のようになります。
z=0.300 BITCOS=1.700 five-trit=1.625 smaller=five-trit packing
z=0.375 BITCOS=1.625 five-trit=1.625 smaller=same
z=0.400 BITCOS=1.600 five-trit=1.625 smaller=BITCOS
z=0.515 BITCOS=1.485 five-trit=1.625 smaller=BITCOS
グループサイズを変更すると、five-trit packing 側の端数処理によって実効 bit/weight も変わります。そのため、37.5% という境界は 128 重み単位で 1.625 bit/weight と比較する場合の値です。別のグループサイズでは、同じコードで比較値と境界を再計算できます。
bit/weight の比較範囲をそろえる
2 - z が表しているのは、presence bitmap と sign vector からなる三値記号部分です。実際のモデル形式では、量子化尺度、ブロック情報、そのほかのテンソルやメタデータが加わります。
このため、保存形式を比較するときは、両方の数値がどこまでを含むかをそろえます。三値記号部分の bit/weight と、尺度やメタデータまで含むモデル全体の平均 bit 幅を直接比較すると、異なる範囲を比較することになります。原典でも、記号部分、尺度込みの重み、モデル全体を分けて扱っています[2]。
実務では、少なくとも次の単位を分離すると判断しやすくなります。
| 比較単位 | 含めるもの |
|---|---|
| 三値記号部分 |
-1、0、+1 を復元するためのデータ |
| 重み表現 | 三値記号部分と量子化尺度など |
| モデル全体 | 重み表現に加えて、そのほかのテンソルやメタデータ |
BITCOS の 2 - z と five-trit packing の 1.625 bit/weight を比較する場合は、どちらも三値記号部分として比較できます。
保存量と推論速度を別の評価値として測る
保存量が小さくなると、重み読み出し時のメモリー転送量を減らせる可能性があります。一方、BITCOS では presence bitmap を解釈し、sign vector から元の三値列を復元する処理が実行経路へ加わります。
BITCOS の論文では、実際の三値モデルで観測されたゼロ率を用いた評価において、行列ベクトル積カーネルで最大 1.28 倍、エンドツーエンドの decode throughput で CPU 最大 1.18 倍、GPU 最大 1.27 倍の改善を報告しています[1]。これらは論文で評価した実装とハードウェア条件での測定結果です。
保存形式を選ぶときは、まずゼロ率から bit/weight を計算し、次に対象ハードウェア上で復号を含む推論性能を測ります。128 重み単位の five-trit packing と比較するなら、保存量については z > 0.375 が明確な採用条件になります。その後の性能評価では、同じモデル、同じ推論条件、同じハードウェアで decode throughput を測ることで、保存量削減が実行時間へ反映される範囲を確認できます。
参考文献
- Evangelos Georganas, Alexander Heinecke, Pradeep Dubey, Breaking the 1.58-bit Barrier for Ternary LLMs(2026-09-14). https://arxiv.org/abs/2609.16338
- id774, 三値 LLM の圧縮は保存量と復号処理の配置問題になる(2026-09-25). https://blog.id774.net/entry/2026/09/25/5710/