Uniform Quantization
Transforms value $w$ -> quantized value $w_q$.
by \(w_q = \text{clamp}(\text{round}(\frac{w}{s_q} + z))\)
- $w \in [\beta, \alpha]$
- $w_q \in [0, 2^b-1]$
- $b$ is the number of bits used in the quantization process.
- $s_q=\frac{\alpha - \beta}{2^b - 1}$ is the scale factor
- $z=-\text{round}(\beta \frac{\beta - \alpha}{2^b - 1})$ is the zero point.
w는 weight $W$의 row-wise하게 group size개씩 묶어서 계산한다. (memory order에 따라 128개씩 묶은 것이 의미있을까?)
Channel and Activation
$Y = XW$일 때, X는 (n, input dim)차원, W는 (input dim, output dim) 차원이다. W의 Row를 채널이라 하고, X의 Columns 액티베이션이라 하는 것 같다. 이 네이밍 컨벤션은 어디서 왔는지 모르겠다 (따라서 이해하는데 상당히 헷갈렸다)
Activation Aware Quantization
-
관찰 1: 특정 channel에 어떤 상수 $s$를 곱해주고 quantize한 뒤, 어떤 상수 $c$로 다시 나눠주면 그 특정 채널의 값의 Quantization Error가 감소한다.
-
관찰 2: Activation이 클 수록 Salient Channel일 수 있다.
$s_x = $ s에 매칭되는 activation들의 평균값. (이걸 왜 x_max라고 표현했는지도 역시 이해가 안 간다)
\(\text{minimize } [Q(w \cdot s_x^a) (s_x^a)^{-1}W - WX]\) where $a$ in range(0, 1, 0.05) 에 대해 quantization error를 계산하고, 그 중 최소값을 찾는다.
근데 실제 구현은 약간 달라서, 뭔가 이상하다
scale factor를 계산한 뒤, s = s / (s.max() * s.min()).rsqrt()를 해준다. (이건 뭔가 이상하다)
이렇게 per channel(or per group)별 scale factor $s$를 찾아줘서, quantization/dequantization시 활용하는 것이 AWQ 알고리즘의 핵심(인 것 같다)