ディープニューラルネットワークの量子化についてざっくりまとめた

機械学習

はじめに

ディープニューラルネットワーク(DNN)のモデルを圧縮する技術の代表的な手法のひとつに量子化があります。量子化ではモデルの重み等のパラメータの量子化ビット数を下げることでモデルサイズを縮小し、計算の高速化を行います。

量子化についてざっくりと学びたいと思い、A Survey of Quantization Methods for Efficient Neural Network Inferenceという量子化に関するサーベイ論文を読んだので、その内容をもとにニューラルネットワークの量子化の基礎的な部分(論文中でいうとセクション3に相当)についてまとめていこうと思います。

なお、セクション4で述べられているMixed-precision QuantizationやExtreme Quantization, Vector Quantizationについては後日まとめたいと思います。

PyTorchで実際に量子化を行ってみた記事は↓

PyTorchの量子化をかるく動かしてみる【Quantization】
はじめにPyTorchでは、ディープラーニングのモデルを量子化する様々な方法が用意されています。今回はPyTorchでサポートされている量子化方法について、PyTorchのドキュメントに記載されているコードをベースに確認していこう...

Uniform QuantizationとNon-uniform Quantization

実数値\(r\)の量子化は以下の式で表すことができます。ここで、\(S\)はスケーリングファクター、\(Z\)は整数のゼロ点であり、Int関数は実数値から整数値への丸めを意味しています。
この量子化はUniform Quantizationといい、量子化後の値は等間隔に配置されることになります。



また、量子化後の値が等間隔にならないNon-uniform Quantizationも存在します。


実数値\(r\)は、dequantizationと呼ばれる手法により復元することが可能です。ただし、量子化時に丸めによる誤差が発生するため、完全に元の値へと復元することはできません。


Symmetric QuantizationとAsymmetric Quantization

uniform quantizationにおいて、スケーリングファクター\(S\)の選択が非常に重要になってきます。スケーリングファクターは、量子化前の実数値rの範囲をいくつかの範囲に分割します。

以下の式で、\([\alpha, \beta]\)は実数値のクリッピングされる範囲を、\(b\)は量子化ビット数を示します。スケーリングファクターを決定するためには、この\([\alpha, \beta]\)を決める必要があり、このレンジを設定することをキャリブレーションと呼びます。


シンプルな方法としては\(\alpha\)を\(r\)の最小値\(r_{min}\)、\(\beta\)を\(r\)の最大値\(r_{max}\)とする方法があり、これをasymmetric quantizationといいます。クリッピングされる範囲が原点に対して対象でない(\(\alpha\neq-\beta\))ため、下図のようにゼロに対して非対称な量子化となります。


これに対し、\(\alpha=-\beta\)のとする方法をsymmetric quantizationといいます。この方法ではゼロ点の位置が維持され、下図のようにゼロに対し対称な量子化となります。


Asymmetric quantizationの利点は、量子化する値の分布がゼロに対して偏っている場合に精度良く量子化できる点です。一方、symmetric quantizationの利点はゼロ点\(Z\)をゼロとすることができるため、計算効率が良い点です。

スケーリングファクターを決定する際に一般的なのは、min/max値を用いる手法だが、外れ値の影響を受けやすいという欠点があります。外れ値によって量子化する範囲を不必要に広くとってしまい、量子化の精度が低下してしまうということです。
この他には、分布のパーセンタイル(\(i\)番目の値)や、KLダイバージェンスを最小化するようになる値を探すなど、様々なスケーリングファクターの決定方法が存在する。

Static QuantizationとDynamic Quantization

上述のクリッピング範囲をいつ決定するのかも量子化において重要な要素の一つで、これを推論時に動的に決定する手法をDynamic Quantization(動的量子化)、事前に決定しておいて推論時には固定する手法をStatic Quantization(静的量子化) といいます。

一般的に、重みは推論時に変動することがないため、静的量子化を用います。activation(各層の出力値)に関しては、入力する値に応じてレンジが変動するため、動的量子化を用いることがあります。動的にスケーリングファクターを求めることで、静的量子化よりも高い量子化精度が得られるますが、リアルタイムに値のmin/max値やパーセンタイルを計算する必要があり、計算量が増大してしまうという欠点があります。

量子化の粒度について

量子化は各層のテンソルごとに行うのが一般的ですが、より細かな単位で行うことも可能です。
例えば、畳み込み層の重みを量子化する場合は、チャンネルごとに異なる量子化パラメータを設定することもできます。こうした、量子化を行う単位のことをgranularity(直訳すると粒度)というそうです。

下図の例だと、Layerwise Quantizationは層ごとに量子化を行う手法であり、Channelwise Quantizationはチャンネルごとに量子化を行う手法を表しています。

Layerwise Quantizationは実装が容易ですが、チャンネルごとに重みのレンジが異なる場合などに、量子化誤差の大きいチャンネルができてしまい、量子化精度が低い傾向にあります。一方、Channelwise Quantizationの方がより細かな粒度で量子化するため、精度が高い傾向にあります。

他にも、Groupwise Quantizationや、Sub-channelwise Quantizationなどの手法も存在します。


Quantization Aware TrainingとPost Training Quantization

量子化の手法は大きく分けてQuantization Aware Training(QAT)Post Training Quantization(PTQ) があります。

QATでは量子化による誤差を考慮した学習を行い、PTQでは学習後にモデルを量子化します。一般的には、QATの方がより高い精度となると言われています。しかし、量子化プロセスで学習データを必要とする点や、計算コストがかかる点などが欠点として挙げられていました。

QAT

QATでは、下図のように浮動小数点数で量子化された重みを用いて、Forward/Backward passを行います。Backward passの際、量子化関数は微分不可能なため、Straight Through Estimator(STE) という手法で勾配計算を行います。これは、勾配計算時に量子化関数を恒等関数として扱うという方法です。

PTQ

PTQは学習済みのモデルに対して量子化を行う方法で、量子化後に再学習は行いません。このため、量子化の際にデータが不要という利点があります。しかし、特に量子化ビット数の小さい量子化ではQATと比較して精度が低下しがちで、この精度低下を緩和させるためのアプローチが多数提案されているそうです。

参考文献

  1. Gholami, Amir, et al. “A survey of quantization methods for efficient neural network inference.” arXiv preprint arXiv:2103.13630 (2021).
  2. Pytorchの量子化ドキュメント

コメント

タイトルとURLをコピーしました