int8 양자화는 잘 됐습니다. 벤치마크 점수가 0.3%p 떨어지고 메모리는 4분의 1이 됐습니다. 같은 파이프라인에서 비트만 4로 내리자 점수가 절반 아래로 떨어졌습니다.
여기서 보통 도구를 바꿔 봅니다 — 캘리브레이션 데이터를 늘리고, GPTQ를 써 보고, 그룹 크기를 조정합니다. 그런데 왜 8에서 4로 갈 때 그 자리에서 무너지는지는 그 어느 것도 설명하지 않습니다.
설명은 계산으로 나옵니다. 양자화 오차의 크기는 비트 수와 값의 분포만으로 결정되고, 그 오차가 층의 출력에서 얼마나 커지는지도 한 줄로 예측됩니다. 이 글은 그 계산을 세웁니다. 기법과 도구는 양자화 기초와 AWQ·GPTQ 비교가 맡고, 여기서는 오차의 수학만 봅니다.
격자 사상과 스텝 크기
양자화는 실수 구간을 유한한 격자에 사상하는 일입니다. 비트면 격자가 개이고, 담을 구간이 일 때
가 격자 사이의 간격입니다. 이 값을 스텝 크기라고 부릅니다. 분모가 이 아니라 인 것은 격자가 개면 그 사이의 간격은 개이기 때문입니다.
값 하나를 격자에 올리는 것은 반올림입니다.
오차 는 를 톱니로 오갑니다. 반올림이 가장 가까운 격자로 가므로 오차가 간격의 절반을 넘을 수 없고, 한 칸 안에서는 왼쪽 끝의 에서 오른쪽 끝의 까지 선형으로 훑습니다.
오차의 분산은 Δ²/12
톱니 모양을 보면 다음 단계가 나옵니다. 입력이 격자 간격에 견줘 넓게 퍼져 있으면 오차는 위의 균등분포로 봐도 됩니다. 그러면 분산이 적분 한 줄로 나옵니다.
평균이 0이라 이고, 밀도가 로 일정하니 그냥 을 적분하면 됩니다. 가 양자화 오차의 분산이고, 이 글의 나머지가 전부 이 한 값에서 나옵니다.
정말 그런지 200만 개로 재 봤습니다.
| 비트 | 오차 분산 (실측) | 최대 오차 | |||
|---|---|---|---|---|---|
| 8 | 0.007843 | 5.125 × 10⁻⁶ | 5.126 × 10⁻⁶ | 0.00392 | 0.00392 |
| 4 | 0.133333 | 1.481 × 10⁻³ | 1.481 × 10⁻³ | 0.06667 | 0.06667 |
| 3 | 0.285714 | 6.806 × 10⁻³ | 6.803 × 10⁻³ | 0.14286 | 0.14286 |
소수 넷째 자리까지 맞습니다. 최대 오차도 정확히 입니다.
이 근사가 깨지는 자리도 분명합니다. 입력이 격자 간격보다 좁게 몰려 있으면 오차가 균등하지 않고 격자 위치에 따라 편향됩니다. 비트가 아주 적거나(2비트) 값이 한 격자 근처에 모여 있는 경우가 그렇고, 뒤에서 2비트가 예측과 어긋나는 것을 보게 됩니다.
비트 하나가 6.02dB다
오차의 절대 크기는 값의 규모에 따라 다르므로, 비교하려면 신호와의 비를 봐야 합니다. SNR(signal-to-noise ratio, 신호 대 잡음비)은 신호의 분산을 오차의 분산으로 나눈 값이고 데시벨로 적습니다.
여기에 를 대입합니다. 데이터의 최댓값이 표준편차의 배라고 두면 — — 대칭 양자화에서 이므로
비트 하나가 6.02dB입니다. 가 약분돼 사라진 것에 주목할 만합니다 — 값을 몇 배로 키우든 SNR은 안 변합니다. 남은 것은 비트 수 와 분포의 꼬리 길이 뿐입니다.
표준정규분포 200만 개(, )로 대조했습니다.
| 비트 | 실측 SNR | 예측 | 차이 |
|---|---|---|---|
| 8 | 38.01 dB | 38.07 dB | −0.06 |
| 6 | 25.75 dB | 26.03 dB | −0.27 |
| 4 | 12.83 dB | 13.99 dB | −1.16 |
| 3 | 5.49 dB | 7.97 dB | −2.48 |
8비트와 6비트는 0.3dB 안쪽으로 맞고, 비트가 줄수록 실측이 예측보다 나쁩니다. 앞에서 말한 균등분포 가정이 무너지는 자리입니다 — 격자가 성기면 정규분포의 봉우리가 한 칸 안에 통째로 들어가 오차가 균등하지 않게 됩니다.
항이 실무적으로 중요합니다. 꼬리가 길수록 SNR이 나빠지고, 그 손해가 비트 손실로 환산됩니다. 가 두 배가 되면 dB를 잃는데, 이것은 정확히 비트 하나를 버리는 것과 같습니다. 클리핑(꼬리를 잘라 를 줄이는 것)이 손해처럼 보이면서도 이득인 이유가 여기 있습니다 — 잘린 소수의 값에서 큰 오차를 감수하고 나머지 전부의 를 줄입니다.
대칭인가 비대칭인가
지금까지 를 데이터의 최소·최대로 잡았습니다. 이것이 비대칭 양자화입니다. 0이 격자의 어디에 놓일지 모르므로 「0에 해당하는 정수」를 따로 저장하는데, 이것을 영점(zero point)이라고 합니다.
대칭 양자화는 ()으로 잡아 0이 격자의 정확히 가운데에 오게 합니다. 영점이 항상 0이라 저장할 것이 하나 줄고, 정수 연산에서 영점 보정 항이 사라져 커널이 단순해집니다.
어느 쪽이 나은지는 분포가 얼마나 치우쳤는가 하나로 갈립니다.
| 분포 | 비트 | 비대칭 | 비대칭 MSE | 대칭 | 대칭 MSE | MSE 비 |
|---|---|---|---|---|---|---|
| 0 대칭 (가중치) | 8 | 0.03508 | 1.03 × 10⁻⁴ | 0.03602 | 1.08 × 10⁻⁴ | 1.06배 |
| 0 대칭 (가중치) | 4 | 0.59628 | 2.97 × 10⁻² | 0.65352 | 3.57 × 10⁻² | 1.20배 |
| 한쪽 치우침 (ReLU 출력) | 8 | 0.01844 | 1.75 × 10⁻⁵ | 0.03703 | 7.08 × 10⁻⁵ | 4.04배 |
| 한쪽 치우침 (ReLU 출력) | 4 | 0.31351 | 5.09 × 10⁻³ | 0.67182 | 2.33 × 10⁻² | 4.58배 |
0 근처로 퍼진 가중치에서는 차이가 1.2배뿐이라 커널이 단순한 대칭 쪽을 씁니다. ReLU를 지난 활성값처럼 한쪽만 나오는 분포에서는 대칭 격자가 음수 쪽에 칸의 절반을 버려 오차가 4.6배가 됩니다. 「가중치는 대칭, 활성값은 비대칭」이라는 실무의 관행이 이 표에서 나옵니다.
MSE 비가 4배 남짓인 것도 우연이 아닙니다. 대칭이 범위를 두 배로 잡으면 가 두 배가 되고, 오차 분산은 에 비례하니 네 배가 됩니다.
이상치 하나가 나머지의 비트를 먹는다
가 로 정해진다는 것이 이 방식의 급소입니다. 값 4,096개 중 하나만 크면 나머지 4,095개의 격자 간격이 그것에 끌려갑니다.
4비트 대칭 양자화에서, 표준편차 0.5짜리 값 4,096개 중 첫 번째만 크게 바꿔 가며 쟀습니다.
| 이상치 | 범위 | 정상값이 실제로 쓰는 비트 | 정상값 MSE | 상대오차 | |
|---|---|---|---|---|---|
| 없음 | 1.75 | 0.2494 | 3.91 | 5.12 × 10⁻³ | 0.142 |
| 2 | 2.00 | 0.2857 | 3.70 | 6.76 × 10⁻³ | 0.163 |
| 5 | 5.00 | 0.7143 | 2.32 | 4.16 × 10⁻² | 0.404 |
| 20 | 20.00 | 2.8571 | 1.58 | 2.51 × 10⁻¹ | 0.993 |
| 100 | 100.00 | 14.2857 | 0.00 | 2.55 × 10⁻¹ | 1.000 |
「실제로 쓰는 비트」는 정상값 4,095개가 실제로 차지한 격자 칸 수의 로그입니다. 4비트를 할당했는데 이상치가 20이면 1.58비트만 쓰고, 100이면 0비트 — 모든 정상값이 같은 칸(0)으로 사상됩니다. 상대오차 1.000은 값을 통째로 잃었다는 뜻입니다.
이것이 LLM 양자화에서 「이상치 채널」이 문제가 되는 이유입니다. 트랜스포머의 활성값에는 몇 개 차원에서만 다른 차원보다 수십 배 큰 값이 규칙적으로 나타나는데, 텐서 전체에 스케일 하나를 쓰면 그 몇 개가 나머지 수천 개의 비트를 먹습니다.
처방은 스케일을 나누는 것입니다. 이상치가 특정 채널에 몰려 있다면 채널마다 를 따로 두면 됩니다.
가중치에서 17번 채널만 40배 크게 만들어 두고 두 방식을 비교했습니다.
| 비트 | 텐서 전체에 스케일 하나 | 채널마다 스케일 | 차이 |
|---|---|---|---|
| 8 | 8.77 × 10⁻³ | 4.19 × 10⁻⁵ | 209배 |
| 4 | 2.57 × 10⁻¹ | 1.24 × 10⁻² | 21배 |
채널마다 스케일 하나(fp16 두 바이트)를 더 저장하는 값으로 오차가 20배에서 200배 줄었습니다. 채널이 256개면 추가 저장량은 512바이트, 원래 가중치의 1.6%입니다. 그룹 단위 양자화(채널을 다시 128개씩 묶어 그룹마다 스케일을 두는 것)가 실무의 기본값이 된 이유가 이 표입니다.
오차 예산으로 무너지는 지점을 미리 계산하기
서두의 질문으로 돌아갑니다. int4에서 무너질지를 돌려 보기 전에 알 수 있을까요.
선형층 에서 를 양자화하면 이고, 출력의 오차는 입니다. 의 성분이 분산 로 독립이라고 보면, 출력 오차의 크기와 출력 자체의 크기가 각각
이므로 과 가 통째로 약분됩니다. 남는 것은
한 줄이고, 이것을 오차 예산이라고 부르겠습니다. 필요한 값은 가중치의 표준편차와 최댓값 둘뿐이라 모델을 돌리지 않고 계산할 수 있습니다.
선형층에서 예산과 실측을 대조했습니다.
| 비트 | 예산 | 실제로 잰 상대오차 |
|---|---|---|
| 8 | 0.0106 | 0.0103 |
| 6 | 0.0436 | 0.0438 |
| 5 | 0.0901 | 0.0910 |
| 4 | 0.1931 | 0.1814 |
| 3 | 0.4505 | 0.4403 |
| 2 | 1.3516 | 0.9730 |
5비트까지는 소수 셋째 자리까지 맞습니다. 2비트에서만 예산이 비관적인데, 이 지점에서는 오차가 신호만큼 커져 「독립적인 잡음」이라는 전제가 무너지기 때문입니다(양자화가 값을 아예 0으로 뭉개는 쪽으로 편향됩니다).
표에서 읽히는 것이 서두의 질문에 대한 답입니다. int8은 출력을 1% 흔들고 int4는 18% 흔듭니다. 층 하나에서 18%면 층 서른 개를 지나며 어떻게 될지는 그 층들이 오차를 얼마나 증폭하느냐에 달렸지만, 1%와 18%가 같은 결과를 낼 수 없다는 것은 분명합니다. 8과 4 사이가 아니라 5와 4 사이가 절벽이라는 것도 이 표가 알려 줍니다 — 9%에서 18%로 두 배가 되는 자리입니다.
그리고 예산 식의 분자에 가 있으므로, 를 줄이는 모든 조작이 그대로 예산을 줄입니다. 채널별 스케일, 그룹 양자화, 클리핑이 전부 를 낮춰 를 줄이는 일이고, 그것이 얼마나 도움이 될지도 같은 식에 넣어 미리 계산할 수 있습니다.
정리
- 양자화의 스텝 크기는 이고, 반올림 오차는 를 톱니로 오간다.
- 오차를 균등분포로 보면 분산이 다. 적분 한 줄로 나오고, 200만 개 실측과 소수 넷째 자리까지 맞았다. 이 근사는 격자가 아주 성길 때(2~3비트) 깨진다.
- SNR로 옮기면 다(). 비트 하나가 6.02dB이고, 신호의 크기 는 약분돼 사라진다.
- 꼬리가 두 배로 길어지면 비트 하나를 버리는 것과 같다(6.02dB). 클리핑이 손해처럼 보이면서 이득인 이유다.
- 대칭이냐 비대칭이냐는 분포가 치우쳤는지 하나로 갈린다. 0 대칭인 가중치에서는 차이가 1.2배지만 ReLU 출력에서는 4.6배다 — 대칭 격자가 데이터 없는 음수 쪽에 칸의 절반을 버리기 때문이다.
- 가 로 정해지므로 이상치 하나가 나머지 전부의 격자를 늘린다. 4비트에서 이상치가 20이면 정상값이 실제로 쓰는 비트는 1.58, 100이면 0이다.
- 처방은 스케일을 나누는 것이다. 채널마다 스케일을 두니 오차가 8비트에서 209배, 4비트에서 21배 줄었다. 추가 저장은 가중치의 1.6%다.
- 오차 예산 은 층 출력의 상대오차를 모델을 돌리지 않고 예측한다. 5비트까지 소수 셋째 자리까지 맞았다.
- 그 예산이 말하는 것 — int8은 출력을 1% 흔들고 int4는 18% 흔든다. 절벽은 8과 4 사이가 아니라 5와 4 사이다.
읽어주셔서 감사합니다. 😊

