대칭 vs 비대칭 선형 양자화: 핵심 개념과 실무적 고찰
신경망 양자화 연구 계획에 이어, 이 글에서는 대칭 및 비대칭 선형 양자화의 개념을 한층 더 깊이 있게 다뤄보겠습니다.
아직 대규모 실험이 진행되지는 않았기에, 이 글은 다음과 같은 내용을 중심으로 합니다.
- 수식과 직관적인 이해를 정리하고,
- 어떤 상황에서 어떤 방식이 유리할지 예측하며,
- 앞으로 어떤 실험을 수행할지 계획합니다.
따라서 이 글은 개념과 실험 계획 중심의 글입니다. 실제 벤치마크 결과와 레이어별 수치는, 실험을 마치는 대로 별도의 “실험 결과” 편에서 상세히 다룰 예정입니다.
1. 숫자 표현 방식 간단 복습
양자화를 제대로 이해하려면, 먼저 하드웨어에서 숫자를 어떻게 표현하는지 짚고 넘어가는 것이 좋습니다.
FP32 (32비트 부동소수점)
- 1비트 부호 + 8비트 지수 + 23비트 가수
- 범위: 대략 ±3.4 × 10^38
- 정밀도: 약 7자리 소수
- 메모리: 값당 4바이트
INT8 (8비트 부호 있는 정수)
- 범위: -128 ~ 127
- 메모리: 값당 1바이트
- FP32 대비 4배의 메모리 절감 효과
결국 양자화의 핵심 질문은 이렇게 요약할 수 있습니다.
연속적인 FP32 값을, 제한된 개수의 INT8 값으로 변환하면서 우리가 관심 있는 성능(정확도) 손실을 얼마나 최소화할 수 있을까?
2. 대칭 선형 양자화
2.1. 기본 아이디어
대칭(symmetric) 양자화는 FP32의 0을 INT8의 0에 정확히 대응시키고, 값의 분포가 “0을 중심으로 좌우 대칭”이라고 가정합니다.
텐서 x(가중치 또는 활성화)에 대해, 비트 수를 b라고 하면 (예: INT8은 b = 8)
양수 쪽에서 사용할 수 있는 정수 레벨의 수는 다음과 같습니다.
n_levels = 2^(b - 1) - 1
INT8의 경우 n_levels는 127이 됩니다.
개념적인 구현은 다음과 같이 표현할 수 있습니다.
def quantize_symmetric(x, bits=8):
n_levels = 2 ** (bits - 1) - 1 # INT8의 경우 127
max_abs = torch.max(torch.abs(x))
scale = max_abs / n_levels # Δ (스케일)
x_int = torch.round(x / scale)
x_int = torch.clamp(x_int, -n_levels - 1, n_levels)
return x_int, scale
def dequantize_symmetric(x_int, scale):
return x_int * scale
여기서 scale(Δ)은 “정수 1스텝(step)당 실제 값이 얼마나 변하는지”를 나타내는 척도입니다.
2.2. 토이 예시 (가중치)
가상의 예로, [512, 512] 형태의 가중치 텐서가 있고, 그 값의 범위가
min = -0.15max = 0.18
라고 가정해 보겠습니다. 이 텐서를 INT8 대칭 양자화하면:
n_levels = 127
max_abs = 0.18
Δ = max_abs / n_levels = 0.18 / 127 ≈ 0.00142
이 경우:
- 0이 아닌 가장 작은 표현 단위(해상도)는 약
0.00142가 됩니다. -0.00142 / 2~+0.00142 / 2사이의 값은 0으로 반올림됩니다.- 그 외의 값들은 Δ의 정수 배에 맞춰 반올림됩니다.
이는 실제 실험 데이터가 아닌, 스케일 인자에 대한 감을 잡기 위한 단순 예시입니다.
2.3. 대칭 양자화가 잘 맞는 경우
대칭 양자화는 일반적으로 다음과 같은 경우에 효과적입니다.
- 데이터가 0을 기준으로 비교적 고르게 퍼져 있을 때 (예: BatchNorm / LayerNorm 후의 출력값)
- 분포가 대략 대칭을 이룰 때 (적절히 초기화된 대부분의 레이어 가중치)
- 구현의 단순성을 우선할 때 (Zero-point를 별도로 저장하거나 계산할 필요가 없음)
실제 적용 사례로는 다음과 같은 경우가 자연스럽습니다.
- 컨볼루션 / 선형 레이어의 가중치 양자화
- 정규화(Normalization) 이후의 pre-activation 양자화
3. 활성화가 더 까다로운 이유 (특히 ReLU)
이처럼 깔끔한 “대칭” 가정은 ReLU 활성화처럼 항상 0 이상의 값만 나오는 분포에서는 깨지게 됩니다.
예를 들어, 어떤 ReLU의 출력이 다음과 같다고 가정해 봅시다.
min = 0.0max = 3.24
이 상황에 INT8 대칭 양자화를 그대로 적용하면,
- 실제 데이터는 0 이상인데도, 정수 범위의 절반(-128 ~ -1)이 전혀 활용되지 못합니다.
- 결국 256개의 표현 범위 중 절반가량만 유효하게 사용하는 셈이며,
같은 구간
[0, 3.24]를 표현하는 데 스텝 크기(step size)가 불필요하게 커지는 비효율이 발생합니다.
결과적으로:
- 우리가 실제로 사용하는 값 구간에서의 해상도(resolution) 가 저하되고,
- 양자화 노이즈가 증가하여 최종 정확도 손실로 이어질 수 있습니다.
이러한 문제를 해결하기 위해 비대칭(asymmetric) 양자화가 필요합니다.
4. 비대칭 선형 양자화
4.1. 기본 아이디어
비대칭 양자화는 실제 값의 범위를 정수 범위에 효과적으로 매핑하기 위해 zero-point라는 개념을 도입합니다.
- 스케일
Δ(실수) - 제로 포인트
z(정수)
를 정하고, 개념적인 매핑 수식은 다음과 같습니다.
q = round(x / Δ) + z
x̂ = (q - z) * Δ
파이토치 스타일의 예시 코드는 다음과 같습니다.
def quantize_asymmetric(x, bits=8):
n_levels = 2 ** bits # INT8의 경우 256
x_min, x_max = torch.min(x), torch.max(x)
if x_max == x_min:
return torch.zeros_like(x, dtype=torch.int32), 1.0, 0
scale = (x_max - x_min) / (n_levels - 1)
zero_point = torch.round(-x_min / scale)
x_int = torch.round(x / scale) + zero_point
x_int = torch.clamp(x_int, 0, n_levels - 1)
return x_int, scale, zero_point
def dequantize_asymmetric(x_int, scale, zero_point):
return (x_int - zero_point) * scale
4.2. 토이 예시 (ReLU 출력)
앞서 살펴본 가상의 ReLU 출력:
min = 0.0max = 3.24
에 대해 INT8 비대칭 양자화를 적용하면 다음과 같습니다.
n_levels = 256
Δ = (3.24 - 0.0) / (256 - 1) ≈ 0.0127
z ≈ 0
대칭 방식과 비교하면:
- 전체 256 레벨을
[0, 3.24]구간 내에서 온전히 활용할 수 있습니다. - 같은 구간을 더 세밀하게 표현하므로 해상도가 향상됩니다.
이 역시 직관적인 이해를 돕기 위한 구성 예시이며, 실제 측정값은 아닙니다.
5. 앞으로의 실험 설계 방향
아직 ResNet-50 같은 대형 모델 기준의 정량적인 벤치마크는 진행하지 않았으며, 현재까지는 이론과 기존 연구들을 바탕으로 방향성을 수립하는 단계입니다. 실험은 대략 다음 순서로 진행할 계획입니다.
- 대칭 INT8부터 시작 — 가중치와 일부 활성화(정규화 후 출력 등)에 대칭 양자화 우선 적용. ResNet-50 및 더 작은 모델에서 벤치마크 수행.
- 명백히 비대칭인 활성화에 비대칭 양자화 추가 적용 — ReLU 이후 활성화, Attention의 Softmax 출력,
[0, 1]구간에 분포하는 각종 확률 값. - 핵심 비교 지표 — FP32 대비 Top-1 / Top-5 정확도, 추론 지연시간, 모델 크기, 레이어별 민감도.
예상되는 패턴은 다음과 같습니다.
- 가중치 / 정규화된 신호에는 대칭 양자화가 단순하고 효과적일 것입니다.
- 비대칭적인 활성화에는 비대칭 양자화가 더 유리할 것입니다.
- 이 둘을 혼합 사용하는 하이브리드 전략이 정확도와 효율을 모두 잡는 현실적인 선택이 될 가능성이 큽니다.
실험이 완료되면, 이 섹션은 실제 수치와 그래프, 레이어별 심층 분석 결과로 대체될 예정입니다.
6. 현재까지의 실무적 권장 사항
아직 저희의 실험 결과는 없지만, 이론과 기존 문헌을 토대로 다음과 같은 기본 전략을 고려해볼 수 있습니다.
6.1. 대칭 양자화를 추천하는 경우
- 컨볼루션 / 선형 레이어의 가중치
- BatchNorm / LayerNorm 이후처럼 정규화된 신호
- 구현의 단순성이 중요할 때
6.2. 비대칭 양자화를 추천하는 경우
- ReLU 이후 활성화
- Softmax 출력
[0, 1]범위에 있는 각종 확률 / 점수- 분포가 한쪽으로 심하게 치우친 경우
6.3. 현실적인 혼합 전략
- 가중치: 대칭 INT8 (per-tensor)
- 정규화된 pre-activation: 대칭 INT8
- ReLU 이후 / Softmax / 확률 출력: 비대칭 INT8
- 특히 민감한 레이어(예: 마지막 분류기)는 필요시 FP16/FP32로 유지
7. 구현 시 고민할 지점들
- 캘리브레이션 (Calibration) — min/max 값 추정을 위해 얼마나 많은 샘플이 필요한가? 백분위수 클리핑 vs 단순 min-max?
- Per-tensor vs Per-channel — 채널별 분포 편차가 큰 경우의 정확도 차이.
- PTQ vs QAT — PTQ를 우선 시도하고, 정확도 손실이 크면 QAT로 확장.
구체적인 설정과 벤치마크 결과는 실험 완료 후 별도의 글에서 정리할 예정입니다.
전체적인 연구 방향과 동기, 타임라인이 궁금하다면 신경망 양자화 연구 계획 글을 참고하시면 됩니다.