トレーニング後の量子化は、モデルの精度をほとんど低下させることなく、モデルサイズを小さくしながら CPU とハードウェア アクセラレータのレイテンシを改善できる変換手法です。TensorFlow Lite コンバータを使用して TensorFlow Lite 形式に変換する場合は、トレーニング済みの浮動小数点 TensorFlow モデルを量子化できます。
最適化手法
トレーニング後の量子化オプションはいくつかあります。次の表に、選択肢とそれぞれのメリットを示します。
技術 | 利点 | ハードウェア |
---|---|---|
ダイナミック レンジ量子化 | 4 分の 1 サイズ、2 ~ 3 倍の高速化 | CPU |
完全整数量子化 | サイズが 4 分の 1、速度が 3 倍以上 | CPU、Edge TPU、マイクロコントローラ |
Float16 量子化 | 2 分の 1 の GPU アクセラレーション | CPU、GPU |
次のディシジョン ツリーは、ユースケースに最適なトレーニング後の量子化方法を判断するのに役立ちます。
量子化なし
開始点として、量子化を使用せずに TFLite モデルに変換することをおすすめします。これにより、浮動小数点型の TFLite モデルが生成されます。
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) tflite_quant_model = converter.convert()
これを最初のステップとして、元の TF モデルの演算子が TFLite と互換性があり、その後のトレーニング後の量子化方法によって生じる量子化エラーをデバッグするためのベースラインとして使用できることを検証することをおすすめします。たとえば、量子化 TFLite モデルが予期しない結果をもたらす場合、浮動小数点 TFLite モデルは正確ですが、TFLite 演算子の量子化バージョンによって生じるエラーに問題を絞り込めます。
ダイナミック レンジの量子化
ダイナミック レンジの量子化により、キャリブレーション用の代表的なデータセットを用意しなくても、メモリ使用量を減らし、計算を高速化できます。このタイプの量子化では、変換時に浮動小数点から整数への重みのみを静的に量子化します。これにより、8 ビットの精度が得られます。
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.optimizations = [tf.lite.Optimize.DEFAULT] tflite_quant_model = converter.convert()
推論時のレイテンシをさらに短縮するために、「ダイナミック レンジ」演算子は 8 ビットの範囲に基づいて活性化を動的に量子化し、8 ビットの重みと活性化を使用して計算を実行します。この最適化により、完全固定小数点推論に近いレイテンシが得られます。ただし、出力は引き続き浮動小数点数を使用して保存されるため、ダイナミック レンジ演算の速度の向上は、完全な固定小数点計算よりも少なくなります。
完全整数量子化
すべてのモデル計算を整数量子化することで、レイテンシのさらなる改善、ピークメモリ使用量の削減、整数のみのハードウェア デバイスまたはアクセラレータとの互換性を実現できます。
完全な整数量子化では、範囲のキャリブレーションまたは推定が必要です。つまり、モデル内のすべての浮動小数点テンソルの (min, max)。重みやバイアスなどの定数テンソルとは異なり、モデル入力、活性化(中間レイヤの出力)、モデル出力などの変数テンソルは、推論サイクルを数回実行しない限り調整できません。そのため、コンバータには、キャリブレーションのために代表的なデータセットが必要になります。このデータセットは、トレーニング データまたは検証データの小さなサブセット(約 100 ~ 500 サンプル)にできます。以下の representative_dataset()
関数をご覧ください。
TensorFlow 2.7 バージョンからは、次の例のように、署名を使用して代表的なデータセットを指定できます。
def representative_dataset(): for data in dataset: yield { "image": data.image, "bias": data.bias, }
特定の TensorFlow モデルに複数の署名がある場合は、署名キーを指定して複数のデータセットを指定できます。
def representative_dataset(): # Feed data set for the "encode" signature. for data in encode_signature_dataset: yield ( "encode", { "image": data.image, "bias": data.bias, } ) # Feed data set for the "decode" signature. for data in decode_signature_dataset: yield ( "decode", { "image": data.image, "hint": data.hint, }, )
入力テンソルのリストを指定して、代表的なデータセットを生成できます。
def representative_dataset(): for data in tf.data.Dataset.from_tensor_slices((images)).batch(1).take(100): yield [tf.dtypes.cast(data, tf.float32)]
TensorFlow 2.7 バージョン以降では、入力テンソルのリストベースのアプローチではなく、シグネチャベースのアプローチを使用することをおすすめします。これは、入力テンソルの順序を簡単に反転できるためです。
テスト目的で、次のようにダミー データセットを使用できます。
def representative_dataset(): for _ in range(100): data = np.random.rand(1, 244, 244, 3) yield [data.astype(np.float32)]
浮動小数点数によるフォールバックありの整数(デフォルトの浮動小数点入力/出力を使用)
モデルを完全に整数化し、整数実装がない場合に浮動小数点演算子を使用する(変換をスムーズに行うため)には、次の手順を使用します。
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.representative_dataset = representative_dataset tflite_quant_model = converter.convert()
整数のみ
整数のみのモデルの作成は、TensorFlow Lite for Microcontrollers と Coral Edge TPU の一般的なユースケースです。
さらに、整数のみのデバイス(8 ビット マイクロコントローラなど)やアクセラレータ(Coral Edge TPU など)との互換性を確保するために、次の手順で、入力と出力を含むすべてのオペレーションに完全な整数の量子化を適用できます。
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.representative_dataset = representative_dataset converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] converter.inference_input_type = tf.int8 # or tf.uint8 converter.inference_output_type = tf.int8 # or tf.uint8 tflite_quant_model = converter.convert()
Float16 量子化
16 ビット浮動小数点数の IEEE 標準である float16 に重みを量子化することで、浮動小数点モデルのサイズを小さくできます。重みの float16 量子化を有効にするには、次の手順を行います。
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.target_spec.supported_types = [tf.float16] tflite_quant_model = converter.convert()
float16 の量子化の利点は次のとおりです。
- モデルサイズを最大半分に削減できます(すべての重みが元のサイズの半分になるため)。
- 精度の低下は最小限に抑えられます。
- float16 データを直接操作できる一部のデリゲート(GPU デリゲートなど)をサポートしているため、float32 の計算よりも高速に実行されます。
float16 の量子化のデメリットは次のとおりです。
- 固定小数点計算の量子化ほどレイテンシは短縮されません。
- デフォルトでは、float16 量子化モデルは、CPU で実行すると重み値を float32 に「逆量子化」します。(GPU デリゲートは float16 データに対して処理できるため、この逆量子化は行いません)。
整数のみ: 8 ビットの重みで 16 ビットのアクティベーション(試験運用版)
これは試験運用中の量子化スキームです。これは「整数のみ」のスキームに似ていますが、活性化は 16 ビットの範囲に基づいて量子化され、重みは 8 ビット整数で量子化され、バイアスは 64 ビット整数に量子化されます。これを 16x8 量子化と呼びます。
この量子化の主な利点は、精度を大幅に向上できるが、モデルサイズをわずかに増加させるだけです。
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.representative_dataset = representative_dataset converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8] tflite_quant_model = converter.convert()
モデル内の一部の演算子で 16x8 の量子化がサポートされていない場合、モデルは引き続き量子化できますが、サポートされていない演算子は浮動小数点数で保持されます。このためには、target_spec に次のオプションを追加する必要があります。
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.representative_dataset = representative_dataset converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8, tf.lite.OpsSet.TFLITE_BUILTINS] tflite_quant_model = converter.convert()
この量子化スキームによって精度が向上するユースケースの例は次のとおりです。
- super-resolution,
- オーディオ信号処理(ノイズ キャンセリングやビームフォーミング、
- 画像ノイズ除去、
- 単一の画像からの HDR 再構成。
この量子化の欠点は次のとおりです。
- 現時点では、最適化されたカーネル実装がないため、推論は 8 ビットの完全整数よりも著しく遅くなります。
- 現在、ハードウェア アクセラレーションされている既存の TFLite デリゲートとは互換性がありません。
この量子化モードのチュートリアルについては、こちらをご覧ください。
モデルの精度
重みはトレーニング後に量子化されるため、特に小規模なネットワークでは精度が低下する可能性があります。事前トレーニング済みの完全に量子化されたモデルは、特定のネットワーク用に Kaggle モデルで提供されています。量子化モデルの精度をチェックして、精度の低下が許容範囲内であることを確認することが重要です。TensorFlow Lite モデルの精度を評価するツールがあります。
また、精度の低下が高すぎる場合は、量子化認識トレーニングの使用を検討してください。ただし、これを行うには、偽の量子化ノードを追加するようにモデルのトレーニング中に変更を加える必要がありますが、このページのトレーニング後の量子化手法では、既存の事前トレーニング済みモデルを使用します。
量子化テンソルの表現
8 ビットの量子化では、次の式を使用して浮動小数点値を近似します。
\[real\_value = (int8\_value - zero\_point) \times scale\]
この表現は、主に次の 2 つの部分で構成されています。
軸ごと(チャンネルごと)またはテンソルごとの重み。ゼロ点が 0 で、範囲 [-127, 127] の int8 2 の補数値によって表されます。
テンソルごとの活性化/入力。これは、範囲 [-128, 127] の int8 の 2 の補数値で表され、範囲 [-128, 127] にはゼロ点があります。
量子化スキームの詳細については、量子化仕様をご覧ください。TensorFlow Lite のデリゲート インターフェースに接続するハードウェア ベンダーは、ここで説明する量子化スキームを実装することをおすすめします。