양자화 입문¶
이 챕터에서 배우는 것
- int8 / int4 양자화 — fp16 가중치를 정수로 압축
- symmetric vs asymmetric, per-tensor vs per-channel 의 의미
- Post-training quantization (PTQ) 한 번 — 가장 단순한 길
- 메모리 1/4 ~ 1/8, 정확도 손실은 PPL 5~10% 이내
1. 개념 — 비트 줄이기¶
| 형식 | bytes | 표현 가능 값 | 정확도 손실 |
|---|---|---|---|
| fp32 | 4 | ±3.4×10³⁸ | 0 (기준) |
| fp16 | 2 | ±6.5×10⁴ | <1% |
| int8 | 1 | -128 ~ 127 (256 값) | 2~5% |
| int4 | 0.5 | -8 ~ 7 (16 값) | 5~15% |
| int2 | 0.25 | -2 ~ 1 (4 값) | 30%+ (실용 X) |
본 책 10M 모델 fp16 = 20MB → int4 = 5MB. 모바일/노트북에 매우 가벼움.
양자화 식 (symmetric)¶
s(scale) — 가중치 max 절댓값을 정수 max 로 나눈 비율q— 정수- 역양자화:
x ≈ q × s
손실은 round 단계에서. 숫자 분포가 좁고 균등할수록 손실 적음.
2. 왜 필요한가 — 메모리·속도·전력¶
| 디바이스 | fp16 모델 한계 | int4 모델 한계 |
|---|---|---|
| 모바일 (4GB) | 1B | 7B |
| 노트북 (16GB) | 7B | 30B |
| Colab T4 (16GB) | 8B | 40B |
| A100 80GB | 40B | 160B |
→ 양자화 없이는 큰 모델을 작은 디바이스에 못 띄움. 본 책 10M 은 양자화 없어도 어디든 들어가지만, 캡스톤에서 더 큰 모델 (1B+) 다룰 때 필수.
또: 추론 속도 도 빨라짐 (int matmul 이 fp16 보다 ~2× 빠름, 단 hardware 지원 시).
3. 어디에 쓰이나 — 4가지 변형¶
3.1 Per-tensor vs Per-channel¶
- Per-tensor: 전체 가중치 행렬에 scale 1개. 단순, 손실 큼.
- Per-channel: 각 row (또는 column) 별로 scale. 정밀, 메타데이터 ↑.
→ 표준은 per-channel.
3.2 Symmetric vs Asymmetric¶
- Symmetric: scale 만. zero point = 0. weight 분포가 0 중심일 때.
- Asymmetric: scale + zero point. activation (ReLU 후) 같이 한쪽으로 쏠릴 때.
→ Weight = symmetric, activation = asymmetric 이 일반.
3.3 PTQ (Post-Training Quantization)¶
학습 끝난 모델에 양자화만 적용. 추가 학습 없음. 가장 단순. 본 책의 길.
3.4 QAT (Quantization-Aware Training)¶
학습 중에 양자화 흉내. 손실 최소. 학습 비용 ↑.
본 책은 PTQ 만 — Part 7 의 LoRA 와 결합한 QLoRA 가 사실상 PTQ + LoRA.
4. 최소 예제 — 손으로 int8 PTQ¶
- 127 = int8 의 양수 max. -128 까지 가능하지만 symmetric 은 보통 ±127.
- 메모리: weight (256·256·4 = 262KB) → q (256·256·1 = 65KB) + scale (256·2 = 512B) = 약 1/4.
전형적 mean abs error: 0.0008 (init weight 의 1% 미만). 학습된 모델에선 살짝 더.
5. 실전 — 본 책 모델 int8/int4 양자화¶
- embedding 은 양자화 안 함 (작은 모델일수록 영향 큼).
- 시뮬레이션: 실제 int8 matmul 은 hardware 지원 필요. PyTorch 표준은 quantize → 즉시 dequantize → fp 연산. 진짜 int8 inference 는 다음 챕터의 GGUF.
본 책 10M 모델 결과:
int8 은 거의 무손실, int4 도 실용 범위. 메모리 절감 1/2, 1/4 → 가치 있음.
6. int4 양자화 — 16 값으로¶
int8 (256 값) 의 절반. 손실 더 큼.
- PyTorch 에는 int4 dtype 이 없어 int8 에 저장 (그러나 값은 -8~7 범위만 사용).
Group-wise 양자화 — 128 elements 마다 별도 scale. per-row 보다 정밀, 메타데이터 약간 ↑. GGUF int4 의 표준.
7. 자주 깨지는 포인트¶
1. embedding 도 양자화 — 작은 모델 (10M) 에선 embedding 비중 30%. 양자화하면 PPL 5~10% 추가 손실. embedding 은 fp16 유지.
2. RMSNorm gamma 양자화 — 1D scalar 라 의미 없음. 양자화 대상 = 2D matmul weight 만.
3. per-tensor 만 사용 — 한 행렬에 큰 값과 작은 값 섞이면 둘 다 손실. per-channel / group-wise 가 표준.
4. asymmetric 을 weight 에 — weight 는 0 중심 분포 (RMSNorm + init). asymmetric 은 활용 X, 메타만 ↑.
5. PTQ 만 하고 평가 없음 — int4 양자화 후 PPL 안 재면 어디서 깨졌는지 모름. 항상 양자화 전·후 PPL + 샘플 비교.
6. KV cache 양자화 빼먹음 — 큰 모델 추론 시 KV cache 메모리가 weight 보다 클 수 있음. KV cache 도 int8 양자화 필요 (Part 6 Ch 20 의 GGUF 가 자동).
7. 시뮬레이션 vs 실제 추론 혼동 — dequantize 후 fp16 연산 = fp16 속도 (메모리만 ↓). 진짜 int8 가속 은 GPU/CPU 의 int8 kernel 사용 (다음 챕터 llama.cpp).
8. 운영 시 체크할 점¶
양자화 결정 게이트:
- 베이스라인 PPL (fp16) 측정
- int8 양자화 → PPL 비교 (5% 이내면 OK)
- int4 양자화 → PPL 비교 (10% 이내면 OK)
- embedding 제외 확인 (per-row weight 만)
- per-channel / group-wise 사용
- symmetric (weight) / asymmetric (activation, 필요시)
- 생성 샘플 5개 비교 — 정확도 외 능력 손실 확인
- 메모리 측정 — 실제 절감 비율
- (선택) speed 측정 — 양자화 가속 hardware 지원 확인
9. 연습문제¶
- 본 책 10M 모델에 §5 의 int8 양자화 적용. PPL 변화는?
- §6 의 int4 (group_size=128) vs (group_size=64) 비교. 더 작은 group 이 정밀하지만 메타 ↑.
- embedding 까지 양자화한 vs 제외한 PPL 차이는?
- 양자화된 모델로 §5 의 동화 5개 생성 샘플 (Ch 15) 을 다시 생성. 차이가 보이는가?
- (생각해볼 것) 같은 1B 모델을 int4 로 한 것과 250M 모델을 fp16 으로 한 것 — 메모리는 비슷. 어느 쪽이 능력 좋을까? 어떤 task 에 따라 답이 다를까?
원전¶
- Dettmers et al. (2022). LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale. arXiv:2208.07339
- Frantar et al. (2022). GPTQ. arXiv:2210.17323
- Lin et al. (2023). AWQ. arXiv:2306.00978
- llama.cpp 의 GGUF quantization specs — Q4_0, Q4_K_M 등
- HuggingFace
bitsandbytes라이브러리 docs