Featured image of post [On-Device AI] 02. Quantization — 비트 수를 줄이는 법

[On-Device AI] 02. Quantization — 비트 수를 줄이는 법

Linear Quantization의 Scale·Zero-point 계산부터 Symmetric·Asymmetric 방식, Static·Dynamic Quantization, PTQ와 QAT의 트레이드오프까지 모델을 저비트로 표현하는 Quantization의 핵심을 정리합니다.

01장의 Pruning이 “연결을 끊는” 방식이라면, Quantization(양자화)은 각 값을 표현하는 비트 수를 줄이는 방식입니다. 32비트 부동소수점으로 저장하던 가중치를 8비트나 4비트 정수로 바꾸면, 같은 모델도 저장 공간과 메모리 대역폭 사용량이 그만큼 줄어듭니다. 이 장은 값을 정수로 매핑하는 계산 과정부터, 언제 양자화 파라미터를 계산할지, 그리고 학습을 포함시킬지 여부에 따른 트레이드오프를 다룹니다.

왜 BF16 같은 포맷이 등장했는가

소수점을 얼마나 세밀하게 표현하느냐보다, 값의 범위를 얼마나 넓게 표현할 수 있느냐가 실전에서 더 중요한 경우가 많습니다. 일반적인 16비트 부동소수점(FP16)은 32비트(FP32)보다 지수(exponent) 비트를 줄여 표현 범위 자체가 좁아지는 반면, BF16(bfloat16)은 지수 비트를 FP32와 동일하게 유지하고 가수(mantissa) 비트만 줄입니다. 정밀도는 다소 떨어지더라도 오버플로우에 강한 넓은 범위를 유지할 수 있어, 최근 LLM 학습·추론에서 기본값처럼 쓰입니다.

Quantization의 종류

값을 저비트로 매핑하는 방식은 크게 세 갈래로 나뉩니다. Learned Quantization은 데이터로부터 양자화 구간(레벨)을 학습하거나 결정합니다 — 예를 들어 K-means 클러스터링으로 비슷한 값끼리 묶어 조회 테이블(lookup table)로 구현합니다. Uniform(균일) Quantization은 정수와 실수 사이를 $r = S(q - Z)$ 형태의 아핀(affine) 변환으로 매핑하며, 양자화 구간 사이의 간격이 균일합니다. Non-Uniform(비균일) Quantization은 구간 간격이 데이터 분포에 따라 다르게 설정됩니다.

Static과 Dynamic — 언제 양자화 파라미터를 정할 것인가

가중치(Weight)는 학습이 끝난 시점에 이미 고정된 값을 알고 있으므로, 추론 전에 미리(static) 양자화 파라미터를 계산해둘 수 있습니다. 반면 활성화값(Activation)은 입력에 따라 매번 달라지므로 미리 알 수 없습니다. 그럼에도 실무에서는 대표 입력 데이터로 미리 범위를 추정해두는 Static 방식(calibration)이 더 많이 사용됩니다 — 매 추론마다 범위를 다시 계산하는 Dynamic 방식보다 오버헤드가 적기 때문입니다.

Linear Quantization의 계산

양자화는 실수 값 $r$을 정수 $q$로 바꾸는 과정입니다.

$$q = \mathrm{clamp}\big(\mathrm{round}(r/S) + Z\big), \qquad r = S(q - Z)$$

여기서 $S$(Scale)는 정수 구간과 실수 구간의 비율이고, $Z$(Zero-point)는 원래 값에서 “0"에 해당하는 정수 위치입니다. 양자화 파라미터는 실제 값의 범위로부터 계산합니다.

$$S = \frac{r_{max} - r_{min}}{q_{max} - q_{min}}, \qquad Z = \mathrm{round}\left(q_{min} - \frac{r_{min}}{S}\right)$$
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import torch

def linear_quantize(r: torch.Tensor, num_bits: int = 8):
    q_min, q_max = 0, 2**num_bits - 1
    r_min, r_max = r.min(), r.max()
    scale = (r_max - r_min) / (q_max - q_min)
    zero_point = torch.round(q_min - r_min / scale)
    q = torch.clamp(torch.round(r / scale) + zero_point, q_min, q_max)
    return q.to(torch.uint8), scale, zero_point

def dequantize(q: torch.Tensor, scale: torch.Tensor, zero_point: torch.Tensor) -> torch.Tensor:
    return scale * (q.float() - zero_point)

가중치는 분포가 0을 중심으로 거의 대칭이므로, Zero-point를 항상 0으로 고정하고 $S = |W|{max} / q{max}$만 구하는 Symmetric(대칭) 방식을 주로 씁니다. Symmetric 방식은 Zero-point 계산·저장이 필요 없어 연산이 단순해지는 장점이 있지만, 실제 분포가 대칭이 아닐 경우 Asymmetric(비대칭) 방식보다 오차가 커질 수 있습니다.

Weight와 Activation을 각각 저비트로 양자화했다면, 매번 역양자화(dequantization)해서 계산하는 대신 저비트 상태 그대로 연산하고, 값이 누적(accumulate)되는 부분에서만 더 높은 정밀도(예: 32비트)로 처리해 오차 누적을 방지하는 방식이 실무에서 널리 쓰입니다.

Outlier(이상치) 처리 — CNN과 LLM의 차이

값의 분포에서 극단적으로 크거나 작은 outlier를 어떻게 다루느냐도 중요한 설계 지점입니다. CNN 시절에는 outlier를 제거(clipping)하는 방식이 일반적이었습니다. 하지만 LLM에서는 outlier를 단순히 제거하지 않고 보정(compensate)해서 사용하는 방식이 선호됩니다 — LLM에서는 특정 채널에 몰린 outlier가 실제로 중요한 정보를 담고 있는 경우가 많기 때문입니다. 이 통찰은 05장에서 다룰 AWQ에서 더 발전된 형태로 다시 등장합니다.

PTQ와 QAT — 언제 양자화할 것인가

PTQ(Post-Training Quantization)는 이미 학습이 끝난 모델에 대해, 추가 학습 없이 소량의 데이터만 사용해 양자화 파라미터만 뽑아냅니다. 작업량(overhead)이 적은 대신 정확도가 다소 떨어질 수 있으며, AdaRound 같은 보정 기법으로 정확도를 끌어올릴 수 있습니다. Per-Channel Weight Quantization은 텐서 전체에 하나의 Scale을 쓰는 Per-Tensor 방식이 채널마다 값의 범위가 크게 다른 작은 모델에서 문제가 될 수 있어, 채널별로 Scale을 따로 두는 방식입니다(다만 Scale 저장 비용이 채널 수만큼 늘어납니다). Weight Equalization은 Per-Channel의 메모리 부담과 Per-Tensor의 낮은 정확도 사이의 절충안으로, 채널 간 값의 범위를 사전에 맞춰주는 기법입니다(활성화 함수가 선형이어야 정확하게 적용 가능합니다).

QAT(Quantization-Aware Training)는 가중치를 32비트로 유지하면서, 순전파 과정에서는 저비트로 양자화된 것처럼 계산하고 그 결과로 발생하는 오차를 학습 과정에 반영합니다. 문제는 양자화 함수가 계단(step) 형태라 미분이 불가능하다는 것입니다(기울기가 대부분 0). 그래서 순전파에서는 실제 계단형 양자화 함수를 쓰지만, 역전파에서는 선형 함수인 것처럼 근사해 기울기를 흘려보냅니다(Straight-Through Estimator와 유사한 아이디어).

PTQQAT
추가 학습불필요(소량의 calibration 데이터만)필요
비용낮음높음
정확도상대적으로 낮음(AdaRound 등으로 보정 가능)상대적으로 높음

흔한 오개념 — “양자화 함수는 미분이 안 되니 QAT는 불가능하다”

양자화 함수가 계단 형태라 기울기가 거의 항상 0이라는 사실만 보면, “손실을 역전파로 최소화하는” 일반적인 학습 방식이 QAT에는 적용될 수 없을 것처럼 보입니다. 하지만 QAT는 이 문제를 “정확한 미분"이 아니라 “학습에 유용한 근사"로 우회합니다 — Straight-Through Estimator는 순전파에서는 실제 계단 함수를 쓰되, 역전파에서는 그 계단 함수가 마치 항등함수(기울기 1)인 것처럼 취급해 기울기를 그대로 통과시킵니다. 이는 수학적으로 엄밀한 미분이 아니라 실용적인 근사이지만, 실제로는 이 근사만으로도 양자화로 인한 오차를 학습 과정에 충분히 반영할 수 있다는 것이 QAT가 실무에서 동작하는 이유입니다.

다음 장에서는 Pruning·Quantization과는 다른 세 번째 축인 Knowledge Distillation을, Teacher-Student 구조와 Temperature를 이용한 Soft Label 전달 방식 중심으로 다룹니다.