본문 바로가기
ML & DL/Study

Integer Quantization for Deep Learning Inference 리뷰

by 별준 2024. 2. 7.

References

  • Integer Quantization for Deep Learning Inference: Principles and Empirical Evaluation (link)

이 논문은 뉴럴 네트워크의 INT quantization에 대한 수학적인 배경과 성능과 관련하여 quantization parameter를 선택하는 몇 가지 방법을 이야기한다. 또한, quantization workflow를 제안하며 이를 통해 모든 네트워크에서 1% 이내의 정확도 손실로 양자화할 수 있다는 것을 보여준다.

 

Intro

양자화(quantization) 기법은 높은 처리량의 integer instruction을 활용하여 딥뉴럴 네트워크의 크기를 줄이고 추론 속도를 향상시킬 수 있다.

 

일반적으로 32비트의 single-precision 부동소수점이 딥러닝에서 주로 사용되지만, 최근에는 연산 성능을 높이기 위해 다양한 포맷을 사용한다. 특히, FP16이나 BFloat16과 같은 16비트 부동소수점 타입을 사용하여 모델을 학습하기도 한다. 학습이 완료된 이후에는 더 낮은 정밀도의 타입이나 정수 타입을 사용하여 추론한다. 최근 엣지 디바이스에서는 INT8 네트워크 추론만 지원하는 경우도 많다.

 

32비트보다 더 낮은 정밀도를 가진 타입을 사용하면 아래와 같은 성능상의 이점을 얻을 수 있다.

  • 많은 프로세서들이 low-bit 포맷에서 더 높은 처리량의 math pipelines를 제공한다. 이를 통해 math-intensive 연산(convoution 및 matrix multiplication)에서 속도를 향상시킬 수 있다.
  • 워드(word)의 크기가 작으면 memory bandwidth pressure가 감소하고, 이러한 bandwidth에 의해 제한되는 연산의 성능을 향상시킬 수 있다.
  • 워드(word)의 크기가 작으면 결과적으로 동일한 파라미터 수에 대해 더 적은 메모리를 사용하므로 캐시 활용을 향상시키거나 메모리 시스템 연산의 다른 측면을 향상시킬 수 있다.

위 표는 NVIDIA Turing GPU에서 다양한 데이터 타입에 대한 텐서 연산 처리량을 비교하여 보여준다. FP32 대신 INT8을 사용하면 최대 16배의 속도 향상을 얻을 수 있으며 bandwidth 또한 4배 증가하게 된다.

 

속도는 향상시킬 수 있지만, 표현할 수 있는 수치 범위가 감소하기 때문에 정확도가 낮아질 수 있다. 따라서, 양자화를 적용할 때는 모델의 정확도에 미치는 영향을 최소화하도록 주의해야 한다.

Quantization Fundamentals

논문에서는 high throughput을 가진 integer math pipelines를 행렬 곱셈과 컨볼루션에 활용할 수 있는 uniform quantization에 대해 중점적으로 살펴본다. Uniform quantization은 다음의 2개의 단계로 나눌 수 있다.

  1. 양자화할 실수 범위를 선택하고, 이를 벗어나는 값은 클램핑(clamping)한다.
  2. 실수 값을 특정 bit-width로 표현할 양자화된 값으로 매핑한다.

Range Mapping

양자화할 실수 표현의 범위가 \([\beta, \alpha]\) 이고, \(b\)를 부호가 있는 정수 표현의 bit-width라고 하자. Uniform quantization은 입력 \(x \in [\beta, \alpha]\) 를 \([-2^{b-1}, 2^{b-1} - 1]\) 로 변환하며, 범위를 벗어나는 입력 값은 가장 가까운 경계값으로 잘린다. 논문에서는 uniform transformations만 다루고 있으므로, 두 가지 변환 방식에 대해 살펴본다.

  • affine transformation: \(f(x) = s \cdot x + z\)
  • scale transformation:  \(f(x) = s \cdot x\) (affine의 special case)

Affine Quantization

Affien Quantization은 실수값 \(x \in \mathbb{R}\)을 \(b\)-bit 정수 \(x_q \in \{-2^{b-1}, -2^{b-1}+1, ..., 2^{b-1}-1\}\)으로 매핑한다. Affine transformation 함수, \(f(x) = s \cdot x + z\)는 아래의 식으로부터 정의된다.

여기서 \(s\)는 scale factor이고, \(z\)는 zero-point이다. 8-bit인 경우에는 \(s = \frac{255}{\alpha - \beta}\), \(z = -\text{round}(\beta\cdot s) - 128\)이 된다.

 

quantize 연산은 아래의 식으로 정의된다.

아래 식은 dequantize 연산이다. 이 연산은 original real value input을 근사한다 (\(\hat{x} \approx x\)).

Scale Quantization

Scale quantization은 오직 scale transformation만으로 실수값으로부터 정수값으로의 매핑을 수행한다. 간단하게 살펴보기 위해 입력의 범위와 정수의 범위가 0을 중심으로 대칭인 symmetric 버전에 대해서만 고려하며, 이를 symmetric quantization이라고 한다. Symmetric quantization에서 INT8인 경우에는 \([-127, 128]\) 범위를 사용하며, -128 값은 사용하지 않는다.

아래 식은 범위가 \([-\alpha, \alpha]\)인 실수값 \(x\)의 scale quantization을 정의하며, \(b\)-bit 정수값 \(x_q\)로 매핑된다.

아래 식은 대응되는 dequantize 연산을 정의한다.

Tensor Quantization Granularity

텐서 요소 간의 quantization parameters를 공유하는데 여러 선택지가 있으며, 이러한 선택을 quantization granularity라고 칭한다. 예를 들어, 가장 대략적인 방법으로는 텐서 내 모든 요소가 동일한 파라미터를 공유하는 것이 있다 (per-tensor granularity). 반면, 가장 미세하게 세분화된 방법으로는 텐서 내 각 요소 별로 개별적인 파라미터를 가지는 것이 있다 (per-element granularity). 중간 정도의 세분성으로는 텐서의 각 차원 별로 파라미터를 공유하는 방법이 있다 (e.g., per-column granularity).

 

이 논문에서는 모델의 정확도와 연산 비용이라는 두 가지 요소를 고려하고 있으며, 최대 성능을 위해서 아래의 방법을 제안하고 있다.

  • Activations: per-tensor granularity (성능상의 이유로 only per-tensor만 practical 하다고 언급하고 있다)
  • Weights: per-tensor or per-column granularity

Depthwise convolution의 경우에는 연산이 채널 별로 수행되므로 per-channel granularity를 적용해야 한다.

Computational Cost of Affine Quantization

Affien quantization의 연산은 아래와 같이 약간 복잡하다.

연산은 (1), (2), (3)의 세 부분으로 나눌 수 있는데, (1) 항은 integer dotproduct이고 (2) 항은 integer weights와 zero-point로만 구성된다. 결과적으로 (1)과 (2)는 offline에서 계산될 수 있는 부분이고, 추론에서 element-wise addition만 추가해주면 된다.

 

반면 (3) 항에서는 양자화된 입력인 \(x_q\)가 포함되어 있으므로 offline으로 계산할 수 없다. 구현에 따라서 이 연산에는 상당한 오버헤드가 발생할 수 있다. 이 연산은 affine quantization을 사용하는 경우에만 발생하므로, 추론 성능을 최대화하려면 weights에 대해서 scale quantization을 사용하는 것이 좋다. 이 논문에서는 scale quantization으로도 충분한 정확도를 얻을 수 있다고 언급한다.

Calibration

캘리브레이션은 모델의 weights와 activations에 대해 \(\alpha,\beta\)를 선택하는 프로세스이다. 논문에서는 3가지 방법에 대해 언급하고 있다.

  • Max: 캘리브레이션 중에 발견된 maximum absolute value를 사용
  • Entropy: KL divergence를 사용하여 original floating-point값과 양자화된 형식으로 나타낼 수 있는 값 사이의 information loss를 최소화하는 방식으로 수행된다. TensorRT에서 기본적으로 사용되는 방식이다.
  • Percentile: 캘리브레이션을 통해 확인한 절댓값의 분포의 백분위로 범위를 설정한다. 예를 들어, 99% percentile이라면 가장 큰 크기의 값의 1%를 clip 한다.

 

Post Training Quantization (PTQ)

Post Training Quantization (PTQ)는 학습이 완료된 이후에 양자화를 적용하는 것을 의미한다. 추가적인 학습이 필요하지 않으며 offline에서 calibration을 진행하게 된다.

Weight Quantization

Weight 값은 네트워크 입력에 의존하지 않기 때문에 별도로 quantization 평가하고, max calibration으로 INT8 weights의 정확도를 유지하는데 충분하다는 것을 보여준다. 아래 표의 결과는 per-tensor와 per-channel quantization granularity가 정확도에 미치는 영향을 비교한다.

Per-tensor quantization 결과는 정확도의 손실이 상당하다. EfficientNet b0에서는 batch-normalization(BN)이 conv 레이어로 폴딩되면 그 손실이 더욱 심해질 수 있다는 것을 보여준다.

 

BN folding은 추론 속도를 높이기 위해 일반적으로 사용되는 기법이다. 하지만 BN의 매개변수는 채널별로 학습되기 때문에, 폴딩했을 시 채널 별로 weight의 분포가 크게 달라질 수 있다. 따라서 per-channel quantization granularity에서는 모델의 정확도를 어느정도 유지하고 있다는 것을 보여준다.

Activation Quantization

아래 표는 다양한 캘리브레이션 방법(max, entropy, percentile)에 대한 activation quantization 결과를 보여준다. Weight는 per-channel (with max calibraiton)을 사용하여 양자화되었다.

대부분의 네트워크에서는 허용 가능한 정도의 정확도를 달성하는 activation quantization 방법이 적어도 하나는 존재한다. 다만, 모든 네트워크에서 최선인 방법은 없다.

 

Techniques to Recover Accuracy

네트워크 학습 이후 PTQ를 적용했을 때 정확도를 유지하는 네트워크도 있는 반면, 정확도가 상당히 감소하는 경우도 존재한다. 이렇게 감소한 정확도를 복구하기 위한 여러 가지 기법들이 있는데, 가장 간단한 방법은 partial quantization이다. 즉, 양자화에 민감한 레이어는 양자화하지 않는 것이다. 또 다른 방법으로는 네트워크를 학습할 때 quantization도 같이 수행하는 것이다. 또한, model wieghts와 quantization parameters를 함께 학습하는 방식도 있다.

Partial Quantization

양자화된 모델에서 보통 몇몇의 레이어가 정확도 손실의 대부분에 기여한다. 따라서, 정확도를 높이기 위해 이러한 민감한 레이어들을 양자화하지 않는다. 즉, 이러한 레이어들의 입력과 연산은 부동소수점 타입으로 진행하는 것이다.

 

한 레이어의 양자화는 다른 레이어의 입력에 영향을 미치기 때문에 양자화에 최적인 레이어 집합을 찾으려면 많은 케이스를 테스트해야할 수 있다. 때문에, 정확도를 감소에 가장 큰 영향을 차지하는 레이어를 찾는 것보다 one-at-a-time sensitivity analysis를 제안한다.

 

아래 그래프는 EfficientNet b0의 sensitivity analysys와 partial quantization 결과를 보여준다. 여기서는 entropy calibration을 사용하며, 한 번에 한 레이어씩 양자화를 수행하고 정확도를 평가한다.

위 그래프에서는 양자화에 가장 민감한 10개의 레이어만을 보여주는데, 이러한 10개의 레이어는 스킵하고 나머지 레이어들에 대해서만 양자화를 수행하여 정확도를 유지할 수 있다고 한다.

 

Quantization-Aware Training

Quantization Aware Training (QAT)는 학습 또는 fine-tuning 전에 quantization operation을 네트워크에 추가하는 기법이다. QAT가 일반적으로 PTQ보다 더 좋은 결과를 보여주는데, 그 이유는 아래 그림에서 보여주고 있다.

간략히 요약하면, 위 그림에서 PTQ(a)는 \(w \approx -0.5\)에서 local minimum으로 수렴했다. PTQ를 적용할 때, scale factor가 1인 경우 이 weight는 가장 가까운 정수 \(w_q = -1\)로 양자화되기 때문에 loss가 크게 증가한다. 이러한 경우를 narrow minimum으로 수렴되었다고 말하는데, 이는 weight가 아주 조금 변했지만 loss가 크게 변했기 때문이다.

 

반면 QAT(b)의 경우에는 양자화된 weights에 대한 기울기를 계산하여 narrow minimum을 잠재적으로 피할 수 있다. 이를 통해 잠재적으로 모델이 'wide' or 'flat' minimum에 대한 loss를 탐색할 수 있도록 한다. 따라서 loss가 더 낮고 정확도는 높아지게 된다.

 

QAT를 구현하는 일반적인 방법은 simulated quantization이라고도 부르는 fake quantization operatioin을 floating-point network에 추가하는 것이다. 아래 식이 바로 fake quantization을 정의한다.

Fake quantization에 대한 내용은 여기서 다루지는 않는다. 간단히, quantization parameter도 학습 단계에서 학습하는 것으로 이해할 수 있다.

 

아래 표는 PTQ와 QAT 결과 성능을 비교한다. 여기서 QAT는 best PTQ 모델로부터 fine-tuning한 것이다.

Recommended Workflow

지금까지의 결과를 바탕으로 논문에서는 다음을 만족하는 INT8 quantization을 권장한다.

  • Weights
    • Use scale quantization with per-column/per-channel granularity
    • Use a symmetric integer range for quantization \([-127, 127]\) and max calibration
  • Activations
    • Use scale quantization per-tensor granularity

또한, 학습된 네트워크를 양자화하기 위한 아래의 절차를 권장한다.

  • PTQ: 모든 computationally intensive layers (conv, linear, matmul, ...)를 양자화하고, max/entropy/percentile을 포함하는 activation calibration을 수행한다. 원하는 성능을 얻지 못하는 경우에는 partial quantization 또는 QAT를 사용한다.
  • Partial Quantization: Sensitivity analysis를 통해 양자화에 민감한 레이어를 찾고, 이러한 레이어들은 양자화하지 않는다. 그래도 성능을 만족하지 못한다면 QAT를 시도한다.
  • QAT: 가장 calibration이 잘 된 quantized model로부터 시작한다. 본래 학습에 사용했던 스케쥴의 10% 정도만 사용하여 fine-tuning을 수행하며, 초기 training learning rate의 1%를 사용한다.

 

댓글