Contents

  1. QAT: FakeQuant
  2. PTQ: GGUF (GPT Generated Unified Format)
  3. PTQ: GPTQ (Post-Training Quantization for Transformers)
  4. PTQ: AWQ (Activation-aware Weight Quantization)
  5. QAT + PTQ: SpinQuant


1. QAT: FakeQuant

(1) 개요

[한 줄 요약] 학습 중에 양자화 연산을 흉내만 내는(faked) 연산을 넣어, 네트워크가 양자화에 적응하도록 만드는 기법

  • Forward에서는 “양자화했다가 다시 복원한 값”을 쓰고
  • Backward에서는 STE(Straight-Through Estimator)로 미분을 흘려줌

\(\rightarrow\) 학습이 끝나면, 실제 정수 커널(INT8/INT4 등)로 교체해 배포


(2) Forward

Notation

  • \(b\): 비트 수
  • 정수 범위 \([Q_{\min}, Q_{\max}]\)
    • e.g., 대칭 INT8은 [-127,127]
    • e.g., 비대칭 INT8은 [0,255]
  • \(x\): FP32 텐서(가중치 또는 활성화)
  • \(s\): scale(스텝 크기)
  • \(z\): zero-point(오프셋, 대칭이면 보통 0)
  • \(\hat{x}\): 양자화-복원된 값(이 값이 다음 연산으로 전달)


양자화 → 복원(FakeQuant):

\(\begin{aligned} q &= \mathrm{clamp}\!\left(\mathrm{round}\!\left(\frac{x}{s} + z\right),\; Q_{\min},\; Q_{\max}\right),\\ \hat{x} &= s \cdot (q - z), \end{aligned}\).


대칭(symmetric):

  • \(z=0,\; s=\dfrac{T}{Q_{\max}}\) with $$T=\max(\mid T_{\min} , T_{\max} )$$

비대칭(asymmetric):

  • \(s=\dfrac{T_{\max}-T_{\min}}{Q_{\max}-Q_{\min}},\; z=\left\lfloor-\dfrac{T_{\min}}{s}\right\rceil\).


(3) Backward, STE

round와 clamp는 “미분 불가능”이므로, QAT에서는 STE를 사용

  • 아이디어: 전달할 그레이디언트는 1로 가정 (클리핑 구간 밖은 0)

  • 직관적 표기:

    \(\frac{\partial \hat{x}}{\partial x} \approx \begin{cases} 1 & \text{(클리핑 범위 내부)}\\ 0 & \text{(클리핑 범위 바깥, saturation)} \end{cases}\).

\(\rightarrow\) 이렇게 해서 양자화가 넣는 불연속성에도 학습이 진행되도록!!


(4) 어디에 붙이나? (삽입 위치)

(1) 가중치 (Conv/Linear weight):

  • 보통 per-channel 스케일(출력 채널별 scale)로 FakeQuant 삽입

(2) 활성화 (activation):

  • 보통 per-tensor 스케일, 연산 노드(Conv/Linear) 출력 쪽에 FakeQuant 삽입


(5) Scale/ Zero-point

  1. Observer(관찰자) 기반:
    • MinMax, MovingAverageMinMax, Histogram, Percentile 등으로 \(T_{\min}, T_{\max}\) 추정 → s,z 계산
    • QAT 시작 시 칼리브레이션 몇 배치로 초기화 후, 학습 동안 EMA로 갱신하거나 고정
  2. 학습형(learnable) 스케일:
    • LSQ류: s를 파라미터로 두고 학습 (역전파 시 STE 변형)
    • PACT류: 활성화 클리핑 임계값 \(\alpha\)를 학습
      • ReLU 앞뒤에 \(\mathrm{clip}(x; 0,\alpha)\)


Tip)

  • 4-bit 같은 저비트로 갈수록, 학습형 스케일/클리핑이 정확도 유지에 유리!

  • 초기엔 FakeQuant를 껐다가 (Observer만 켜서 통계 수집) → 수 epoch 뒤 켜기(학습 안정)
  • 첫/마지막 레이어, 임베딩 레이어는 고정밀(FP16/BF16) 유지
  • 가중치는 per-channel, 활성화는 per-tensor가 일반적
  • BatchNorm은 QAT 전에 Conv에 fuse하는 게 보편적


Pytorch

import torch
import torch.nn as nn
from torch.ao.quantization import FakeQuantize, MovingAverageMinMaxObserver

# 예: 대칭 INT8, activation용 FakeQuant 모듈
act_fakequant = FakeQuantize(
    observer=MovingAverageMinMaxObserver,
    quant_min=-127, 
    quant_max=127,   # 대칭
    dtype=torch.qint8,
    qscheme=torch.per_tensor_symmetric,
    reduce_range=False
)

# 간단한 forward에서 사용
x = torch.randn(4, 16)  # activation
x_q = act_fakequant(x)  # forward에서 양자화-복원된 값으로 대체


PTQ에 비해 효과적인 이유

  • PTQ는 사후에 스케일을 맞추기만 하므로!

    \(\rightarrow\) clipping 손실을 모델이 보상하지 못함

  • QAT는 학습 중 FakeQuant로 인한 손실을 모델 parameter가 학습적으로 보상

    → 저비트(특히 4-bit)에서 효과 큼


2. PTQ: GGUF (GPT Generated Unified Format)

(1) 개요

GGUF (GPT Generated Unified Format)

  • llama.cpp 계열 툴체인에서 사용하는 model 저장 포맷
    • e.g., GGUF, safetensors, ckpt → 특정 규칙에 맞게 weight+메타데이터 저장
  • LLM 모델을 효율적으로 저장하고 추론할 수 있도록 만든 최신 PTQ(Post-Training Quantization) 포맷
  • QAT (X), PTQ (O)
    • 즉, QAT(학습 중 양자화)가 아니라, 이미 학습된 모델을 사후에 양자화해 저장하는데 사용


llama.cpp란?

  • Meta의 LLaMA 모델을 CPU나 작은 GPU에서도 돌릴 수 있게 만든 오픈소스 프로젝트
  • 파이썬이나 거대한 GPU 환경이 없어도, 단순한 C/C++ 코드로 모델을 실행 가능
  • 여기서 모델을 불러올 때는 특정 파일 포맷을 요구하는데, 그 최신 표준이 GGUF


(2) 특징

  • (1) 다양한 정밀도 지원

    • FP16, INT8, INT4 등 여러 정밀도로 model 변환 가능

    • 특히 LLaMA, Mistral, Falcon 같은 model을 4-bit, 8-bit로 PTQ 해서 PC/모바일에서도 돌릴 수 있게 함.

  • (2) 구조적 저장

    • 단순한 weight 배열이 아니라,
    • 메타데이터(토크나이저 정보, 레이어별 설정 등)까지 함께 담아 완전한 모델 package
  • (3) 효율성

    • 기존 GGML 포맷보다 빠른 로딩, 더 작은 디스크 용량, 호환성↑

    • GPU 없이도 CPU에서 가볍게 구동 가능하도록 설계됨.


(3) PTQ와의 연결

GGUF는 양자화 알고리즘 자체가 아님!

양자화된 결과물을 담는 컨테이너 역할임

  • 예를 들어, LLaMA-7B를 INT4로 PTQ 했다면 → 그 결과물이 GGUF 파일(model.Q4_K_M.gguf)로 저장됨.
  • 따라서 GGUF는 PTQ 기반 배포에서 표준 포맷처럼 사용


(4) Summary

  • GGUF = PTQ된 모델을 담는 최신 통합 포맷
    • GGUF는 양자화 알고리즘 자체가 아님!
    • 양자화된 결과물을 담는 컨테이너 역할임
  • e.g., LLaMA-7B를 INT4로 PTQ 했다면

    → 그 결과물이 GGUF 파일(model.Q4_K_M.gguf)로 저장됨.

  • INT8, INT4 PTQ 모델 배포에서 사실상 표준처럼 사용


좋습니다. 이제 3) PTQ: GPTQ에 대해 설명드릴게요.


3) PTQ: GPTQ (Post-Training Quantization for Transformers)

(1) 개요

GPTQ = “Post-Training Quantization for Transformers”

  • (Note that 이름과 달리 단순히 GPT 모델만을 위한 건 아님)

    \(\rightarrow\) 모든 Transformer 계열 LLM에 적용할 수 있는 PTQ 방식

핵심:

  • 단순히 min–max 기반으로 스케일링 X
  • 행렬 곱 연산에서 생기는 quantizarion error를 최소화하도록 weight를 양자화


(2) 동작 방식

  • (1) Block 단위 처리
    • Layer-wise → Block-wise
      • Transformer의 큰 weight 행렬(예: Linear layer)을 작은 블록(열 단위)으로 나눔.
    • “블록 별로 최적의 scale/zero-point”를 찾음.
  • (2) Quantiaztion error 최소화

    • 단순히 round 하는 것이 아님!
    • weight 행렬 \(W\)와 양자화된 \(W_q\)를 사용했을 때의 출력 차이 \(\mid \mid XW - XW_q \mid \mid\) 를 최소화하도록 weight를 선택
      • 여기서 \(X\)는 sample 데이터(== calibration 데이터).
  • (3) 순차 최적화(Sequential approximation)

    • 한 열(column)을 양자화 → 그로 인한 오차를 고려 → 다음 열을 보정하면서 양자화.

    • 이렇게 하면 누적 오차를 줄일 수 있음.


(3) Example

  • 원래 Linear 레이어 weight: 4096 × 11008 행렬 (FP16)

  • INT4로 단순 quantization → 성능 급락

  • GPTQ 적용 시:

    • 샘플 입력 배치를 넣고, weight 열 단위로 최적 스케일 계산
    • 오차 최소화 → INT4에서도 원래 성능에 근접
  • GPTQ = 고도화된 PTQ 알고리즘
  • 핵심 = weight 행렬을 열 단위로 최적화해 출력 오차 최소화
  • 효과 = INT4에서도 정확도 손실 최소화, LLM 배포에 많이 쓰임 (예: model.gptq 파일 형식으로 제공됨)

(4) Summary

  • GPTQ = 고도화된 PTQ 알고리즘
  • 핵심 = weight 행렬을 열 단위로 최적화해 출력 오차 최소화

  • PTQ 방식 → 추가 학습 (finetuning) 필요 없음.
  • INT4에서도 정확도 손실 최소화, LLM 배포에 많이 쓰임 (예: model.gptq 파일 형식으로 제공됨)
  • Details
    • 비트 수: 주로 INT4, INT3에서도 좋은 성능.
    • 정확도: 단순 uniform PTQ보다 훨씬 좋음.
    • 계산량: 최적화 과정 때문에 변환 시간이 조금 더 걸림.


4. PTQ: AWQ (Activation-aware Weight Quantization)

(1) 개요

AWQ (Activation-aware Weight Quantization)

  • 단순히 weight 분포만 보고 양자화하지 않고,

    활성화(activation)와의 상호작용을 고려하여 가중치를 양자화!

  • PTQ 기법

  • 목표: INT4 양자화에서도 GPTQ 수준의 성능 유지, 하지만 더 빠르고 간단하게!


(2) 핵심 아이디어

  • (1) weight 중요도 측정

    • 모든 weight가 모델 출력에 같은 영향을 주는 게 아님.

    • 특히 activation이 크게 반응하는 방향의 weight는 더 중요.

    \(\rightarrow\) 따라서 weight마다 “중요도”를 측정

  • (2) 중요한 weight 보존

    • 중요도가 높은 weight: scale factor를 조정해서 손실이 덜 나도록 양자화.

    • 중요도가 낮은 weight: 더 거칠게 양자화해도 괜찮음

  • (3) 결론

    • 전체 오차(MSE)를 최소화하는 대신,
    • 모델 “출력에 더 큰 영향”을 주는 부분을 정밀하게 보존.


(3) Example

\(y = Wx\).

  • GPTQ: \(W\)의 양자화 오차를 최소화 (\(\mid \mid XW - XW_q \mid \mid\))
  • AWQ: \(Wx\)에서 activation \(x\)와 곱했을 때 영향 큰 weight를 더 잘 보존


즉, 입력(activation) 분포까지 고려해서 quantization을 최적화한다는 차이가 있음.

(4) Summary

  • PTQ 방식 → 학습(finetuning) 불필요.
  • 빠름: GPTQ처럼 복잡한 최적화가 필요 없음 → 변환 속도 ↑.
  • 효과적: INT4에서도 FP16 성능에 근접.
  • 구현: Hugging Face awq 라이브러리 등에서 쉽게 사용 가능.


(5) GPTQ vs. AWQ

GPTQ

  • 문제식: \(\min_{W_q} \; \\mid XW - XW_q \\mid ^2\).
    • 여기서 X는 칼리브레이션 데이터(activation batch) 전체, W는 weight.
  • 즉, 행렬 곱의 출력 차이 전체(norm) 최소화가 목표.
  • 구현상은 열(column) 단위로 순차 양자화 → 누적 오차를 줄이는 방식.

\(\rightarrow\) 결과: “모든 weight가 공평하게 고려됨.”

  • 큰 activation 방향이 자동으로 더 큰 오차를 주기는 하지만,
  • GPTQ는 weight를 직접적으로 중요/비중요로 나누지 않고, 그냥 전체 오차를 줄이는 최적화 문제로 접근.


AWQ

  • 문제식: \(\min_{W_q} \; \\mid X(W - W_q) \\mid ^2\)
    • with reweighting by activation importance
  • 차이:
    • X의 분포를 단순히 “샘플 데이터”로 보는 게 아니라,
    • activation이 큰 축(즉, 모델이 자주 크게 반응하는 weight 방향)을 강조해서 보존하도록 설계.
  • 실무적으로는 중요한 weight만 FP16 그대로 두고 나머지만 INT4로 양자화하거나,
    • scale factor를 중요 weight에 유리하게 조정.

\(\rightarrow\) 결과: “활성화와 곱했을 때 영향력이 큰 weight는 더 정밀하게 보존, 덜 중요한 weight는 손실 감수.”


Example

  • 데이터: \(x = [1000, \; 1], weight W = [0.01, \; 0.01].\)
  • 출력: \(y = 1000 \cdot 0.01 + 1 \cdot 0.01 = 10.01\)


GPTQ

  • 두 weight 모두 0.01이니까 → 똑같이 양자화됨.
  • 결과적으로 activation이 큰 첫 번째 weight가 약간 손실되면 → 출력 오차 커짐.
  • GPTQ는 출력 오차 전체를 줄이려 애쓰지만, weight 중요도를 명시적으로 다루지 않음.


AWQ

  • \(x_1 = 1000\)이 크므로 첫 weight(0.01)는 매우 중요.
  • 따라서 이 weight를 FP16에 남겨두거나, 더 정밀하게 스케일링.
  • 반대로 x_2=1 방향은 영향이 작으므로 INT4로 손실 감수해도 됨.
  • 결과: 출력 오차는 훨씬 작아짐.


5. SpinQuant

(1) 개요

SpinQuant

  • 2024년에 제안된 QAT + PTQ 기법
  • 특정 레이어를 회전(rotate) 변환한 뒤 양자화를 적용
    • “Spin” = weight 공간을 회전(spin)시켜 더 양자화 친화적인 space로 바꾸는 것


(2) 핵심 아이디어

  • (1) 문제:

    • LLM weight는 “특정 축 방향으로 분산이 크거나 긴 꼬리 분포(outlier)”가 존재.

    • 따라서, 그대로 (INT4/INT8로) 양자화하면 일부 축에서 심한 손실 발생

  • (2) 해결:

    • Step 1) weight를 직교 행렬(orthogonal transform)로 회전시켜 분포를 더 “균등”하게 만든 뒤에 양자화!

    • Step 2) 양자화 후 다시 역회전(inverse transform)하여 원래 space로 복원!

  • (3) 학습(Adaptation):

    • 단순한 고정 회전 X
    • 저차원 어댑터(LoRA처럼 작은 학습 가능 모듈)를 사용해 회전 행렬을 학습 O

    \(\rightarrow\) 모델 전체를 다시 학습할 필요 없이, 작은 추가 학습만으로 양자화 친화적인 weight 공간 확보


(3) Example

  • 원래 weight 벡터: \([10, 0.1, 0.05]\)

    • 첫 번째 값이 너무 큼 → 아웃라이어
  • 그대로 INT4 quantization 시?

    → 첫 번째 값 때문에 scale이 커져, 나머지 값들(0.1, 0.05)이 전부 0으로 사라짐!

  • SpinQuant:

    • weight 공간을 회전시켜 [2, 2, 2] 같은 균등 분포로 만든 뒤 양자화 → 손실 최소화!!
    • 양자화된 상태에서 역회전 → 원래 의미를 잘 살린 weight 복원.


(4) Summary

  • SpinQuant = weight 공간 회전(orthogonal transform) + 소규모 학습 → 양자화 친화적 표현으로 변환 후 양자화
  • PTQ + 소규모 학습 = Hybrid
    • PTQ처럼 전체를 재학습하지 않지만, GPTQ/AWQ보다 조금 더 학습을 허용.
  • 저비트(특히 4-bit 이하)에서 큰 성능 개선.
  • 다양한 Transformer 구조(LLaMA, Mistral 등)에 적용 가능.

Categories: ,

Updated: