1. 개요[편집]
| 신경망 양자화 Neural Network Quantization | |
|---|---|
| 하는 일 | 가중치·활성값을 FP32 대신 INT8/INT4 정수 격자에 올린다 |
| 기본 사상 | 아핀(비대칭) 또는 대칭 균일 양자화 |
| 스케일 단위 | 텐서 단위 · 출력 채널 단위 · 그룹 단위(g=128 국룰) |
| 두 갈래 | 학습 후 양자화(PTQ) · 양자화 인지 학습(QAT) |
| QAT의 핵심 트릭 | 직통 추정기(STE) — 반올림의 0 기울기를 항등으로 갈아 끼움 |
| 실제 이득 | 메모리·대역폭 4배(INT8), 정수 연산 처리량 증가 |
| 최대 난적 | 대형 언어모형 활성값의 이상치 채널 |
신경망 양자화는 신경망의 가중치와 활성값을 32비트 부동소수점 대신 8비트·4비트 정수 격자 위의 값으로 표현해, 메모리와 연산 비용을 줄이는 모형 압축 기법이다. 파라미터 하나가 4바이트에서 1바이트가 되면 모형 파일과 메모리 대역폭이 그대로 4분의 1이 되고, 정수 곱셈-누산 유닛은 부동소수점보다 훨씬 싸고 빠르다. 지식 증류·신경망 가지치기와 함께 배포 파이프라인의 표준 3종 세트를 이룬다.
이름이 겹치지만 벡터 양자화와는 다른 물건이다. 벡터 양자화는 데이터 벡터를 학습된 코드북의 인덱스로 바꾸는 손실 압축이고, 여기서 말하는 양자화는 스칼라 하나하나를 균일 격자에 반올림하는 것이다. 코드북도, 최근접 탐색도, 로이드 반복도 없다. 굳이 관계를 따지자면 신경망 양자화는 “코드북이 등간격으로 고정된 1차원 스칼라 양자화”이며, 실제로 곱 양자화 방식으로 가중치를 압축하는 계열도 따로 존재한다. 다만 그쪽은 정수 연산 커널의 이득을 못 받으므로 목적이 다르다 — 균일 양자화가 이기는 이유는 정밀도가 아니라 하드웨어가 그 격자를 직접 계산할 줄 알기 때문이다.1
2. 균일 양자화의 산술[편집]
비트 폭 , 실수 구간 를 정수 격자로 보내는 아핀(비대칭) 양자화는 스케일 와 영점 로 정의된다.
대칭 양자화는 으로 못 박고 을 쓴다. 표현 범위를 반쯤 낭비하는 것처럼 보이는데도 가중치에는 거의 항상 대칭을 쓰는 이유는 행렬곱을 전개해 보면 나온다.
이면 항 하나가 통째로 사라지고, 남는 보정항은 미리 계산해 편향에 접어 넣을 수 있다. 반면 활성값은 ReLU 뒤에서 한쪽으로만 분포하므로 비대칭이 유리하다. 가중치는 대칭, 활성값은 비대칭이 실무 국룰인 것은 우아한 이유 때문이 아니라 이 전개식 때문이다.
3. 스케일을 어디까지 쪼갤 것인가[편집]
스케일 하나를 텐서 전체에 쓰는 것이 텐서 단위(per-tensor), 출력 채널마다 다른 를 쓰는 것이 채널 단위(per-channel)다. 합성곱 필터의 노름은 채널마다 한두 자릿수씩 차이 나는 것이 보통이라, 텐서 하나로 묶으면 작은 채널이 INT8 격자에서 서너 개 값으로 뭉개진다. 채널 단위로 쪼개면 이 문제가 거의 사라지고, 비용은 스케일 벡터 하나(FP32 개)뿐이다.
그런데 아무 축이나 쪼갤 수는 없다. 출력 채널 스케일이 허용되는 이유는 그것이 축약 인덱스 바깥에 있어 합 밖으로 빠져나오기 때문이다.
입력 채널(축약 축)마다 다른 스케일을 주면 이 인수분해가 깨져서 정수 누산기 안에서 실수 곱을 해야 한다. 활성값 쪽에서 토큰 단위(per-token) 스케일이 허용되는 것도 같은 이유다. 뒤에 나올 SmoothQuant가 “축약 축 방향 스케일을 앞 레이어에 접어 넣는” 우회를 하는 것은 이 제약을 정면으로 돌파할 수 없기 때문이다. 절충안으로 축약 축을 128개씩 끊어 그룹마다 스케일을 두는 그룹 단위 양자화가 널리 쓰이는데, 이건 부분합을 그룹 경계에서 한 번씩 실수로 되돌리는 대가를 치른다. INT4 언어모형에서 g=128 이 사실상 표준값인 것은 그 대가와 정확도의 타협점이 거기 있어서다.
4. 클리핑 임계 — 자를 것인가 뭉갤 것인가[편집]
를 관측 최댓값으로 잡으면 이상치 하나가 스케일 전체를 늘려 나머지 99.9%를 몇 개 격자점에 몰아넣는다. 그래서 일부러 좁게 잘라 클리핑 오차와 반올림 오차를 맞바꾼다. 임계를 라 하면 반올림 오차는 격자 간격 에 비례해 커지고, 클리핑 오차는 꼬리 확률질량에 비례해 작아진다. 최적값은 둘의 합이 최소가 되는 지점이다.
실무에서 임계를 고르는 방법은 셋이다.
- MSE 최소화. 위 식을 보정용 표본 히스토그램 위에서 직접 격자 탐색한다. 가장 정직하고 가장 흔하다.
- 백분위수. 99.99% 지점 같은 값으로 자른다. 싸고 대체로 무난하지만 분포가 두꺼운 꼬리를 가지면 임의적이다.
- KL(엔트로피) 기준. FP32 히스토그램 와 임계 로 양자화해 다시 펼친 히스토그램 사이의 쿨백-라이블러 발산을 최소화한다. TensorRT의 보정 방식으로 알려지면서 널리 퍼졌다. 제곱오차 대신 정보량 손실을 재는 셈인데, 분류 정확도와의 상관이 MSE보다 특별히 높다는 근거는 사실 약하다.
반올림 자체도 자명하지 않다. AdaRound(2020)는 층별 출력 오차 를 기준으로 보면 각 가중치를 위로 올릴지 내릴지가 결합된 이산 최적화이며 최근접 반올림이 최적이 아님을 보였다. 실제로 소량의 보정 데이터만으로 올림/내림을 학습시키면 INT4에서 수 %p씩 회복된다. “반올림은 반올림이지”라는 직관이 깨지는 지점.
5. PTQ와 QAT[편집]
학습 후 양자화(PTQ)는 이미 학습된 FP32 모형에 보정용 데이터 수백~수천 개만 흘려 통계를 잡고 스케일을 정한다. 재학습이 없으니 몇 분이면 끝나고, 학습 데이터·학습 코드가 없어도 된다. INT8에서는 대부분의 합성곱 신경망·트랜스포머가 PTQ만으로 정확도 손실 1%p 이내에 들어온다.
양자화 인지 학습(QAT)은 순전파에 가짜 양자화(fake quantization) 노드를 끼워 넣고 학습을 계속한다. 모형이 격자의 존재를 알고 그에 맞는 해로 이동하므로 INT4 이하나 정확도 요구가 빡빡한 경우에 필수가 된다. 문제는 명백하다 — 반올림 함수의 도함수는 거의 모든 곳에서 0이라 역전파가 즉시 죽는다.
처방이 직통 추정기(straight-through estimator, STE)다. 순전파는 양자화된 값을 쓰고, 역전파에서는 양자화 연산의 야코비안을 항등으로 선언한다.
클리핑 범위 밖에서는 0을 주는 것(clipped STE)이 중요하다. 그렇지 않으면 이미 포화된 가중치가 계속 밖으로 밀려 나간다. 수학적으로 이건 근사도 아니고 그냥 다른 함수의 기울기를 갖다 쓰는 것이라 수렴 보장이 없지만, 지난 10년간 안 되는 걸 본 사람이 드물다는 이유로 표준이 됐다.2 여기서 한 걸음 더 나간 것이 LSQ(Learned Step Size Quantization, 2020)로, 스케일 자체를 학습 파라미터로 두고 를 STE로 흘린다. 임계를 사람이 고르는 대신 손실이 고르게 하는 것이며, 저비트에서 눈에 띄게 유리하다. 벡터 양자화 문서에 나오는 VQ-VAE의 직통 추정량과 정확히 같은 발상이 다른 격자 위에서 반복되는 셈이다.
6. 대형 언어모형과 이상치 채널[편집]
여기서 판이 바뀐다. 모형이 커지면 활성값 텐서의 특정 은닉 차원 몇 개가 나머지보다 한두 자릿수 큰 값을 가지는 현상이 나타나고, 이 이상치는 무작위가 아니라 채널이 고정되어 있으며 모든 토큰과 모든 층에서 같은 차원에 몰린다. 대략 60억 파라미터 부근부터 뚜렷해진다는 것이 LLM.int8()(2022)의 관측이었다. 텐서 단위 스케일은 이 몇 개 차원에 인질로 잡히고, 하필 축약 축이라 채널 단위 스케일로 나눌 수도 없다. 활성값 양자화가 어려운 이유가 여기 다 있다.
우회로가 세 갈래로 갈렸다.
-
혼합 정밀도 분해. LLM.int8()은 이상치 차원만 FP16으로 따로 빼서 계산하고 나머지를 INT8로 돌린다. 정확도는 지켜지지만 커널이 지저분해지고 이상치 비율이 늘면 이득이 사라진다.
-
어려움을 옮기기. SmoothQuant(2022)는 활성값은 이상치 때문에 어렵고 가중치는 원래 얌전하다는 비대칭에 주목해, 수학적으로 동치인 재배분을 한다.
가 기본값. 활성값의 이상치를 눌러 가중치 쪽으로 넘기면 양쪽 다 적당히 어려워진다. 축약 축 스케일이라 그 자체로는 인수분해가 안 되지만, 을 앞단 층 정규화나 이전 선형층 가중치에 미리 접어 넣으면 런타임 비용이 0이 된다. 앞 절의 제약을 정면돌파 대신 우회한 사례.
-
회전으로 흩기. 최근 계열(QuaRot, SpinQuant 등, 2024)은 아다마르 변환처럼 직교행렬 를 끼워 로 만든다. 회전하면 이상치 에너지가 여러 차원에 고르게 퍼져 최댓값이 크게 낮아지고, 를 가중치에 흡수시키면 역시 공짜다. 4비트 활성값·KV 캐시까지 내려가는 최근 결과들이 이 위에 서 있다.
가중치만 양자화하는(weight-only) 노선도 크다.3 토큰을 하나씩 생성하는 디코딩 단계는 연산이 아니라 가중치를 메모리에서 읽어 오는 대역폭에 묶여 있으므로, 활성값을 FP16으로 두고 가중치만 INT4로 줄여도 속도가 붙는다.
- GPTQ(2022)는 층별 재구성 오차 를 최소화하되, 가중치를 열 단위로 하나씩 양자화하고 그때 생긴 오차를 아직 양자화하지 않은 열들에 헤세 역행렬로 재분배한다. 이 갱신식은 신경망 가지치기의 OBS(최적 뇌 수술)에서 그대로 온 것이고, 의 촐레스키 분해와 지연 배치 갱신으로 1750억 파라미터를 GPU 몇 시간에 3~4비트로 내린다. 가지치기 이론이 20년 뒤 양자화에서 부활한 대표 사례.
- AWQ(2023)는 가중치가 전부 같은 값어치는 아니라는 관찰에서 출발한다. 활성값 크기로 골라낸 상위 0.1~1% “중요 채널”만 보호하면 오차 대부분이 사라지는데, 이걸 혼합 정밀도로 하면 커널이 지저분해지므로 대신 그 채널의 가중치를 배 키우고 활성값을 로 줄인 뒤 통째로 정수 양자화한다. 전부 정수로 남는다는 점이 배포 관점의 결정적 장점이다.
7. 실무에서 실제로 부딪히는 것들[편집]
- 양자화한다고 자동으로 빨라지지 않는다. INT8 텐서코어를 실제로 태우는 커널이 있어야 이득이 나온다. 프레임워크가 양자화-역양자화 노드만 잔뜩 끼워 넣고 실제 연산은 FP32로 하는 “가짜 양자화 배포”는 모델 크기만 줄고 지연시간은 오히려 늘어난다. GPU 컴퓨팅 쪽 프로파일러로 확인하기 전까지는 이득을 주장하지 않는 게 좋다.
- 연산자 융합이 곧 성능이다. 합성곱 → 배치 정규화 → ReLU 를 하나로 접어 넣고 그 경계에서만 정수↔실수를 오가야 한다. 층마다 왔다 갔다 하면 변환 비용이 이득을 다 먹는다.
- 양자화에 특히 약한 부위가 있다. 소프트맥스와 정규화층, 어텐션의 로짓, 잔차 누산기는 보통 높은 정밀도로 남긴다. 첫 층과 마지막 층을 INT8에서 빼는 관행도 같은 이유다.
- 평가 지표를 바꾸면 결론이 바뀐다. 상위-1 정확도는 그대로인데 출력 확률의 보정이 무너지거나, 평균 성능은 유지되는데 희귀 입력에서만 크게 틀리는 경우가 흔하다. 압축은 성능의 평균이 아니라 꼬리를 먼저 깎는다.
- 순서가 있다. 증류 → 구조적 가지치기 → 양자화 순서가 무난하다. 양자화를 먼저 하면 이후 학습 단계마다 STE를 끌고 다녀야 한다.
8. 관련 문서[편집]
- 지식 증류 · 신경망 가지치기 · 벡터 양자화 · 곱 양자화
- 심층 학습 · 합성곱 신경망 · 트랜스포머 · 역전파
- 부동소수점 연산 · 혼합 정밀도 연산 · GPU 컴퓨팅
- 쿨백-라이블러 발산 · 층 정규화 · 배치 정규화
- 촐레스키 분해 · 특이값 분해 · 조건수
- 불확실성 정량화 · 검증 및 확인
9. Footnotes[편집]
-
그래서 “비균일 격자가 정보이론적으로 더 낫다”는 논증은 이 바닥에서 잘 안 먹힌다. 로그 격자나 학습된 코드북이 같은 비트 수에서 왜곡을 더 줄이는 것은 맞는데, 그 값을 곱하려면 결국 룩업 테이블을 거쳐야 하고 그 순간 텐서코어를 못 쓴다. 이론적 최적성과 실리콘이 싸우면 대체로 실리콘이 이긴다. ↩
-
STE의 정당화 논문은 지금도 꾸준히 나오는데, 대개 “특정 가정 아래 STE 방향이 진짜 기울기와 예각을 이룬다” 형태다. 실무자 입장에서 요약하면 “왜 되는지는 모르겠고 안 쓰면 학습이 안 된다”이며, 이 문장은 심층학습 전반에 재사용 가능하다. ↩
-
그래서 언어모형 추론에서는 “연산량을 줄였다”보다 “읽어 올 바이트를 줄였다”가 정확한 표현이다. 배치 크기 1인 디코딩에서 GPU는 대부분의 시간을 놀면서 가중치가 도착하기를 기다린다. 루프라인 모델을 그려 보면 어디에 걸려 있는지 바로 보이는데, 그걸 안 그리고 FLOP만 세다가 “INT4로 줄였는데 왜 4배가 안 나오죠”를 묻게 된다. ↩