콘텐츠로 이동

LLM Quantization

개요

양자화(Quantization)는 모델의 가중치와 활성화를 더 낮은 비트 정밀도로 표현하여 메모리 사용량과 추론 속도를 개선하는 기법이다. FP32나 FP16 대신 INT8, INT4 등을 사용하여 모델 크기를 2-8배 줄일 수 있다.

핵심 개념

양자화 기본 원리

Quantization:
  x_q = round(x / scale) + zero_point

Dequantization:
  x = (x_q - zero_point) * scale

여기서: - x: 원본 FP32/FP16 값 - x_q: 양자화된 INT 값 - scale: 스케일링 팩터 - zero_point: 영점 오프셋

양자화 유형

유형 설명 예시
Weight-only 가중치만 양자화 GPTQ, AWQ, GGUF
Dynamic 추론 시 활성화 동적 양자화 PyTorch Dynamic Quant
Static 캘리브레이션 후 고정 양자화 TensorRT
QAT 학습 중 양자화 LLM-QAT

그룹 양자화 (Group Quantization)

Per-tensor:  전체 텐서에 단일 scale/zero_point
Per-channel: 채널별 scale/zero_point
Per-group:   그룹(예: 128개)별 scale/zero_point

Precision vs Efficiency tradeoff:
Per-tensor < Per-channel < Per-group (in terms of accuracy)
Per-tensor > Per-channel > Per-group (in terms of efficiency)

아키텍처 다이어그램

Weight-only Quantization 흐름

    Original Model (FP16)
           |
           v
    +------------------+
    | Calibration Data |
    | (for AWQ/GPTQ)   |
    +--------+---------+
             |
             v
    +------------------+
    | Quantization     |
    | Algorithm        |
    | (GPTQ/AWQ/etc)   |
    +--------+---------+
             |
             v
    +------------------+
    | Quantized Model  |
    | (INT4/INT8)      |
    +--------+---------+
             |
             v
    +------------------+
    | Inference        |
    | (Dequant on fly) |
    +------------------+

GPTQ 알고리즘 흐름

    Weight Matrix W
          |
          v
    +---------------------+
    | Compute Hessian H   |
    | H = X^T X           |
    | (from calibration)  |
    +----------+----------+
               |
               v
    +---------------------+
    | For each column i:  |
    |                     |
    | 1. Quantize w_i     |
    |    q_i = round(w_i) |
    |                     |
    | 2. Compute error    |
    |    e = w_i - q_i    |
    |                     |
    | 3. Update remaining |
    |    W[:,i+1:] -=     |
    |    e * H[i,i+1:]/   |
    |    H[i,i]           |
    +---------------------+
               |
               v
    Quantized Weight Q

AWQ (Activation-aware Weight Quantization)

                Calibration Data
                       |
                       v
               +---------------+
               | Run Forward   |
               | Collect Acts  |
               +-------+-------+
                       |
                       v
               +---------------+
               | Find Salient  |
               | Channels      |
               | (high act mag)|
               +-------+-------+
                       |
                       v
               +---------------+
               | Scale Salient |
               | Weights Up    |
               | (protect them)|
               +-------+-------+
                       |
                       v
               +---------------+
               | Quantize      |
               | All Weights   |
               +-------+-------+
                       |
                       v
               +---------------+
               | Scale Back    |
               | During Infer  |
               +---------------+

GGUF 파일 구조

    +----------------------------------+
    |           GGUF Header            |
    +----------------------------------+
    | Magic Number: "GGUF"             |
    | Version: 3                       |
    | Tensor Count                     |
    | Metadata KV Count                |
    +----------------------------------+
    |           Metadata               |
    +----------------------------------+
    | general.architecture: "llama"    |
    | general.name: "Llama-3-8B"       |
    | llama.context_length: 8192       |
    | llama.embedding_length: 4096     |
    | ...                              |
    +----------------------------------+
    |        Tensor Info               |
    +----------------------------------+
    | token_embd.weight: Q4_K_M        |
    | blk.0.attn_q.weight: Q4_K_M      |
    | blk.0.attn_k.weight: Q4_K_M      |
    | ...                              |
    +----------------------------------+
    |        Tensor Data               |
    +----------------------------------+
    | [Quantized weight bytes]         |
    | [...]                            |
    +----------------------------------+

K-Quants 구조 (GGUF)

    Q4_K_M Block (32 weights per block)

    +------------------------------------------+
    | Scales (6 bits x 8 = 48 bits = 6 bytes)  |
    +------------------------------------------+
    | Mins (6 bits x 8 = 48 bits = 6 bytes)    |
    +------------------------------------------+
    | Weights (4 bits x 32 = 128 bits=16 bytes)|
    +------------------------------------------+

    Total: 28 bytes for 32 weights = 7 bits per weight

    Dequantization:
    w[i] = (quantized[i] * scale[group] + min[group])

주요 양자화 기법 비교

GPTQ vs AWQ vs GGUF

+----------+----------------+----------------+----------------+
| 특성     | GPTQ           | AWQ            | GGUF           |
+----------+----------------+----------------+----------------+
| 방식     | OBQ 기반       | Activation     | K-quant        |
|          | 2차 정보 활용  | aware scaling  | 블록 양자화    |
+----------+----------------+----------------+----------------+
| 정밀도   | 높음           | 매우 높음      | 좋음           |
+----------+----------------+----------------+----------------+
| 속도     | 중간           | 빠름           | 매우 빠름      |
|          | (양자화 시간)  |                | (CPU 최적화)   |
+----------+----------------+----------------+----------------+
| 하드웨어 | GPU 필요       | GPU 필요       | CPU/GPU 모두   |
+----------+----------------+----------------+----------------+
| 사용처   | GPU 추론       | GPU 추론       | CPU/Edge       |
|          | (vLLM, TGI)    | (vLLM 권장)    | (llama.cpp)    |
+----------+----------------+----------------+----------------+

비트별 품질/크기 비교

    Model Quality vs Size Tradeoff

    |Quality
    |
    |  * FP16 (100%)
    |  
    |  * INT8 (99.5%)
    |  
    |  * Q8_0 (99%)
    |  
    |  * Q6_K (98.5%)
    |  
    |  * Q5_K_M (97%)
    |  
    |  * Q4_K_M (95%)
    |  
    |  * Q4_0 (93%)
    |  
    |  * Q3_K_M (90%)
    |  
    |  * Q2_K (85%)
    |
    +---------------------------------> Size Reduction
      1x    2x    3x    4x    5x    6x

대표 양자화 모델

원본 모델 양자화 크기 VRAM 필요
Llama-3-70B FP16 140GB ~150GB
Llama-3-70B Q8_0 70GB ~75GB
Llama-3-70B Q4_K_M 40GB ~45GB
Llama-3-8B FP16 16GB ~18GB
Llama-3-8B Q4_K_M 4.7GB ~6GB
Llama-3-8B Q3_K_M 3.9GB ~5GB

장단점

GPTQ

장점: - 높은 정확도 유지 - GPU 추론에 최적화 - vLLM, TGI 등 서빙 프레임워크 지원

단점: - 양자화에 GPU 및 캘리브레이션 데이터 필요 - 양자화 시간이 오래 걸림 - CPU 추론 지원 제한

AWQ

장점: - GPTQ보다 높은 정확도 (특히 instruction-tuned 모델) - 빠른 양자화 속도 - vLLM 권장 포맷

단점: - GPU 필요 - GPTQ보다 생태계가 작음 (하지만 빠르게 성장 중)

GGUF

장점: - CPU 추론 최적화 (llama.cpp) - 다양한 양자화 레벨 (Q2~Q8) - 플랫폼 독립적 (Windows, Mac, Linux) - 부분 GPU 오프로딩 지원

단점: - 순수 GPU 추론은 GPTQ/AWQ보다 느릴 수 있음 - 서빙 프레임워크 지원 제한 (주로 llama.cpp)

코드 예시

GPTQ 양자화 (AutoGPTQ)

from transformers import AutoModelForCausalLM, AutoTokenizer
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig

# Load model
model_name = "meta-llama/Meta-Llama-3-8B"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
    model_name, 
    torch_dtype=torch.float16,
    device_map="auto"
)

# Prepare calibration data
calibration_data = [
    tokenizer(text, return_tensors="pt")
    for text in [
        "The quick brown fox jumps over the lazy dog.",
        "Machine learning is a subset of artificial intelligence.",
        # ... more calibration texts
    ]
]

# Quantization config
quantize_config = BaseQuantizeConfig(
    bits=4,                 # 4-bit quantization
    group_size=128,         # Group size for quantization
    desc_act=True,          # Descending activation order
    damp_percent=0.01,      # Dampening factor
)

# Quantize
quantized_model = AutoGPTQForCausalLM.from_pretrained(
    model_name,
    quantize_config=quantize_config
)
quantized_model.quantize(calibration_data)

# Save
quantized_model.save_quantized("llama3-8b-gptq-4bit")

AWQ 양자화 (AutoAWQ)

from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer

# Load model
model_path = "meta-llama/Meta-Llama-3-8B"
quant_path = "llama3-8b-awq-4bit"

model = AutoAWQForCausalLM.from_pretrained(
    model_path,
    device_map="auto",
    safetensors=True
)
tokenizer = AutoTokenizer.from_pretrained(model_path)

# Quantization config
quant_config = {
    "zero_point": True,
    "q_group_size": 128,
    "w_bit": 4,
    "version": "GEMM"
}

# Quantize
model.quantize(
    tokenizer,
    quant_config=quant_config,
    calib_data="pileval",  # Built-in calibration dataset
)

# Save
model.save_quantized(quant_path)
tokenizer.save_pretrained(quant_path)

GGUF 변환 및 양자화 (llama.cpp)

# 1. Convert HuggingFace model to GGUF
python convert_hf_to_gguf.py \
    ./meta-llama-3-8b \
    --outfile llama3-8b-f16.gguf \
    --outtype f16

# 2. Quantize to different formats
./llama-quantize llama3-8b-f16.gguf llama3-8b-q4_k_m.gguf Q4_K_M
./llama-quantize llama3-8b-f16.gguf llama3-8b-q5_k_m.gguf Q5_K_M
./llama-quantize llama3-8b-f16.gguf llama3-8b-q8_0.gguf Q8_0

# 3. Run inference
./llama-cli -m llama3-8b-q4_k_m.gguf -p "Hello, world!" -n 100

vLLM으로 양자화 모델 서빙

from vllm import LLM, SamplingParams

# AWQ model (recommended for vLLM)
llm = LLM(
    model="TheBloke/Llama-3-8B-AWQ",
    quantization="awq",
    dtype="half",
    gpu_memory_utilization=0.90
)

# GPTQ model
llm = LLM(
    model="TheBloke/Llama-3-8B-GPTQ",
    quantization="gptq",
    dtype="half"
)

# Generate
sampling_params = SamplingParams(
    temperature=0.7,
    max_tokens=256
)
outputs = llm.generate(["Hello, how are you?"], sampling_params)

GGUF K-Quant 상세

타입 비트/가중치 설명 권장 사용처
Q2_K 2.56 최소 크기, 낮은 품질 테스트용
Q3_K_S 3.41 작은 K-quant 메모리 극히 제한
Q3_K_M 3.91 중간 K-quant 메모리 제한
Q4_0 4.50 레거시 4비트 호환성 필요 시
Q4_K_S 4.58 작은 4비트 K-quant 균형
Q4_K_M 4.85 중간 4비트 K-quant 권장 기본값
Q5_K_S 5.52 작은 5비트 K-quant 높은 품질
Q5_K_M 5.69 중간 5비트 K-quant 품질 우선
Q6_K 6.56 6비트 K-quant 최고 품질
Q8_0 8.50 8비트 품질 최우선

참고 논문 및 자료

  1. Frantar, E., et al. (2022). "GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers."
  2. arXiv: https://arxiv.org/abs/2210.17323

  3. Lin, J., et al. (2023). "AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration."

  4. arXiv: https://arxiv.org/abs/2306.00978

  5. Dettmers, T., et al. (2022). "LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale."

  6. arXiv: https://arxiv.org/abs/2208.07339

  7. Dettmers, T., et al. (2023). "QLoRA: Efficient Finetuning of Quantized LLMs."

  8. arXiv: https://arxiv.org/abs/2305.14314

  9. GGML/GGUF Documentation

  10. https://github.com/ggerganov/ggml
  11. https://github.com/ggerganov/llama.cpp

  12. AutoGPTQ

  13. https://github.com/AutoGPTQ/AutoGPTQ

  14. AutoAWQ

  15. https://github.com/casper-hansen/AutoAWQ