量子化¶
quantize は、モデルの線形層を三値に変換し、fake-quantのsnapshotを書き出します。量子化した重みがscale
ごとに3値しか取らない、ふつうのHugging Faceのモデルフォルダです。読み込み・ベンチマーク・評価・書き出しができます。重みに何が起きるかは三値量子化で説明しています。
基本のコマンド¶
openternary quantize google/gemma-4-E2B-it-qat-q4_0-unquantized \
--scale-granularity per_group --group-size 128 \
--output runs/e2b-g128
結果は runs/e2b-g128/artifacts/snapshot にあり、その横にrunの記録(config.yaml・quantization.json など)があります。
必ず先に確認しましょう。--dry-run はすべてを解決・検査し、何も作りません:
openternary quantize google/gemma-4-E2B-it-qat-q4_0-unquantized --scale-granularity per_group --group-size 128 --dry-run
scaleの選び方¶
| オプション | 既定 | 効果 |
|---|---|---|
--scale-granularity per_tensor |
✔ | テンソルごとに1つのscale。追加コストは最小、忠実さは最低 |
--scale-granularity per_group |
各行の --group-size 個ごとに1つのscale |
|
--group-size N |
128 | 1グループの値の数(per_group のとき)。小さいほど忠実だが、保存するscaleが増える |
--grouping-scheme last-dim-rowwise-v1 |
✔ | 唯一のグループの作り方。グループ化を参照 |
OpenTernaryの研究で使っている構成はグループ単位のG128です。FP32のscaleのために、重み1つあたり0.25bitが追加でかかります。
設定ファイルを使う¶
フラグで渡せるものはすべてYAMLにも書けます。フラグのないオプションも書けます:
model:
id: google/gemma-4-E2B-it-qat-q4_0-unquantized
revision: 6befbaca7398925921802abd1f277b495b78b738
quantization:
backend: ternary
scheme: absmean
scale_granularity: per_group
group_size: 128
target:
attention: true
mlp: true
mixed_precision: # これらのテンソルは元の精度のまま
model.language_model.layers.0.self_attn.q_proj.weight: preserve
passes: # 量子化の前に順に適用
- name: clip
options: {max_abs: 2.0}
device: cpu
フラグはファイルより優先され、ファイルは既定値より優先されます。解決した結果は、runの config.yaml として保存されます。コマンドラインで渡したモデルは model.id を置き換え、新しいモデルIDが別のモデルの固定revisionを引き継ぐことはありません。各キーの説明は設定のリファレンスにあります。
テンソル名の調べ方
mixed_precision のキーは正確なテンソル名でなければなりません。inspection.json から調べてください(調査と計画)。どれにも当てはまらない名前はエラーになります。
デバイスとdtype¶
snapshotの変換は、常にCPUでテンソルを1つずつ行います:
--device cpuかauto(既定)を受け付けます。--device cudaは、黙ってCPUを使うのではなく、終了コード3で拒否します。- snapshotは元のモデルの浮動小数点のdtypeを保ちます(BF16のモデルならBF16のsnapshot)。そのため
quantizeの--dtypeは終了コード2で拒否します。モデルを動かすときのdtypeは、ベンチマークや評価のときに選びます。
メモリの使用量には上限があり、おおよそ最大のテンソル1つと出力のshard 1つ(最大512MiB)分で、モデル全体の大きさではありません。ディスクは、snapshotのために元のモデルとほぼ同じ容量を使います。
TorchAO backend¶
確立された8bitの方式と比べるために、torchao==0.18.0 を入れた環境で:
openternary quantize ./my-model --backend torchao --scheme int8-weight-only --weight-dtype int8 --output runs/my-int8
TorchAOの成果物は、同じバージョンのTorchAOでしか読み込み直せず、safetensorsへの書き出しもできません。
runに記録されるもの¶
quantization.json には、たとえば次のものがあります:
- 実行した設定と、テンソルを分類したアダプタ
- テンソルごとの詳細: 形、dtype、scaleの統計、グループの数、scaleのfingerprint(scaleの配列そのものはJSONに保存しない)
- snapshotのcontentのfingerprint(テンソル名・形・dtype・バイト列のハッシュ)
- ビットの集計: 理想・packed・scaleの追加分を分けて記録(ビットを正直に数える)
snapshot自体には、全ファイルのSHA-256を記した openternary-manifest.json が含まれるので、いつでも
openternary artifacts validate で確認できます。
量子化のあとで¶
古いバージョンからの移行¶
| 以前 | 現在 |
|---|---|
quantize --method naive |
--backend ternary --scheme absmean(YAMLの method: naive は引き続き使える) |
quantize --dtype bf16 |
拒否。snapshotは元のdtypeを保つ |