Step 22 양자화(Quantization)

거대 모델을 내 컴퓨터에 — GGUF, INT8, INT4의 모든 것

1. 왜 양자화가 필요한가?

LLaMA 3 70B 모델을 그냥 실행하려면 VRAM 140GB 이상이 필요합니다. 최신 RTX 4090도 24GB밖에 없습니다. 일반인은 절대 못 쓰죠. 양자화는 이 거대한 모델을 소비자 GPU에서도 돌아가도록 압축하는 기술입니다.

📊 LLaMA 3 70B — 양자화 전후 비교

방식비트수파일 크기필요 VRAM일반 GPU 가능?
원본 (FP32)32bit~280GB280GB+❌ 절대 불가
FP16 / BF1616bit~140GB140GB+❌ 불가
INT88bit~70GB70GB+❌ A100 필요
Q4_K_M (GGUF)4bit~40GB40GB+⚠️ A6000 정도
Q4_K_M (분할)4bit~40GBCPU 오프로드✅ 일반 PC 가능!

※ 더 작은 모델(7B, 13B)은 4bit 양자화 시 일반 GPU(8~16GB)로도 충분히 가능합니다.

2. 양자화란 정확히 무엇인가?

모델의 가중치(weight)는 원래 32비트 부동소수점(FP32)으로 저장됩니다. 양자화는 이 값을 더 적은 비트의 정수(INT)로 변환하는 것입니다. 마치 사진을 압축하는 것처럼요!

🔢 비트 수에 따른 표현 가능 값의 범위

비트 수가 많을수록 더 정밀하게 표현 가능 FP32 (32비트) 4,294,967,296가지 값 표현 가능 (정밀도 매우 높음) 4 bytes/값 FP16 (16비트) 65,536가지 값 표현 2 bytes/값 INT8 (8비트) 256가지 값 1 byte/값 INT4 (4비트) 16가지 0.5 bytes/값 정밀 압축

🧮 실제 변환 예시 — FP32 → INT8

가중치 값을 정수 범위로 선형 매핑 FP32 원본 가중치 [-1.234, 0.567, -0.089, 2.341] 32비트 float → 각 4바이트 = 16바이트 scale 계산 min/max 찾기 scale = 2.341 / 127 = 0.01843 zero_point = 0 양자화 [-67, 31, -5, 127] INT8 → 각 1바이트 = 4바이트 역양자화 (추론 시 복원): INT8 × scale → 근사 FP32 -67 × 0.01843 = -1.235 (원본 -1.234, 오차 0.001) ✅ 메모리 4배 절약, 정밀도 손실은 미미!

3. GGUF 포맷이란?

GGUFllama.cpp 프로젝트에서 개발한 양자화 모델 저장 포맷입니다. CPU로도 LLM을 실행할 수 있게 해주며, HuggingFace에 수천 개의 GGUF 모델이 올라와 있습니다.

📦 GGUF 양자화 레벨 완전 가이드

포맷비트/가중치7B 크기품질추천 상황
F3232~28GB완벽학습 시 (추론엔 쓰지 않음)
F1616~14GB거의 완벽고급 GPU (VRAM 충분할 때)
Q8_08~7.2GB매우 좋음VRAM 8GB+ GPU, 품질 우선
Q5_K_M5~4.8GB좋음품질과 크기 균형 (추천)
Q4_K_M4~4.1GB좋음가장 대중적 (기본 추천)
Q3_K_M3~3.3GB보통VRAM 4GB 이하, 속도 우선
Q2_K2~2.7GB떨어짐최후의 수단
IQ4_XS~4~3.9GB좋음중요 레이어 보호 방식

K_M, K_S, K_L의 의미:
K = "K-quants" (더 스마트한 양자화 방식, 중요 레이어에 더 많은 비트 할당)
M = Medium (균형), S = Small (더 압축), L = Large (더 좋은 품질)

4. 품질 손실이 얼마나 심한가?

📉 양자화 레벨별 품질 비교 (Perplexity 기준)

Perplexity (낮을수록 좋음) — LLaMA 7B 기준 F16 대비 품질 저하율 (오른쪽 막대가 길수록 품질 저하 큼) F16 (기준) 0% (기준) Q8_0 +0.03% 사실상 무손실 Q5_K_M +0.11% ✅ 권장 — 체감 거의 없음 Q4_K_M +0.22% ✅ 권장 — 일반 사용 충분 Q3_K_M +0.68% △ 가끔 어색한 답변 Q2_K +2.15% ❌ 체감 품질 저하

결론: Q4_K_M, Q5_K_M은 실사용에서 F16과 거의 차이가 없습니다. 일반 사용자에게는 Q4_K_M이 최고의 선택입니다 (크기 최소화 + 품질 유지).

5. Ollama로 양자화 모델 실행하기

Ollama는 양자화 모델을 가장 쉽게 실행할 수 있는 도구입니다. Docker처럼 모델을 pull 해서 바로 실행합니다.

🚀 Ollama 설치 및 실행

# 1. Ollama 설치 (Linux/Mac)
curl -fsSL https://ollama.ai/install.sh | sh

# 2. 모델 다운로드 및 실행 (자동으로 Q4_K_M 받음)
ollama run llama3           # Meta Llama 3 8B
ollama run mistral          # Mistral 7B
ollama run exaone-deep:7.8b # EXAONE Deep 7.8B (한국어)
ollama run qwen2.5:14b      # Qwen 2.5 14B

# 3. Python에서 사용 (OpenAI 호환 API)
import ollama

response = ollama.chat(
    model='llama3',
    messages=[{'role': 'user', 'content': '안녕하세요!'}]
)
print(response['message']['content'])

# 4. OpenAI SDK 호환 방식으로도 사용 가능
from openai import OpenAI
client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
response = client.chat.completions.create(
    model="llama3",
    messages=[{"role": "user", "content": "파이썬 코드 작성해줘"}]
)

6. llama.cpp로 GGUF 직접 실행

⚙️ llama.cpp — 더 세밀한 제어

# 1. llama.cpp 빌드
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make -j8  # GPU 지원: make LLAMA_CUBLAS=1 -j8

# 2. HuggingFace에서 GGUF 모델 다운로드
pip install huggingface_hub
huggingface-cli download \
  LGAI-EXAONE/EXAONE-Deep-32B-Instruct-GGUF \
  --include "EXAONE-Deep-32B-Instruct-Q4_K_M.gguf" \
  --local-dir ./models

# 3. 실행 (GPU 오프로드 레이어 설정 가능)
./llama-cli \
  -m ./models/EXAONE-Deep-32B-Instruct-Q4_K_M.gguf \
  -n 512 \          # 최대 생성 토큰
  -ngl 35 \         # GPU에 올릴 레이어 수 (VRAM 여유에 따라 조정)
  --temp 0.7 \      # 온도 (높을수록 창의적)
  -p "안녕하세요!"  # 프롬프트

# 4. Python 바인딩 (llama-cpp-python)
pip install llama-cpp-python
from llama_cpp import Llama

llm = Llama(
    model_path="./models/model-Q4_K_M.gguf",
    n_gpu_layers=35,   # GPU 레이어 수
    n_ctx=4096,        # 컨텍스트 길이
)
output = llm("Q: 파이썬으로 Hello World 출력하는 방법은? A:")
print(output['choices'][0]['text'])

7. HuggingFace로 INT8/INT4 양자화

🤗 bitsandbytes로 GPU에서 양자화

pip install transformers bitsandbytes accelerate

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch

# ── INT8 양자화 로드 ──────────────────────────────
quantization_config = BitsAndBytesConfig(load_in_8bit=True)

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Meta-Llama-3-8B-Instruct",
    quantization_config=quantization_config,
    device_map="auto"   # GPU 자동 분배
)
# 원래 16GB → 8GB로 절반 절약!

# ── INT4 양자화 (QLoRA 방식) ──────────────────────
quantization_config_4bit = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.bfloat16,  # 연산은 BF16으로
    bnb_4bit_use_double_quant=True,          # 이중 양자화로 추가 절약
    bnb_4bit_quant_type="nf4"               # NF4 = 정규분포 기반 4bit
)

model_4bit = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Meta-Llama-3-8B-Instruct",
    quantization_config=quantization_config_4bit,
    device_map="auto"
)
# 원래 16GB → 4.5GB! 소비자 GPU에서 70B도 가능!

# 사용법은 일반 모델과 동일
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct")
inputs = tokenizer("AI란 무엇인가요?", return_tensors="pt").to("cuda")
outputs = model_4bit.generate(**inputs, max_new_tokens=200)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

8. 내 GPU에 맞는 모델 선택 가이드

🎮 GPU별 추천 모델 (Q4_K_M 기준)

GPUVRAM추천 모델한국어 추천
RTX 3060 / 40608GBLlama 3.2 3B, Mistral 7B Q4EXAONE 3.5 7.8B Q4
RTX 4070 Ti / 5070 Ti16GBLlama 3 8B Q8, Mistral 22B Q4EXAONE Deep 7.8B Q8, Qwen2.5 14B Q4
RTX 3090 / 409024GBLlama 3.3 70B Q2, Mistral 22B Q8EXAONE Deep 32B Q3
A6000 / RTX 600048GBLlama 3.3 70B Q4_K_MEXAONE Deep 32B Q8
CPU만 있을 때RAM 32GBLlama 3.2 3B, Phi-3 MiniEXAONE 3.5 7.8B Q4 (느림)
💡 5070 Ti (16GB) 사용자를 위한 팁:

Qwen2.5 14B Q4_K_M (~8.5GB) 또는 EXAONE Deep 7.8B Q8 (~9GB)가 최적입니다. 32B 모델은 IQ3_XS (~14GB) 포맷을 쓰면 아슬아슬하게 가능합니다. CPU 오프로드 옵션(-ngl 줄이기)을 활용하면 더 큰 모델도 (느리지만) 실행 가능합니다.

9. 양자화 방식 한눈에 비교

⚖️ GGUF vs bitsandbytes vs AWQ — 언제 뭘 쓰나?

방식포맷CPU 실행GPU 필요파인튜닝 가능추천 상황
GGUF.gguf✅ 가능옵션로컬 추론, Ollama
bitsandbytesHF 모델✅ 필수✅ QLoRAGPU 파인튜닝
AWQ.safetensors✅ 필수GPU 추론, 빠른 속도
GPTQ.safetensors✅ 필수GPU 추론

✅ 양자화 핵심 정리