3行でいうと

  • 作業は二段階です。まず convert_hf_to_gguf.py で高精度のGGUFにし、次に llama-quantize で圧縮します。
  • 公式の表では、Llama-3.1-8BのQ4_K_Mは4.58GiB、F16は14.96GiBです。
  • imatrixは、サンプル文章を流して作る「どの重みが効くか」の記録で、圧縮時に品質の低下を抑えるために使います。
  • 量子化の作業中は、モデル全体をメモリに読み込みます。公式は、メモリとディスクの必要量が同じだと書いています。

この記事は、実際に使って確かめた記録ではありません。この記事は公式の文書や論文を読んでまとめたものです。数字の比較や割り算は、公式の表から僕らが計算したものです。

先に結論

自分で量子化する価値があるのは、配布元が欲しい圧縮の種類を用意していないとき、imatrixを自分のデータで作りたいとき、あるいは仕組みを理解したいときです。単に4ビット版を使いたいだけなら、すでに誰かが作ったGGUFを使うほうが手間は少ないはずです(見立てです)。

手順は短いです。公式READMEの流れは次の三つです。

  1. Hugging Faceのモデルを、BF16かF16のGGUFにする(変換)。
  2. llama-quantize で、Q4_K_Mなどの形式に圧縮する。
  3. 画像などを扱うモデルなら、mmproj(画像用の部品)も別に作る。

前提:用語

手順1:Hugging Faceのモデルを、高精度のGGUFにする

公式READMEの例です。この記事では、実行していません。

python convert_hf_to_gguf.py --outfile gemma-4-E2B-it-bf16.gguf --outtype bf16 --remote google/gemma-4-E2B-it

事前に、リポジトリの requirements.txt で、Pythonの部品を入れます。READMEの補足は次のとおりです。

スクリプトのソースで確認した --outtype の選択肢は、f32・f16・bf16・q8_0・tq1_0・tq2_0・auto です。auto は「16ビット浮動小数点で最も忠実な型」と説明されています。--remote は実験的な機能で、safetensorsファイルをダウンロードせずに読む、とあります。ログイン制限のあるリポジトリには、環境変数 HF_TOKEN が要ります。

手順2:llama-quantizeで圧縮する

公式READMEの例です。この記事では、実行していません。

./build/bin/llama-quantize gemma-4-E2B-it-bf16.gguf gemma-4-E2B-it-Q4_K_M.gguf Q4_K_M

引数は「入力のGGUF、出力のGGUF、量子化の種類、(任意で)スレッド数」です。

主なオプションです(READMEとソースの --help の記述)。

オプション 働き
--imatrix ファイル 重要度行列を使って、圧縮を最適化する
--include-weights / --exclude-weights imatrixを使うテンソルを指定する。両方は同時に使えない
--allow-requantize すでに量子化された重みを再量子化する。公式は、品質が大きく落ちうると警告
--leave-output-tensor 出力の重みを圧縮しない。サイズは増えるが、品質が上がることがある
--pure k-quantの混合をやめ、全部を同じ型にする
--output-tensor-type、--token-embedding-type 出力の重み、単語の埋め込みに別の型を使う
--tensor-type 名前=型 特定のテンソルだけ型を変える(正規表現可、上級者向け)
--dry-run 圧縮せず、できあがるサイズだけを計算して表示する(ソースの説明)
--max-buffer-size MiB 1つのテンソルを圧縮する間にメモリに置く行数の上限。メモリが少ない機械では小さくする(ソースの説明)

見立てです。最初は、種類だけを指定した最小の形(上の例)で作り、--dry-run でサイズを先に見る、という順番が安全だと思います。

imatrix(重要度行列)を作る

imatrixは、サンプル文章(キャリブレーションデータ)をモデルに読ませて、各層の入力の大きさを記録したものです。圧縮のときに「効く重みを丁寧に、効かない重みは粗く」扱うために使われます。元のプルリクエスト(#4861)の説明は、各テンソルの列ごとの活性化の二乗の平均を重みとして、重み付きの誤差を最小にする、という考え方です。この説明は、WebFetchの要約で読んだもので、原文の確認は十分ではありません。

公式の tools/imatrix のREADMEの例です。この記事では、実行していません。

# 重要度行列を作る(99層をGPUに載せる)
./llama-imatrix -m ggml-model-f16.gguf -f calibration-data.txt -ngl 99

# それを使って Q4_K_M に圧縮する
./llama-quantize --imatrix imatrix.gguf ggml-model-f16.gguf ./ggml-model-q4_k_m.gguf q4_k_m

READMEから読み取れる点です。

サンプル文章に何を使うかの具体的な推奨は、今回読んだ範囲のREADMEにはありませんでした。READMEの例は wiki.train.raw です。

見立てです。imatrixは、サンプル文章に近い使い方で効果が出る仕組みなので、日本語で使うなら、日本語を含む文章で作ったほうがよいのではないかと思います。ただし、公式がそう書いているわけではなく、確かめてもいません。

数字を読む:種類によるサイズと速さ

公式READMEの表(Llama-3.1-8B)と、ソース内のppl差

READMEの表から抜粋

公式の tools/quantize/README.md には、Llama-3.1-8Bの各形式について、bits/weight、サイズ(GiB)、速度(トークン/秒)の表があります。条件は、プロンプトの処理が512トークン、文章の生成が128トークンです。この表を測ったハードウェアは、読んだ範囲に書かれていませんでした。

形式 bits/weight サイズ(GiB) 生成 t/s @128 読み込み t/s @512
IQ2_M 2.9294 2.74 74.44 787.68
Q3_K_M 3.9960 3.74 71.68 783.44
Q4_K_S 4.6672 4.36 76.71 818.55
Q4_K_M 4.8944 4.58 71.93 821.81
Q5_K_M 5.7036 5.33 67.23 758.69
Q6_K 6.5633 6.14 58.67 812.01
Q8_0 8.5008 7.95 50.93 865.09
F16 16.0005 14.96 29.17 923.49

ソース内のppl差

quantize.cpp の種類の一覧には、各形式の説明として、Llama-3-8Bでのperplexityの増加が書かれています。

形式 サイズ ppl増加
Q2_K 2.96G +3.5199
Q3_K_M 3.74G +0.6569
Q4_K_M 4.58G +0.1754
Q5_K_M 5.33G +0.0569
Q6_K 6.14G +0.0217
Q8_0 7.96G +0.0026

上の表はLlama-3.1-8B、こちらはLlama-3-8Bの数字です。モデルが違うので、サイズが近くても別の測定です。

僕らの計算

  • Q4_K_MのサイズはF16の約31%です(4.58÷14.96)。
  • 生成の速さは、F16の29.17に対してQ4_K_Mが71.93で、約2.5倍です。一方、読み込みの速さはF16が923.49、Q4_K_Mが821.81で、F16のほうが速い表です。

見立てです。この表を見ると、「生成」の速さはファイルが小さいほど上がり、「読み込み」の速さはあまり変わらないように見えます。生成では、1トークンごとに重みを読み直すためメモリの読み出し量が効く、という一般的な説明と合いますが、公式のREADMEがその理由を述べているわけではありません。

作業に必要なメモリとディスク

公式READMEの「Memory/Disk Requirements」節は、次のように書いています。

例(Llama 3.1)は、8Bが元の32.1GBから4.9GB、70Bが280.9GBから43.1GB、405Bが1,625.1GBから249.1GB(Q4_K_M)です。元のサイズは、32ビットで保存した場合に見えます(8B×4バイト)。

見立てです。32GBのMacでは、8Bの変換と量子化は余裕がありそうですが、70Bのような大きいモデルは、変換の入力が数百GBになるので、ディスクの空きを先に確かめる必要があります。

画像・音声に対応するモデル

公式READMEによると、llama.cppは既定でモデルのLLM部分だけを変換します。画像や音声を使うには、別のファイル(mmproj)を作ります。

python convert_hf_to_gguf.py --mmproj --outfile mmproj-gemma-4-E2B-it-Q8_0.gguf --outtype q8_0 --remote google/gemma-4-E2B-it

公式の説明では、これらの部品は本体より小さく、品質が出力に直接影響するので、BF16かQ8程度の高い品質で残すのが普通です。速度とメモリへの影響は、小さい形式にしても無視できる程度、とあります。

よくある失敗・つまずき

気をつけること

出典

更新履歴