이전 포스트에서 신경망 양자화 기술에 대한 연구 계획을 설명했습니다. 오늘은 두 가지 기본적인 양자화 방식인 대칭 선형 양자화와 비대칭 선형 양자화에 대해 자세히 알아보겠습니다.
양자화가 중요한 이유
기술적인 세부 사항을 살펴보기 전에, 효율적인 AI 모델 배포에 양자화가 왜 중요한지 간략히 설명하겠습니다:
- 메모리 사용량 감소: 32비트 부동소수점 가중치를 8비트 또는 4비트 정수로 변환하면 모델 크기를 4-8배 줄일 수 있습니다.
- 추론 속도 향상: 정수 연산은 부동소수점 연산보다 계산 비용이 크게 낮습니다.
- 전력 효율성: 낮은 정밀도 계산은 전력 소비가 적어 배터리 제약이 있는 엣지 디바이스에 중요합니다.
- 하드웨어 호환성: 많은 특수 AI 가속기는 정수 연산에 최적화되어 있습니다.
기초: 비트, 바이트 및 숫자 표현
양자화를 완전히 이해하려면 컴퓨터가 숫자를 어떻게 표현하는지부터 알아야 합니다:
- 비트: 가장 기본적인 정보 단위로, 0 또는 1을 나타냅니다.
- 바이트: 8개의 비트로, 256가지 다른 값(0-255)을 표현할 수 있습니다.
- 정수: 부호 없는 정수(0부터 2^n-1까지) 또는 부호 있는 정수(-2^(n-1)부터 2^(n-1)-1까지)가 있습니다.
- 부동소수점: 부호 비트, 지수, 가수(또는 유효숫자)를 사용해 실수를 표현합니다.
딥러닝에서는 주로 다음 요소들을 다룹니다:
- 가중치: 순방향 전파 과정에서 입력에 곱해지는 학습 가능한 매개변수
- 활성화: 입력과 가중치 간의 계산 결과인 각 레이어의 출력
- 편향: 활성화 함수를 이동시키기 위해 출력에 더해지는 상수 값
대부분의 신경망은 32비트 부동소수점(FP32) 정밀도로 학습되는데, 이는 높은 정확도의 장점이 있지만 많은 메모리와 계산 자원이 필요합니다.
양자화의 기본 원리
양자화의 핵심은 연속적인 부동소수점 값을 이산적인 정수 값 집합으로 매핑하는 것입니다. 이 과정에서 필연적으로 일부 근사 오차가 발생하지만, 올바르게 수행하면 모델 정확도에 미치는 영향을 최소화하면서 상당한 효율성 향상을 얻을 수 있습니다.
양자화의 핵심 과제는 정보 손실을 최소화하는 부동소수점과 정수 값 사이의 최적 매핑을 결정하는 것입니다.
대칭 선형 양자화
대칭 선형 양자화는 제로 포인트를 0으로 고정하여 부동소수점 0이 정확히 정수 0에 매핑되도록 합니다. 이 방식은 간결하고 계산 효율이 높습니다.
수학적 공식화
부동소수점 값 x
를 양자화된 값 xQ
로 매핑하는 과정:
xint = round(x / Δ)
xQ = clamp(-Nlevels/2, Nlevels/2 - 1, xint) // 부호 있는 정수의 경우
여기서:
Δ
(scale): 인접한 표현 가능한 값 사이의 단계 크기Nlevels
: 표현 가능한 레벨 수(8비트의 경우 256)clamp(a, b, x)
: x를 범위 [a, b]로 제한하는 함수
역양자화(부동소수점으로 다시 변환):
xfloat = xQ * Δ
계산 예시
[-4.0, 4.0] 범위의 값을 가진 가중치 행렬을 8비트 부호 있는 정수(-128부터 127까지)로 양자화하는 구체적인 예를 살펴보겠습니다:
- 스케일 계수 계산:
Δ = max(abs(-4.0), abs(4.0)) / 127 = 4.0 / 127 ≈ 0.0315 - 특정 값 양자화:
- -4.0의 경우: xint = round(-4.0 / 0.0315) = -127, xQ = clamp(-128, 127, -127) = -127
- 0의 경우: xint = round(0 / 0.0315) = 0, xQ = clamp(-128, 127, 0) = 0
- 4.0의 경우: xint = round(4.0 / 0.0315) = 127, xQ = clamp(-128, 127, 127) = 127
- 역양자화 검증:
- -127 → -127 × 0.0315 = -4.0005 (원래 값: -4.0)
- 0 → 0 × 0.0315 = 0 (원래 값: 0)
- 127 → 127 × 0.0315 = 4.0005 (원래 값: 4.0)
이는 대칭 양자화가 0을 정확히 보존하고 값 범위의 극단에서도 좋은 근사치를 제공함을 보여줍니다.
비대칭 선형 양자화
대칭 양자화는 0을 중심으로 분포된 가중치에는 잘 작동하지만, 많은 활성화 함수(ReLU 등)는 주로 양수 출력을 생성합니다. 이러한 비대칭 분포에서는 비대칭 양자화가 정수 값의 전체 범위를 활용하여 더 나은 결과를 제공할 수 있습니다.
수학적 공식화
비대칭 양자화:
xint = round(x / Δ) + z
xQ = clamp(0, Nlevels - 1, xint) // 부호 없는 정수의 경우
여기서:
z
(zero-point): 부동소수점 0을 나타내는 정수 값Δ
(scale): (max(x) - min(x)) / (Nlevels - 1)
역양자화:
xfloat = (xQ - z) * Δ
계산 예시
[-2.5, 1.8] 범위의 값을 가진 가중치 행렬을 8비트 부호 없는 정수(0부터 255까지)로 양자화해 보겠습니다:
- 스케일과 제로 포인트 계산:
- Δ = (1.8 - (-2.5)) / (255 - 0) = 4.3 / 255 ≈ 0.0169
- z = round(0 - (-2.5) / 0.0169) = round(147.93) = 148
- 특정 값 양자화:
- -2.5의 경우: xint = round(-2.5 / 0.0169) + 148 = -148 + 148 = 0, xQ = clamp(0, 255, 0) = 0
- 0의 경우: xint = round(0 / 0.0169) + 148 = 148, xQ = clamp(0, 255, 148) = 148
- 1.8의 경우: xint = round(1.8 / 0.0169) + 148 = 107 + 148 = 255, xQ = clamp(0, 255, 255) = 255
- 역양자화 검증:
- 0 → (0 - 148) × 0.0169 = -2.5012 (원래 값: -2.5)
- 148 → (148 - 148) × 0.0169 = 0 (원래 값: 0)
- 255 → (255 - 148) × 0.0169 = 1.8083 (원래 값: 1.8)
대칭 및 비대칭 양자화 비교
이 두 접근 방식의 근본적인 차이점은 제로 포인트 처리 방식에 있습니다:
- 대칭 양자화: FP32의 0이 INT의 0에 직접 매핑됩니다.
- 비대칭 양자화: FP32의 0이 계산된 정수 값(예시에서는 148)에 매핑됩니다.
각 접근 방식을 사용해야 하는 경우:
- 대칭 양자화: 일반적으로 0을 중심으로 분포된 가중치에 더 적합합니다.
- 비대칭 양자화: 주로 양수 값을 가진 비대칭 분포를 가진 활성화(특히 ReLU 레이어 이후)에 더 적합합니다.
구현 시 고려 사항
실제로 양자화를 구현할 때 몇 가지 중요한 요소를 고려해야 합니다:
- 텐서별 vs. 채널별 양자화: 각 채널에 대해 다른 양자화 매개변수를 적용하면 텐서 전체에 동일한 매개변수를 사용하는 것보다 더 나은 결과를 얻을 수 있습니다.
- 양자화 인식 훈련 vs. 훈련 후 양자화: 학습 중에 양자화 효과를 반영하면 학습 후 양자화에 비해 정확도 손실을 줄일 수 있습니다.
- 하드웨어 제약: 일부 하드웨어 가속기는 특정 양자화 방식이나 비트 폭만 지원할 수 있습니다.
- 동적 범위: 값의 분포를 신중하게 분석하면 중요한 정보를 보존하기 위한 최적의 양자화 매개변수를 설정하는 데 도움이 됩니다.
다음 단계
향후 작업에서는 MobileViT 모델에 대칭 및 비대칭 양자화를 모두 구현하고 다양한 비트 폭(FP32, INT16, INT8, INT4)에서 성능을 비교할 예정입니다. 다음과 같은 기준으로 평가할 계획입니다:
- 정확도 유지
- 모델 크기 감소
- 추론 속도 향상
- 메모리 사용량
구현 세부 사항과 실험 결과는 다음 포스트에서 공유하겠습니다 !