Contents
- 기본 아이디어
- 부동소수점(FP16/FP32/bfloat16) vs. 정수(INT4/INT8)
- 2의 보수
- 변환 공식
- ex) INT8 (범위: -128 ~ +127)
- ex) INT4 (범위: -8 ~ +7)
- 차이점 (Float vs Integer)
Integer Quantization (e.g., INT8, INT4)
“실수” 값들을 “정수” 값으로 근사해서 저장하는 방식
1. 기본 아이디어
모델 weight, activation은 원래 실수(float) 값
- 예: \([-2.35, -0.5, 0.0, 1.25, 3.8]\)
하지만 정수 타입(INT8, INT4)은 실수를 직접 표현 못함
\(\rightarrow\) 그래서 “scale factor (스케일)”라는 변환 비율을 사용하여, 실수를 정수로 mapping!
2. 부동소수점(FP16/FP32/bfloat16) vs. 정수(INT4/INT8)
표현 방식 자체가 달라서 공식도 다름!
1) 정수 (two’s complement)
n비트 signed 정수의 값
-
\(V=-b_{n-1}\,2^{\,n-1}+\sum_{i=0}^{n-2} b_i\,2^{\,i}\).
-
범위: \([-2^{n-1},\,2^{n-1}-1]\)
- 예) INT4(n=4): [-8,7]
- 예) INT8(n=8): [-128,127]
2) 부동소수점 (IEEE 754)
비트 구성이 부호 s / 지수 e / 가수(분수) f 로 나뉨.
정규화 수(normalized):
-
\(V = (-1)^s \times \bigl(1+\sum_{i=1}^{m} f_i 2^{-i}\bigr)\times 2^{(e-\text{bias})}\).
- FP32: s1/e8/f23, bias=127
- FP16: s1/e5/f10, bias=15
- bfloat16: s1/e8/f7, bias=127
Summary
- 정수: \(V=-b_{n-1}2^{n-1}+\cdots\)
- 부동소수점: \(V=(-1)^s \times (1.f)\times 2^{(e-\text{bias})}\) (+ subnormal/특수값 규칙)
3. 2의 보수
\(V = -b_{n-1} \cdot 2^{n-1} + \sum_{i=0}^{n-2} b_i \cdot 2^i\).
왜 그렇게 생겼는지를 직관적으로 !!
(1) 2의 보수
컴퓨터는 음수를 다루기 위해 2의 보수 방식을 사용
- 가장 왼쪽 비트(MSB, sign bit)가 0이면 양수
- 가장 왼쪽 비트(MSB, sign bit)가 1이면 음수
\(\rightarrow\) 이때, MSB 하나만으로 전체 부호를 뒤집는 효과!
(2) 수식 해석
\(V = -b_{n-1} \cdot 2^{n-1} + \sum_{i=0}^{n-2} b_i \cdot 2^i\).
[1번째 term: \(-b_{n-1} \cdot 2^{n-1}\)]
-
\(b_{n-1}\): 최상위 비트(MSB) → 음수 가중치를 가짐
-
0이면 영향 없음
-
1이면 \(-2^{n-1}\)을 더함 (즉, 큰 음수로 시작)
-
[2번째 term: \(\sum_{i=0}^{n-2} b_i \cdot 2^i\)]
- 나머지 비트 → 일반 이진수 해석 (양수 부분)
요약
- MSB가 0이면:
- 단순한 양수 범위 (\(0 ~ 2^{n-1}-1\))
- MSB가 1이면:
- “큰 음수 값”을 먼저 찍고
- 거기에 나머지 비트로 보정 → 음수 범위 ( \(-2^{n-1} ~ -1\) )
- 이 공식은 “MSB 하나는 음수 덩어리(\(-2^(n-1)\))로, 나머지는 양수 조각들로” 해석하는 규칙.
- 그래서 전체가 음수와 양수로 절반씩 나뉘어 표현 가능!
(3) Example: INT4 (n=4)
\(V = -b_3 \cdot 2^3 + (b_2 \cdot 2^2 + b_1 \cdot 2^1 + b_0 \cdot 2^0)\).
- 0111 → \(-0 + (4+2+1)=7\)
- 1000 → \((-1 \cdot 8) + 0 = -8\)
- 1111 → \((-1 \cdot 8) + (4+2+1) = -1\)
\(\rightarrow\) 이렇게 해서 [-8,7] 범위가 나옴!!
4. 변환 공식
Notation
- scale = (실수 값 범위) / (정수 표현 가능한 최대값)
- round: 정수 자리로 반올림
[변환] 실수 \(x\) → 정수 \(q\):
- \(q = \text{round}\left(\frac{x}{\text{scale}}\right)\).
[복원] 정수 \(q\) → (근사) 실수 \(\hat{x}\):
- \(\hat{x} = q \times \text{scale}\).
5. ex) INT8 (범위: -128 ~ +127)
왜 \(2^8=256\) 이 아니라 \(2^7=128\)인지?
\(\rightarrow\) “양수/음수” 반반 나눠주기 위해!
Details) -128~127인 이유?
- 가장 작은 값: 1000 0000 → -128
- 앞의 1 = “음수”를 나타냄
- 가장 큰 값: 0111 1111 → +127
- 앞의 0 = “양수”를 나타냄
Example)
실수 weight: \([-2.35, -0.5, 0.0, 1.25, 3.8]\)
- scale = \(0.03\) (가정)
- \(x=-2.35\).
- 5개의 element 변환
- -2.35 / 0.03 ≈ -78
- -0.5 / 0.03 ≈ -17
- 0.0 / 0.03 = 0
- 1.25 / 0.03 ≈ 42
- 3.8 / 0.03 ≈ 127
-
Results
-
저장 (INT8): \([-78, -17, 0, 42, 127]\)
- 복원: \([-2.34, -0.51, 0.0, 1.26, 3.81]\)
- 원본: \([-2.35, -0.5, 0.0, 1.25, 3.8]\)
-
6. ex) INT4 (범위: -8 ~ +7)
실수 weight: \([-2.35, -0.5, 0.0, 1.25, 3.8]\)
- scale = \(0.5\) (가정)
- 변환:
- -2.35 / 0.5 ≈ -5 → 저장: -5
- -0.5 / 0.5 ≈ -1 → 저장: -1
- 0.0 → 0
- 1.25 / 0.5 ≈ 3 → 저장: 3
- 3.8 / 0.5 ≈ 8 → 저장: 7 (최댓값 초과 → 클리핑)
Results
-
저장된 값(INT4): \([-5, -1, 0, 3, 7]\)
-
복원하면: \([-2.5, -0.5, 0.0, 1.5, 3.5]\) (손실 있음)
7. 차이점 (Float vs Integer)
- FP: 지수 + 유효숫자를 써서 아주 넓은 범위를 다룸.
- INT quantization: 범위는 좁지만, scale factor로 실수 범위를 잘라서 정수 격자에 맞춰 저장.
- INT4, INT8일수록 표현 가능한 격자(grid)가 거칠어져서 손실이 커짐.