量子化は、実数の大規模なセットの値を小さな離散セットの値にマッピングするプロセスとして定義できます。通常、これには連続入力を出力の固定値にマッピングすることが含まれます。これを実現する一般的な方法は、四捨五入または切り捨てです。四捨五入の場合は、最も近い整数を計算します。たとえば、値 1.8 は 2 になります。ただし、値 1.2 は 1 になります。切り捨ての場合は、小数点以下の値を盲目的に削除して、入力を整数に変換します。
どちらの方法で進めるにせよ、ディープ ニューラル ネットワークの量子化の背後にある主な動機は、言うまでもなく、ニューラル ネットワークの推論とトレーニングには計算コストが非常にかかるため、推論速度を向上させることです。 大規模言語モデルの出現により、これらのモデルのパラメータの数は増加するばかりで、メモリ フットプリントはますます増大することを意味します。
これらのニューラル ネットワークの進化のスピードに伴い、ラップトップや携帯電話、さらには時計などの小型デバイスでもこれらのニューラル ネットワークを実行する需要が高まっています。これらはどれも量子化なしでは不可能です。
量子化に入る前に、トレーニングされたニューラル ネットワークはコンピューターのメモリに保存されている単なる浮動小数点であることを忘れないでください。
コンピューターに数値を格納するためのよく知られた表現または形式には、float32 または FP32、float16 または FP16、int8、bfloat16 (B は Google Brain を表します)、または最近では、行列またはテンソルを処理するための特殊な形式である tensor float 32 または TF32 などがあります。オペレーション。これらの各形式は、メモリの異なるチャンクを消費します。たとえば、float32 は、符号に 1 ビット、指数に 8 ビット、仮数に 23 ビットを割り当てます。
同様に、float16 または FP16 は、符号に 1 ビットを割り当てますが、指数には 5 ビット、仮数には 10 ビットだけを割り当てます。一方、BF16 は指数に 8 ビットを割り当て、仮数には 7 ビットだけを割り当てます。
表現は十分です。私が言いたいのは、高位のメモリ形式から低位のメモリ形式への変換を量子化と呼ぶということです。深層学習の用語で言えば、Float32 は単精度または全精度と呼ばれ、 Float16 および BFloat16 は半精度と呼ばれます。深層学習モデルがトレーニングおよび保存されるデフォルトの方法は、完全な精度です。最も一般的に使用される変換は、完全精度から int8 形式への変換です。
量子化は均一または不均一にすることができます。均一の場合、入力から出力へのマッピングは線形関数となり、均一な間隔の入力に対して均一な間隔の出力が得られます。不均一の場合、入力から出力へのマッピングは非線形関数であるため、均一な入力に対して出力は均一な間隔にはなりません。
均一タイプについて詳しく説明すると、線形マッピング関数はスケーリングと丸めの操作になります。したがって、均一な量子化には、方程式内のスケーリング係数Sが含まれます。
たとえば float16 から int8 に変換する場合、常に -127 とプラス 127 の間の値に制限でき、入力のゼロが出力のゼロに完全にマッピングされて対称マッピングが得られることを保証できることに注意してください。したがって、この量子化は対称と呼ばれます。量子化。
一方、ゼロの両側の値が同じでない場合 (たとえば、-128 と +127 の間)。さらに、入力のゼロを出力のゼロ以外の値にマッピングしている場合、それは非対称量子化と呼ばれます。出力ではゼロ値がシフトされているため、方程式にゼロ係数Z を含めて、これを計算する必要があります。
スケール係数とゼロ点を選択する方法を学ぶために、実数軸で上の図のように分散された入力の例を見てみましょう。スケール係数は基本的に、最小値r_minから最大値r_maxまでの入力範囲全体を均等なパーティションに分割します。ただし、この入力をある時点で、たとえば負の値の場合はアルファ、正の値の場合はベータでクリップすることを選択できます。アルファとベータを超える値は、アルファと同じ出力にマップされるため、意味がありません。この例では、-127 と +127 です。これらのクリッピング値アルファとベータ、つまりクリッピング範囲を選択するプロセスは、キャリブレーションと呼ばれます。
過剰なクリッピングを防ぐために、最も簡単なオプションは、alpha を r_min に等しく、beta を r_max に等しく設定することです。そして、これらのr_minとr_maxの値を使用して、スケール係数Sを計算できます。ただし、これにより出力が非対称になる可能性があります。たとえば、入力のr_max は1.5 ですが、 r_min は-1.2 のみになる可能性があります。したがって、対称量子化に制約するには、アルファとベータが 2 つの最大値である必要があり、もちろんゼロ点を 0 に設定する必要があります。
対称量子化は、トレーニングされた重みが推論中にすでに事前に計算されており、推論中に変更されないため、ニューラル ネットワークの重みを量子化するときに正確に使用されます。ゼロ点が 0 に設定されるため、非対称の場合に比べて計算も簡単になります。
ここで、入力が一方向、たとえば正側に偏っている例を見てみましょう。これは、ReLU や GeLU などの最も成功したアクティベーション関数の出力に似ています。さらに、アクティベーションの出力は入力に応じて変化します。たとえば、猫の 2 つの画像を表示すると、活性化関数の出力はまったく異なります。ここで問題となるのは、「量子化の範囲をいつ校正するか?」ということです。トレーニング中ですか?それとも推論中、予測用のデータを取得するときでしょうか?
この疑問は、特にポスト トレーニング量子化(PTQ) におけるさまざまな量子化モードにつながります。 PTQ では、追加のトレーニングを行わずに、事前トレーニングされたモデルから開始します。モデルに必要な重要なデータには、クリッピング範囲の計算に使用されるキャリブレーション データ、およびその後のスケール ファクター (S) とゼロ点 (Z) が含まれます。通常、この校正データはモデルの重量から導出されます。キャリブレーション プロセスの後、モデルの量子化に進むことができ、量子化されたモデルが得られます。
量子化対応トレーニング(略して QAT) では、標準的な手順を使用してトレーニングされたモデルを量子化しますが、量子化されたモデルを取得するために新しいトレーニング データを使用してさらに微調整または再トレーニングを行います。 QAT は通常、量子化中に失われた精度やその他の懸念されるメトリックを回復するために、モデルのパラメーターを調整するために行われます。したがって、QAT はトレーニング後の量子化よりも優れたモデルを提供する傾向があります。
微調整を行うには、モデルが微分可能である必要があります。ただし、量子化操作は微分不可能です。これを克服するために、ストレートスルー推定器などの偽の量子化器を使用します。微調整中に、これらの推定器は量子化の誤差を推定し、その誤差がトレーニング誤差と組み合わされて、パフォーマンスが向上するようにモデルを微調整します。微調整中、前方パスと後方パスは浮動小数点の量子化モデルに対して実行されます。ただし、パラメーターは各勾配の更新後に量子化されます。
深層学習におけるモデルの量子化を説明する以下のビデオをご覧ください。
これで量子化の基本がほぼカバーされます。私たちは量子化の必要性と、対称や非対称などのさまざまなタイプの量子化について説明しました。また、量子化パラメーター、つまりスケール ファクターとゼロ点を選択する方法もすぐに学びました。そして、さまざまな量子化モードで終了しました。しかし、これらはすべて PyTorch または TensorFlow でどのように実装されるのでしょうか?それはまた別の日に。このビデオが深層学習における量子化についての洞察を提供できれば幸いです。
次回もよろしくお願いします。それまで気をつけてね!