llama.cpp:複雑化する量子化バリエーションの整理(2024.02現在)

https://github.com/ggerganov/llama.cpp/pull/5747
  • llama.cpp では最近、ikawrakow氏による量子化手法のアップデートが熱心に行われています。
  • 新しい量子化の実装が重なり個人的に分かりづらくなってきたので、簡単に整理しておこうと思います。
  • quantize.cppのオプションを参照すると、現在(2024.02)のGGUFバリエーションは以下のとおりです。

github.com

    • 量子化GGUF:"F32", "F16"量子化していない巨大なGGUF。
    • 量子化GGUF:"Q4_0"、"Q4_1"、"Q5_0"、"Q5_1"、"Q8_0"。Q8以外では既にレガシー扱いとなった最初期フォーマットのGGUF。
    • k-量子化GGUF"Q2_K", "Q2_K_S", "Q3_K_S", "Q3_K_M", "Q3_K_L","Q4_K_S", "Q4_K_M", "Q5_K_S", "Q5_K_M", "Q6_K"。長らく使われている馴染み深いGGUF。後述のiMatrixにも対応しているので一応現役。
    • i-量子化GGUF"IQ1_S", "IQ2_XXS", "IQ2_XS", "IQ2_S", "IQ2_M", "IQ3_XXS", "IQ3_XS", "IQ3_S", "IQ3_M", "IQ4_XS"。最近相次いで追加された、Important Matrix計算前提のGGUF。3bit以下でも量子化誤差を抑える実装。
    • 非線形量子化GGUF"IQ4_NL"。導入意図がよく理解できず。Qwenモデルなどへの対応?

どの量子化を使えばいいのか

  • 雑に言うと、5bit以上では"k-量子化"、4bit以下では"i-量子化"の中から、RAM/VRAM容量に合わせて選択することになると思います。
  • IQの付くi-量子化は、事前計算したImportance Matrixを用いて量子化することで誤差を抑えた量子化モデルです。
  • そのため、もともとはi-量子化のほうがサイズ比で高性能だったのですが、その後k-量子化モデルもiMatrix計算に対応することになったので、分類が分かりづらい状態になっています。
  • HuggingFace上のGGUFモデルの場合、"iMat"や"iMatrix"と明記されている量子化モデルがImportance Matrix計算を行っているものです。

おすすめの量子化サイズ(英語モデルの場合)

  • 量子化による影響度はモデルによって異なるので、おおざっぱな一般論です。
  • 基本的に"Q8_0"なら性能劣化はほぼ無いとされています。ただ正直なところ、"Q5K_M"くらいまでは性能低下に気づくのは難しいので、同じようなものかなと感じます。
  • 性能とサイズのバランスを取りたい場合、従来のk-量子化だと"Q4K_M"程度なら劣化は限られます。iMatrix版を使えるのなら"IQ4_XS", "Q4K_S"でも十分だと思います。
  • サイズ重視で小さめのモデルを選びたい場合はiMatrix版が必須です。"IQ3_XXS"程度までは意外と劣化を感じにくいかもしれません。i-量子化で初期に導入されたクラスで、7Bモデルの場合は3GB弱のサイズ感です。2bit以下の量子化になると、劣化が確実に見える印象があります。

日本語モデルの場合

  • 個人的には、日本語モデルは量子化による性能低下がより厳しいと思います(英語モデルの劣化は、単に語学力の問題で気づきにくいだけかもしれません...)。
  • 日本語モデルの場合は3bit以下の量子化はできるだけ避け、4bit以上のサイズをおすすめします。無理に大型モデルの低bit量子化を使うより、より小型のモデルに切り替えたほうが良い結果が得られることが多いです。

追記:KL-divergence による量子化評価

  • 下記は llama.cpp の dev が作成したものではなく、ユーザーの方がrepoにポストされていたグラフですが、とても網羅的なので参考に転載しておきます(モデルはMistral 7B instruct v0.1)。
  • KL-divergence は Perplexity よりもモデル性能を適切に評価できるとされていて、最近ローカルLLM界隈でよく使われています。

https://github.com/ggerganov/llama.cpp/pull/5747