論文紹介：OmniQuant: Omnidirectionally Calibrated Quantization for Large Language Models

# 紹介する論文

https://arxiv.org/abs/2308.13137

タイトル：OmniQuant: Omnidirectionally Calibrated Quantization for Large Language Models
学会：ICLR2024

OmniQuantは学習ベースの量子化方法です。Learnable Weight Clipping (LWC)とLearnable Equivalent Transformation (LET)の2つの工夫を持ち、学習でパラメータを決めます。

画像・数式は論文から引用しています。

# Learnable Equivalent Transformation (LET)

LETの考え方は[SmoothQuant](https://qiita.com/kyad/items/894bea24fdd0ed79318b)に似ています。つまり、線形層においてチャンネル毎にアクティベーションを$1/s$倍、重みを$s$倍して、アクティベーションの外れ値を重みに移そうというものです。
SmoothQuantとの違いを挙げます。

(1) SmoothQuantでは線形層がバイアス無しの場合で定義されていましたが、LETではバイアス有りの場合でも定義されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/d379dbe9-9ca0-4201-ad51-16d5bbf0dc0e.png)

(2) SmoothQuantは、SelfAttentionの最初のLayerNorm〜線形層とFFNの最初のLayerNorm〜線形層間でのみ変換を適用していましたが、LETではFFNの2個目の線形層を除く全ての線形層の直前に変換を適用します。
[この記事](https://qiita.com/kyad/items/894bea24fdd0ed79318b)ではLayerNorm〜線形層で変換を適用できることを説明しましたが、線形層〜線形層でも$\mathrm{diag}(\mathbf{s})^{-1}$を直前の線形層の重みに適用することによって変換を適用できます。

バイアスが無い場合で確認しましょう。重み$\mathbf{W}$の線形層への入力が$\mathbf{X}$、出力が$\mathbf{Y}$であるとします。この1つ前の線形層の重みが$\mathbf{W}’$、入力が$\mathbf{X}’$とします。この時
```math
\mathbf{Y}=\mathbf{X}\mathbf{W},
```
```math
\mathbf{X}=\mathbf{X}’\mathbf{W}’
```
が成り立ちますので、
```math
\mathbf{Y}=\mathbf{X}\mathrm{diag}(\mathbf{s})^{-1}\mathrm{diag}(\mathbf{s})\mathbf{W}=\hat{\mathbf{X}}\hat{\mathbf{W}},
```
```math
\hat{\mathbf{X}}=\mathbf{X}\mathrm{diag}(\mathbf{s})^{-1}=\mathbf{X}’\mathbf{W}’\mathrm{diag}(\mathbf{s})^{-1}=\mathbf{X}’\hat{\mathbf{W}}’
```
です。ここで、$\hat{\mathbf{X}}=\mathbf{X}\mathrm{diag}(\mathbf{s})^{-1}, \hat{\mathbf{W}}=\mathrm{diag}(\mathbf{s})\mathbf{W}, \hat{\mathbf{W}}’=\mathbf{W}’\mathrm{diag}(\mathbf{s})^{-1}$と置きました。
従って、線形層の重みに左からスケーリングパラメータ$\mathrm{diag}(\mathbf{s})$を掛けるのと同時に、一つ前の線形層の重みに右から$\mathrm{diag}(\mathbf{s})^{-1}$を掛けておけば良いということです。図で書くと下図のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/0697db94-6968-4856-9906-e2e2fe430329.png)

加えて、OmniQuantでは$\mathbf{Q}\mathbf{K}^T$の計算でも同様の変換を適用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/ffcdefdd-b566-4161-be0d-689bfd44cf73.png)

(3) SmoothQuantでは、スケーリングパラメータ$\mathbf{s}$は人が決めていましたが、LETでは学習で決めます。具体的な方法は後で述べます。


# Learnable Weight Clipping (LWC)

LWCの考え方は[PACT](https://arxiv.org/abs/1805.06085)に似ています。非常に大きな外れ値がある場合、大きな外れ値を正確に量子化することを諦めて、それ以外をなるべく正確に量子化しようというものです。
例えば、[0, 128, 255, 255000]を(a)のように全て量子化しようとすると、0, 128, 255がつぶれて0になってしまいますが、(b)のように大きな255000は正しい量子化を諦める(clippingと言います)と、それ以外の値は正確に量子化できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/45ca611c-5f4c-4fdc-9442-0c961b535380.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/60d97dee-ec7d-4e3d-ba80-3e8855e9b844.png)

LWCではclip幅$\beta, \gamma$を学習で決めます。重み$\mathbf{W}$の最小値・最大値に対する比$\beta, \gamma (0\le\beta, \gamma\le 1)$を学習で決め、$\beta\min(\mathbf{W})$以下と$\gamma\max(\mathbf{W})$以上はclipします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/68443894-a720-4535-81cd-a913688330a8.png)

式で書くと(2)式のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/3d71d892-8d0a-4af5-a023-4a919dfc3a96.png)


# Block-wise Quantization Error Minimization

OmniQuantでは、以上に述べた学習パラメータを学習で決めるのですが、そもそも学習に大きな計算量がかかるLLMに対して全てを同時に学習するのは大変です。
そこで、全ての学習パラメータを同時に決めるのではなく、Transformerブロック毎に先頭から最適化していくことによって学習パラメータを決めることを提案しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/c3e48b95-4891-4cbc-a3fc-c7620e52e16f.png)

ここで、$\Theta_1, \Theta_2$はそれぞれLWCとLETの学習パラメータの集合、$Q_w(\cdot), Q_a(\cdot)$はそれぞれ重みとアクティベーションの量子化です。
実験では、SmoothQuantで得られたパラメータを初期値に、WikiText2からキャリブレーション用データを128個ランダムに選択して学習しています。


# 実験

重みのみ量子化方法では[GPTQ](https://qiita.com/kyad/items/8a2ff5206bb28b2eab0d)や[AWQ](https://qiita.com/kyad/items/96a4a2bdec3f0dc09d23)と、重み・アクティベーション量子化方法では[SmoothQuant](https://qiita.com/kyad/items/894bea24fdd0ed79318b)などと比較し、性能悪化が小さいことを示しています。