0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

科学と神々株式会社アドベントカレンダー 2025

LLM量子化 Day 3: 量子化の基本原理

コンピュータは数をどう表現するか

量子化を理解するために、まずコンピュータがどのように数を表現しているかを見てみましょう。

私たちが普段使う「3.14159」のような小数は、コンピュータ内部では「浮動小数点数」という形式で保存されます。FP16(16ビット浮動小数点数)の場合、1つの数値を16個のビット(0と1)で表現します。

FP16の構造(16ビット):
┌─────┬───────────┬──────────────────┐
│符号 │  指数部   │     仮数部       │
│ 1bit│   5bit    │     10bit        │
└─────┴───────────┴──────────────────┘

この16ビットで、-65504から+65504までの範囲を、約3〜4桁の精度で表現できます。

量子化の核心:「間引く」こと

量子化の本質は、連続的な値を離散的な値に変換することです。

わかりやすい例で考えてみましょう。

身長を測るとき、「175.3847cm」まで測れる精密な身長計と、「175cm」しか表示できない簡易な身長計があったとします。後者は精度が低いですが、ほとんどの目的には十分ですよね。

量子化も同じです。FP16で表現できる膨大な数(約6万5千種類)を、INT4(4ビット整数)で表現できる16種類に「間引く」のです。

FP16: -65504 〜 +65504 の間の無数の値
  ↓ 量子化
INT4: -8, -7, -6, ..., 0, ..., +6, +7 の16種類のみ

線形量子化:最もシンプルな方法

最も基本的な量子化方法は「線形量子化」です。値の範囲を均等に分割して、各値を最も近い区間に割り当てます。

例:0〜100の値を4段階に量子化

元の値     →  量子化後
0〜25      →    0
26〜50     →    1
51〜75     →    2
76〜100    →    3

実際の計算では、「スケール」と「ゼロポイント」という2つのパラメータを使います。

量子化: q = round(x / scale + zero_point)
逆量子化: x' = scale × (q - zero_point)

ここで重要なのは、量子化して逆量子化しても、元の値に完全には戻らないということです。この差が「量子化誤差」です。

量子化誤差:避けられない代償

「42.7」という値を4ビット整数に量子化し、再び元に戻す過程を見てみましょう。

元の値: 42.7
  ↓ 量子化(スケール=10, ゼロポイント=0)
量子化値: round(42.7 / 10) = 4
  ↓ 逆量子化
復元値: 4 × 10 = 40.0

誤差: 42.7 - 40.0 = 2.7

この誤差は避けられません。しかし、LLMの重みは統計的に特定のパターンを持っているため、うまく量子化すれば誤差の影響を最小限に抑えられます。

対称量子化と非対称量子化

量子化には大きく2つのスタイルがあります。

対称量子化

0を中心に対称的に量子化します。実装がシンプルで計算が速いですが、値の分布が偏っている場合に無駄が生じます。

対称量子化(4ビット、符号付き):
-8 -7 -6 -5 -4 -3 -2 -1  0  1  2  3  4  5  6  7
└──────────────────┼──────────────────────────┘
                   0(必ず正確に表現される)

非対称量子化

値の実際の範囲を最大限に活用します。精度は高くなりますが、ゼロポイントの計算が追加で必要です。

非対称量子化:
min        ゼロポイント                    max
 │              │                          │
 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15

どちらが良いかは、データの分布やユースケースによります。LLMの重みは比較的0を中心に対称的な分布を持つことが多いため、対称量子化がよく使われます。

グループ量子化:精度向上の秘訣

ここまでの説明では、モデル全体または層全体に対して1つのスケールを使うことを想定していました。しかし、これには問題があります。

外れ値問題

重みの中に極端に大きな値(外れ値)があると、スケールがその値に引っ張られて、他の値の精度が犠牲になります。

例:値の分布が [0.1, 0.2, 0.1, 0.3, 50.0, 0.2] の場合

全体スケール: 50.0 を表現するためにスケールを大きく設定
  → 0.1〜0.3の小さな値は粗く量子化される

グループ量子化の解決策

重みを小さなグループ(例:128個ずつ)に分割し、各グループに個別のスケールを設定します。

グループ1 [0.1, 0.2, ..., 0.3]  → スケール=0.05
グループ2 [0.5, 50.0, ..., 0.8] → スケール=8.0
グループ3 [0.2, 0.1, ..., 0.2]  → スケール=0.04

これにより、外れ値の影響が局所化され、全体的な精度が向上します。

llm-quantizeでは、デフォルトのグループサイズを128に設定しています。これは精度と効率のバランスが良いとされる値です。

なぜLLMの量子化はうまくいくのか

「こんなに粗く量子化して、本当に大丈夫なの?」という疑問は自然です。LLMの量子化がうまくいく理由を3つ挙げましょう。

1. 冗長性

LLMには多くの冗長性があります。70億個のパラメータすべてが等しく重要なわけではありません。多くのパラメータは似たような値を持っており、多少の誤差は問題になりません。

2. 誤差の相殺

量子化誤差はランダムな方向に発生します。正の誤差と負の誤差が統計的に相殺し合うため、全体としての影響は小さくなります。

3. 重要な重みの保護

現代の量子化手法(k-quant、AWQなど)は、重要な重みを特定し、それらを高い精度で保持します。すべての重みを平等に扱うのではなく、「賢い」量子化を行います。

Tips: 量子化を理解するための実験

理解を深めるために、簡単な実験をしてみましょう。

import numpy as np

# 元のデータ(疑似的な重み)
original = np.random.randn(1000) * 0.1  # 平均0、標準偏差0.1

# 量子化(4ビット相当)
scale = (original.max() - original.min()) / 15
zero_point = -original.min() / scale
quantized = np.round(original / scale + zero_point).astype(int)
quantized = np.clip(quantized, 0, 15)

# 逆量子化
dequantized = scale * (quantized - zero_point)

# 誤差を計算
error = original - dequantized
print(f"平均二乗誤差: {np.mean(error**2):.6f}")
print(f"最大誤差: {np.max(np.abs(error)):.6f}")

この実験で、量子化誤差がどの程度になるか体感できます。

次回予告

Day 4では「量子化手法の分類」について解説します。PTQ(学習後量子化)とQAT(量子化を考慮した学習)の違い、そしてllm-quantizeがなぜPTQを採用しているのかを説明します。


量子化は「情報の圧縮」です。完璧な復元はできませんが、重要な情報を残しながら効率的に圧縮することは可能です。JPEGが画像を圧縮するように、量子化はモデルを圧縮します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?