22.04.26 Quantization

2022. 4. 27. 12:18인턴/Quantization

https://gaussian37.github.io/dl-concept-quantization/

 

딥러닝의 Quantization (양자화)와 Quantization Aware Training

gaussian37's blog

gaussian37.github.io

https://arxiv.org/pdf/1712.05877.pdf

Quantization : 실수(Float)를 정수(Int)로 변환하는 과정. 보통 FP32를 INT8(8비트 정수) INT 16 등으로 변환한다.

- 딥러닝에서 Quantization을 사용할 때는 NN의 weight나 acitivation function의 값이 어느 정도 범위 안에 있다고 가정하고 모델을 경량화하게 된다.

- 예를 들어 실수 -1 부터 3 까지의 범위에 있는 데이터들을 INT 8로 양자화 한다고 치면

2**8인 256 개 범위의 Int로 바꿔주는 것이다. (0~255 또는 -127~127)

 

- 양자화를 하게 되면 32bit 자료형이 8bit 자료형으로 줄어들기 때문에 속도 감소, 메모리 사용량 감소 등의 장점이 있다.

왜냐하면 float 타입을 int 타입으로 줄이면서 용량을 줄일 수 있고 bit 수를 줄임으로서 계산 복잡도도 감소함

( 32 bit 였던 것을 8 bit로 줄이게 되면 곱셈 복잡도는 32/8 = 4 , 4의 제곱배인 16배 줄어든다고 한다.)

 

- 즉, 양자화는 딥러닝 모델의 1. 사이즈축소, 2. 연산량 감소, 3. 효율적인 하드웨어 사용 이 목적.

 

Python에서 floating이 int보다 더 빠른 것 확인 예제

import time
t1 = time.time()
print(3.123456789 - 2.345678912)
t2 = time.time()
print(3 - 2)
t3 = time.time()

print((t2 - t1))
# 0.025929689407348633
print((t3 - t2))
# 0.023936748504638672
print((t2 - t1) / (t3 - t2))
# 1.083258630650013

정수 연산보다 실수 연산이 8%정도 더 느리다.

 

딥러닝에서 Quantization의 역할

ResNet에 Quantization을 적용했을 때 Accuracy의 변화를 나타낸 그래프이다. 보통 모델의 크기가 커질수록 Accuracy가 증가하는 대신 필요한 자원이 많아져 trade off 관계가 되는데, 위 결과를 보면 ResNet-34 를 2bit로 표현했을 때 Accuracy가 ResNet-18을 4it로 표현했을 때보다 성능이 더 좋은 것을 알 수 있다. 그리고 모델 사이즈도 오히려 ResNet-34가 18보다 더 가벼운 것을 알 수 있음.

-> 작은 모델에 Quantization을 대충 하는 것보다 큰 모델에 Quantization을 더 잘하는 게 성능 및 모델 사이즈 측면에서 좋을 수 있다.

- FP32 대신 INT8을 사용하면 보통 model size는 1/4, inference speed는 2~4배, memory bandwidth도 2~4배 가벼워짐.

 

딥러닝 Quantization 의 5가지 전제조건

1. Quantization은 Inference할 때만 사용한다.

2. 구현한 딥러닝 모델의 모든 layer가 양자화 될 수 없을 수도 있다.(layer가 민감한 경우, pytorch와 같이 Framework가 지원하지 않는 경우 등)

3. 모든 layer가 반드시 양자화 되어야 하는 것이 가장 효율적인 것은 아니다. Layer Fusion이라는 것도 있음.

4. 같은 양자화를 적용하더라도 모든 딥러닝 모델이 동일한 효과가 나타나는 것은 아니다. layer의 특성에 따라 다르다.

5. 양자화가 적용된 많은 연산이 CPU에서만 사용해야 하는 경우도 있다.

 

딥러닝 Quantization의 6가지 단계

1. Module Fusion : layer들을 하나로 묶어주는 Fusion 단계. 대표적으로 Conv-BatchNorm-ReLU를 많이 Fusion한다. 필요시에만 진행한다.

2. Formula Definition : 양자화 식 정의. 어떻게 양자화 할 것이냐. 일반적으로 FP32-INT8을 많이 쓰고 다시 Floating point로 변경 시 INT8-FP32 로 변경하는 Dequantization 방법도 정의한다.

3. Hardware Deployment : 하드웨어에 따라 어떻게 Calibration할 지 달라진다. 인텔 또는 ARM

4. Dataset Calibration : 딥러닝 모델의 weight를 변환하기 위한 식의 파라미터를 Dataset을 이용하여 계산한다.

5. Weight Conversion : 실제 weight를 FP에서 INT로 변환한다.

6. Dequantization : 딥러닝 모델의 inference를 통해 얻은 출력을 Dequantization을 통해 다시 Floating 타입으로 변경한다. 필요시에만 진행.

 

Quantization 의 각 단계 

1. Module Fusion

주황색 - 첫 번째 모듈, 초록색 - 두 번째 모듈

위 그림은 각 레이어에 각각 양자화를 적용한 것,  밑 그림은 Conv-BatchNorm-ReLU를 묶어서 한번에 양자화를 진행한다는 뜻.

위 그림처럼 각 레이어 각각에 양자화를 적용하면 양자화가 적용된 layer를 걸칠 때마다 precision이 감소함.

밑 그림처럼 하면 동일한 모듈임에도 양자화 횟수를 3번에서 1번으로 줄여 정확도를 향상한다. -> 이것이 Module Fusion

 

모든 layer에 양자화를 적용하지 않는 이유 2가지

a. 양자화 횟수를 줄여 inference time 개선 (less quantization eperations)

b. 양자화 횟수를 줄여 precision 개선 (less approximation)

그러나 과도하게 양자화 횟수를 줄이면 양자화 목적이 사라지므로 어느 부분에 Module Fusion을 할 지 고민해보기.Conv-BatchNorm-ReLU는 그런데 성능효과가 어느 정도 입증됐으므로 Module Fusion을 하기를 권장한다고 함.

 

2. Formula Definition 어떻게 Quantization을 할 지 공식을 정한다.

왼쪽의 FP32를 오른쪽의 INT8로 변환하면 위와 같이 진행된다. 저 값들은 딥러닝 모델의 weight에 해당한다고 생각하자. 

보통 INT8로 quantization을 할때, unsigned 형태를 사용하면 0 ~ 255 까지의 값을 가지고 signed 형태를 사용하면 -128 ~ 127의 값을 가지게 된다.

양자화 식을 정할 때 하드웨어 칩이 ARM인지 INTEL인지도 알아야 한다. ARM은 MinMax를 이용하여 Scale 값을 구하는 반면, INTEL 은 히스토그램 알고리즘이라는 것을 사용한다고 한다.그리고 layer의 lower bound, upper bound를 이용해  Clipping을 진행하기도 한다.

위 식이 양자화 식이다. q = C(round(x/s) + z)  q는 양자화 하고 난 값, x은 양자화하고자 하는 값, C는 Clipping 함수, round는 반올림, s는 Scale, z는 Zero Point이다.Scale : 기존 실수값의 범위 / 양자화 할 정수값의 범위Clipping : 양자화 할 수 있는 실수 범위를 넘어가는 실수 값을 양자화할 수 있는 최소나 최대 값으로 양자화하는 것.Zero Point : r일 때의 영점(범위의 한 가운데, 영점 기준값) 이 양자화 되고 나서 영점. 만약 대칭 Quantization을 하면 z값은 0이 되서 수식이 간편해진다.

3. Hardware Deployment하드웨어에 따라 어떻게 Calibration하는지. 인텔 - 히스토그램 방식, ARM - MinMax 방식

 

4. Dataset CalibrationMinMax 방식이든 히스토그램 방식이든 s(scale값)를 정할 때 알파,베타(위 그림 식에서) 와 같은 범위값을 정하여 공식에 필요한 변수들을 정의한다. (베타,알파,z 등등)

 

5. Weight Conversion드디어 공식과 변수들을 이용해 Quantization 진행. FP 32값들을 INT8로

 

6. DequantizationINT8의 결과를 다시 FP32로 변환하는 것. FP32-INT8로 변환할 때 quantization error(round 에러, clipping 등)가 발생하기 때문에 다시 INT8-FP32로 변환한다고 해도 원래 오리지널 FP32와 차이가 생길 수 밖에 없다. Quantization error를 줄이는 것이 좋은 양자화 알고리즘이라고 할 수 있다.

 

Symmetric / Asymmetric Quantization

왼 : symmetric 오 : asymmetric

- Symmetric Quantization : 양자화를 할 때 최소 최대 값의 절댓값을 같게 두는 것. 영점을 0으로 두는 것. ex INT8 이면 - 128~0~127로. Symmetric 하게 하려면 실수값 데이터의 범위의 최소값과 최대값 중 절대값이 큰 값을 선택한 다음 알파, 베타로 사용한다. 예를 들어 실수값 데이터가 -1부터 3까지 분포되어있다고 치면 절댓값을 3을 선택하여 양자화를 진행한다.

Symmetric quantization을 사용할 때에는  가 되기 때문에 식이 간단해지고, z=0이 된다.

 

- Asymmetric Quantization : 양자화를 할 때 최소 최대 값의 절댓값을 다르게 하는 것. ex  0~126~255로

 

그리고 나서 outlier가 발생하면 Clipping까지 진행하면 양자화가 마무리된다. 

 

Quantization Mapping

Dequantization 식
Quantization 식

c와 d는 양자화 식에 쓰이는 변수이다. 여기서 xq는 정수이지만 floating point x를 c로 나누게 되면서 오차가 발생한다.( round 처리(반올림)를 하면서 발생하게 되는 오차.)

여기서 다음과 같은 식을 세울 수 있고, 즉 c는 scale, d( 또는 -d)는 zero point임을 알 수 있다.

이러한 양자화 과정을 거칠 때 floating point 0은 quantization error가 없다고 가정하므로 x=0일 때 양자화를 한 xq는 다음과 같이 된다. xq = round(0 *1/c - d) = round(-d) = -round(d) = -d. 

즉 floating point 0은 round 연산을 통해 발생하는 error가 없다.

 

 

Quantization 공식 총정리 - Quantization , Dequantization

그래서 총 정리를 하면 위 식이 된다. z는 정수이고, s는 양의 실수이다.

 

Affine Quantization Mapping (with Clipping)

만약 양자화를 했을 때 범위를 [알파,베타]->[알파q,베타q]로 한정된다면 양자화 시 범위를 벗어난 x의 값을 bound시켜버리는 Clipping을 취할 수 있다. 단순히 범위에 벗어난 값(l<=사이<=u)은 최저,최대 값으로 만들어버리는 것이라고 생각해도 될 것 같다.

양자화 하는 범위가 음의 정수를 포함하는 경우(-128~127) 그렇지 않은 경우(0~255)를 나누어서 생각하면 알파(범위의 최소값)와 베타(범위의 최대값)는 다음과 같다.

 

Symmetric Quantization Mapping ( Scale Quantization Mapping) - Affine Quantization Mapping의 한 가지

알파q와 베타q를 반대 부호로, 같은 절대값으로 대칭적으로 양자화 매핑을 진행하는 것을 의미한다.

두 가지 조건이 있다.

1.

2. 

zero point z가 0이어야 함.

 

즉 총정리하면 이 아래 두 조건을 성립하면 된다.

그러니까 Scale Quantization Mapping을 하면

와 같이 변환되고, 즉 양자화 결과는 0을 기준으로 대칭되도록 나타내어진다. (-128~127)

 

Quantized Matrix Multiplication

위에까지는 임의의 스칼라 값에 대해 Affine Quantization Mapping 방법으로 양자화 하는 것을 배웠다.

그러나 머신러닝/딥러닝에서는 최소 Matrix, Tensor 까지 다루기 때문에 Matrix에서 양자화를 어떻게 진행하는 지 알아야 하므로

지금부터는 행렬에서 양자화를 어떻게 진행하는지 살펴본다.

일단 위와 같은 공간에 행렬 Y,X,W이 존재한다고 가정한다.

그러면 행렬 곱은 다음과 같이 표현할 수 있다.

그런데 행렬곱을 진행할 때 floating point를 이용하여 많은 양의 곱과 합 연산을 진행하면 계산 속도가 integer에 비해 느리다.

따라서 저 우리가 원하는 행렬인 Yi,j를 구하기 위해 어떻게 양자화하는지 살펴보자.

그러면 양자화를 적용해서 총 정리를 해보면 Yq,i,j를 integer의 곱과 합으로(q자가 붙은 행렬들 = 양자화를 완료한 행렬들)로 표현할 수 있으며 이러한 integer matrix multiplication은 다양한 하드웨어에서 자체적으로 연산 최적화 방법이 존재한다고 한다.

예를 들어 NVIDIA의 Tensor Core나 Tensor Core IMMA Operation이라는 것을 사용하여 일반적인 실수 행렬 계산시보다 integer matrix multiplication일 때 더 빠르게 계산할 수 있다고 한다.

 

Deep Learning Layers에 적용하는 다양한 Quantization Mode들의 특징들

이 이미지는 뭘 설명하는 지는 잘 모르겠다.. 용주님 말씀으로는 기울기를 나타내는 것 같다고 하심. 근데 그렇게 중요한 그림은 아닌듯

딥러닝 모델에 적용하는 Quantization Mode로는 Dynamic, Static Quantization과 Quantization Aware Training이라는 것이 존재한다. 각 모드들의 장단점, 특징은 위의 표에 나와있다. 

 

Post Training Quantization과 Quantization Aware Training 비교

1. Post Training Quantization

- floating point 모델로 학습을 한 뒤 결과 weight 값들에 대해 양자화하는 방법. 즉, 학습을 완전히 끝내 놓고 양자화 에러를 최소화하도록 한다. 

- 장점 : 파라미터 사이즈가 큰 대형 모델의 정확도 하락 폭이 적다. 

- 단점 : 파라미터 사이즈가 작은 소형 모델의 정확도 하락 폭이 크다.

- PTQ를 사용하면 소형 모델에서 정확도가 하락이 많이 되는 이유는 다음과 같다. 소형 모델에서는 weight 및 layer의 갯수가 작아 weight가 가지는 정보의 양이 상대적으로 작기 때문에, 여러 에러나 outlier에 민감해지는데, 양자화로 인해 학습을 통해 얻은 실제 weight와 달라지는 경우 그 영향이 더 커져서 정확도 하락이 크다.

 

2. Quantization Aware Training

- 학습 진행 시점에 inference 시 양자화 적용에 의한 영향을 미리 시뮬레이션 하는 방식. 최적의 weight를 구하는 것과 동시에 양자화를 진행.

- 장점 : 양자화 이후 모델의 정확도 감소를 최소화 할 수 있다.

- 단점 : 모델 학습 이후 추가 학습이 필요하다.

 

QAT의 의의

양자화를 해야하는 상황은 Edge Device와 같은 환경에서 사용해야 하고, 이때 주로 소형 모델을 사용한다. 그런데 PTQ를 소형모델에 사용하기에는 양자화 성능이 좋지 않다. 따라서 QAT를 이용해 학습을 통해 얻은 실제 weight와 양자화 후 weight의 차이를 최소화하는 작업이 필요하다. 그러므로 mobilenet과 같은 소형 모델에서는 QAT가 필수적이다.

왼쪽이 단순 int형으로 양자화하는 모습이고, 오른쪽이 QAT를 사용한 모습이다. 오른쪽 QAT 그림에서 act quant(activation quantization)과 wt quant(weight quantization) = fake quantization node이 있는 것을 볼 수 있다. 

- QAT는 forward / backward 에서 weight와 activation function 출력에 대한 양자화를 학습 중에 시뮬레이션 한다.

- 저 빨간 노드(act quant, wt quant) 을 fake quantization node라고 하고 forward / backward pass에서 quantization 적용 시 영향을 시뮬레이션하게 된다.

- 추가적으로 batch normalization은 inference에 사용되는 모드를 적용하여 시뮬레이션을 하게 된다.

 

QAT의 메커니즘

- floating point 모델에서 양자화된 정수 모델로 변환하는 동안 양자화가 발생하는 위치에 fake quantization module, 즉 quantization / dequantization 모듈을 배치하여 정수 양자화에 의해 가져오는 Clipping 및 round 에러 효과를 시뮬레이션한다.

- fake quantization 모듈은 scale과 weight, activation의 zero point를 모니터링한다.

- QAT가 끝나면 floating point 모델은 fake quantization 모듈에 저장된 정보를 사용해 양자화된 정수 모델로 변환될 수 있다.