Ganzzahlquantisierung nach dem Training

Auf TensorFlow.org ansehen In Google Colab ausführen Quelle auf GitHub anzeigen Notizbuch herunterladen

Überblick

Ganzzahlquantisierung ist eine Optimierungsstrategie, die 32-Bit-Gleitkommazahlen (wie Gewichtungen und Aktivierungsausgaben) in die nächsten 8-Bit-Festkommazahlen umwandelt. Dies führt zu einem kleineren Modell und erhöhte Inferenz Geschwindigkeit, die für Low-Power - Geräte wie wertvoll Mikrocontroller . Dieses Datenformat wird auch benötigt integer-only Beschleuniger wie der Edge - TPU .

In diesem Tutorial werden Sie ein MNIST Modell von Grund auf neu trainieren, es in eine Datei Tensorflow Lite konvertieren, und quantisiert es mit nach dem Training Quantisierung . Schließlich überprüfen Sie die Genauigkeit des konvertierten Modells und vergleichen es mit dem ursprünglichen Float-Modell.

Sie haben tatsächlich mehrere Möglichkeiten, wie stark Sie ein Modell quantisieren möchten. In diesem Tutorial führen Sie eine "Vollzahl-Quantisierung" durch, die alle Gewichtungen und Aktivierungsausgaben in 8-Bit-Ganzzahldaten umwandelt, während andere Strategien möglicherweise eine gewisse Datenmenge in Gleitkommazahlen belassen.

Mehr über die verschiedenen Strategien Quantisierung, lesen , um zu erfahren TensorFlow Lite Modelloptimierung .

Installieren

Um sowohl die Eingabe- als auch die Ausgabetensoren zu quantisieren, müssen wir APIs verwenden, die in TensorFlow r2.3 hinzugefügt wurden:

import logging
logging.getLogger("tensorflow").setLevel(logging.DEBUG)

import tensorflow as tf
import numpy as np
assert float(tf.__version__[:3]) >= 2.3

Generieren Sie ein TensorFlow-Modell

Wir werden ein einfaches Modell zu klassifizieren Zahlen aus dem Aufbau MNIST - Datensatz .

Dieses Training dauert nicht lange, da Sie das Modell nur für 5 Epochen trainieren, was mit einer Genauigkeit von etwa 98% trainiert.

# Load MNIST dataset
mnist = tf.keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# Normalize the input image so that each pixel value is between 0 to 1.
train_images = train_images.astype(np.float32) / 255.0
test_images = test_images.astype(np.float32) / 255.0

# Define the model architecture
model = tf.keras.Sequential([
  tf.keras.layers.InputLayer(input_shape=(28, 28)),
  tf.keras.layers.Reshape(target_shape=(28, 28, 1)),
  tf.keras.layers.Conv2D(filters=12, kernel_size=(3, 3), activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(10)
])

# Train the digit classification model
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(
                  from_logits=True),
              metrics=['accuracy'])
model.fit(
  train_images,
  train_labels,
  epochs=5,
  validation_data=(test_images, test_labels)
)
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step
11501568/11490434 [==============================] - 0s 0us/step
2021-08-12 11:12:54.467165: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:01.137323: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:01.138459: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:01.140544: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 AVX512F FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2021-08-12 11:13:01.141128: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:01.142112: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:01.143018: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:01.740156: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:01.741068: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:01.742003: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:01.742894: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1510] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 14648 MB memory:  -> device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:05.0, compute capability: 7.0
2021-08-12 11:13:02.680476: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:185] None of the MLIR Optimization Passes are enabled (registered 2)
Epoch 1/5
2021-08-12 11:13:04.989185: I tensorflow/stream_executor/cuda/cuda_dnn.cc:369] Loaded cuDNN version 8100
2021-08-12 11:13:09.754609: I tensorflow/core/platform/default/subprocess.cc:304] Start cannot spawn child process: No such file or directory
1875/1875 [==============================] - 12s 2ms/step - loss: 0.2685 - accuracy: 0.9276 - val_loss: 0.1161 - val_accuracy: 0.9668
Epoch 2/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.1005 - accuracy: 0.9711 - val_loss: 0.0816 - val_accuracy: 0.9743
Epoch 3/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0738 - accuracy: 0.9784 - val_loss: 0.0684 - val_accuracy: 0.9786
Epoch 4/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0610 - accuracy: 0.9823 - val_loss: 0.0599 - val_accuracy: 0.9809
Epoch 5/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0537 - accuracy: 0.9843 - val_loss: 0.0599 - val_accuracy: 0.9800
<keras.callbacks.History at 0x7fe86818fdd0>

In ein TensorFlow Lite-Modell umwandeln

Jetzt können Sie das trainierte Modell TensorFlow Lite - Format mit dem konvertieren TFLiteConverter API und unterschiedlichen Graden der Quantisierung anzuwenden.

Beachten Sie, dass einige Quantisierungsversionen einige der Daten im Float-Format belassen. Die folgenden Abschnitte zeigen also jede Option mit zunehmender Quantisierung, bis wir ein Modell erhalten, das vollständig aus int8- oder uint8-Daten besteht. (Beachten Sie, dass wir in jedem Abschnitt Code duplizieren, damit Sie alle Quantisierungsschritte für jede Option sehen können.)

Hier ist zunächst ein konvertiertes Modell ohne Quantisierung:

converter = tf.lite.TFLiteConverter.from_keras_model(model)

tflite_model = converter.convert()
2021-08-12 11:13:29.213891: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: /tmp/tmpr8l8gs6h/assets
2021-08-12 11:13:29.595758: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:29.596166: I tensorflow/core/grappler/devices.cc:66] Number of eligible GPUs (core count >= 8, compute capability >= 0.0): 1
2021-08-12 11:13:29.596275: I tensorflow/core/grappler/clusters/single_machine.cc:357] Starting new session
2021-08-12 11:13:29.596617: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:29.596976: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:29.597286: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:29.597624: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:29.597909: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:29.598191: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1510] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 14648 MB memory:  -> device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:05.0, compute capability: 7.0
2021-08-12 11:13:29.599730: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:1137] Optimization results for grappler item: graph_to_optimize
  function_optimizer: function_optimizer did nothing. time = 0.006ms.
  function_optimizer: function_optimizer did nothing. time = 0.001ms.

2021-08-12 11:13:29.632963: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-08-12 11:13:29.633013: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.
2021-08-12 11:13:29.636262: I tensorflow/compiler/mlir/tensorflow/utils/dump_mlir_util.cc:210] disabling MLIR crash reproducer, set env var `MLIR_CRASH_REPRODUCER_DIRECTORY` to enable.

Es ist jetzt ein TensorFlow Lite-Modell, verwendet aber immer noch 32-Bit-Floatwerte für alle Parameterdaten.

Konvertieren mit dynamischer Bereichsquantisierung

Nun ermöglichen wir die Standard - optimizations Flag alle festen Parameter (wie Gewichte) quantisiert:

converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]

tflite_model_quant = converter.convert()
INFO:tensorflow:Assets written to: /tmp/tmp_es5n1mh/assets
INFO:tensorflow:Assets written to: /tmp/tmp_es5n1mh/assets
2021-08-12 11:13:30.183182: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:30.183542: I tensorflow/core/grappler/devices.cc:66] Number of eligible GPUs (core count >= 8, compute capability >= 0.0): 1
2021-08-12 11:13:30.183639: I tensorflow/core/grappler/clusters/single_machine.cc:357] Starting new session
2021-08-12 11:13:30.183932: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:30.184280: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:30.184562: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:30.184902: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:30.185190: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:30.185457: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1510] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 14648 MB memory:  -> device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:05.0, compute capability: 7.0
2021-08-12 11:13:30.186996: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:1137] Optimization results for grappler item: graph_to_optimize
  function_optimizer: function_optimizer did nothing. time = 0.007ms.
  function_optimizer: function_optimizer did nothing. time = 0.001ms.

2021-08-12 11:13:30.220271: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-08-12 11:13:30.220311: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.
2021-08-12 11:13:30.239098: I tensorflow/lite/tools/optimize/quantize_weights.cc:225] Skipping quantization of tensor sequential/conv2d/Conv2D because it has fewer than 1024 elements (108).

Das Modell ist jetzt mit quantisierten Gewichten etwas kleiner, aber andere variable Daten sind immer noch im Float-Format.

Konvertieren mit Float-Fallback-Quantisierung

Um die variablen Daten (wie beispielsweise Modelleingabe / Ausgabe und Zwischenprodukte zwischen den Schichten) zu quantisieren, benötigen Sie einen bereitzustellen RepresentativeDataset . Dies ist eine Generatorfunktion, die einen Satz von Eingabedaten bereitstellt, der groß genug ist, um typische Werte darzustellen. Es ermöglicht dem Konverter, einen Dynamikbereich für alle variablen Daten abzuschätzen. (Der Datensatz muss im Vergleich zum Trainings- oder Evaluierungsdatensatz nicht eindeutig sein.) Um mehrere Eingaben zu unterstützen, ist jeder repräsentative Datenpunkt eine Liste und Elemente in der Liste werden dem Modell entsprechend ihrer Indizes zugeführt.

def representative_data_gen():
  for input_value in tf.data.Dataset.from_tensor_slices(train_images).batch(1).take(100):
    # Model has only one input so each data point has one element.
    yield [input_value]

converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_data_gen

tflite_model_quant = converter.convert()
INFO:tensorflow:Assets written to: /tmp/tmpto6jl9p5/assets
INFO:tensorflow:Assets written to: /tmp/tmpto6jl9p5/assets
2021-08-12 11:13:30.765381: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:30.765727: I tensorflow/core/grappler/devices.cc:66] Number of eligible GPUs (core count >= 8, compute capability >= 0.0): 1
2021-08-12 11:13:30.765833: I tensorflow/core/grappler/clusters/single_machine.cc:357] Starting new session
2021-08-12 11:13:30.766110: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:30.766442: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:30.766696: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:30.767005: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:30.767276: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:30.767511: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1510] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 14648 MB memory:  -> device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:05.0, compute capability: 7.0
2021-08-12 11:13:30.768907: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:1137] Optimization results for grappler item: graph_to_optimize
  function_optimizer: function_optimizer did nothing. time = 0.006ms.
  function_optimizer: function_optimizer did nothing. time = 0.001ms.

2021-08-12 11:13:30.801148: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-08-12 11:13:30.801194: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.
fully_quantize: 0, inference_type: 6, input_inference_type: 0, output_inference_type: 0

Jetzt sind alle Gewichte und Variablendaten quantisiert und das Modell ist im Vergleich zum ursprünglichen TensorFlow Lite-Modell deutlich kleiner.

Um jedoch die Kompatibilität mit Anwendungen aufrechtzuerhalten, die traditionell Float-Modell-Eingabe- und Ausgabe-Tensoren verwenden, belässt der TensorFlow Lite Converter die Modell-Ein- und Ausgabe-Tensoren in Float:

interpreter = tf.lite.Interpreter(model_content=tflite_model_quant)
input_type = interpreter.get_input_details()[0]['dtype']
print('input: ', input_type)
output_type = interpreter.get_output_details()[0]['dtype']
print('output: ', output_type)
input:  <class 'numpy.float32'>
output:  <class 'numpy.float32'>

Das ist normalerweise gut für die Kompatibilität, aber es ist nicht kompatibel mit Geräten, die nur ganzzahlbasierte Operationen ausführen, wie z. B. die Edge TPU.

Darüber hinaus kann der obige Prozess eine Operation im Float-Format belassen, wenn TensorFlow Lite keine quantisierte Implementierung für diese Operation enthält. Mit dieser Strategie kann die Konvertierung abgeschlossen werden, sodass Sie ein kleineres und effizienteres Modell haben, aber auch hier ist es nicht mit Nur-Integer-Hardware kompatibel. (Alle Ops in diesem MNIST-Modell haben eine quantisierte Implementierung.)

Um ein End-to-End-Nur-Integer-Modell zu gewährleisten, benötigen Sie also noch ein paar weitere Parameter...

Konvertieren mit Nur-Ganzzahl-Quantisierung

Um die Eingabe- und Ausgabetensoren zu quantisieren und den Konverter zu veranlassen, einen Fehler auszugeben, wenn er auf eine Operation stößt, die er nicht quantisieren kann, konvertieren Sie das Modell erneut mit einigen zusätzlichen Parametern:

def representative_data_gen():
  for input_value in tf.data.Dataset.from_tensor_slices(train_images).batch(1).take(100):
    yield [input_value]

converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_data_gen
# Ensure that if any ops can't be quantized, the converter throws an error
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
# Set the input and output tensors to uint8 (APIs added in r2.3)
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8

tflite_model_quant = converter.convert()
INFO:tensorflow:Assets written to: /tmp/tmpxgy_h2ep/assets
INFO:tensorflow:Assets written to: /tmp/tmpxgy_h2ep/assets
2021-08-12 11:13:31.923651: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:31.924011: I tensorflow/core/grappler/devices.cc:66] Number of eligible GPUs (core count >= 8, compute capability >= 0.0): 1
2021-08-12 11:13:31.924120: I tensorflow/core/grappler/clusters/single_machine.cc:357] Starting new session
2021-08-12 11:13:31.924488: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:31.924820: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:31.925086: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:31.925436: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:31.925710: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-12 11:13:31.925943: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1510] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 14648 MB memory:  -> device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:05.0, compute capability: 7.0
2021-08-12 11:13:31.927262: I tensorflow/core/grappler/optimizers/meta_optimizer.cc:1137] Optimization results for grappler item: graph_to_optimize
  function_optimizer: function_optimizer did nothing. time = 0.006ms.
  function_optimizer: function_optimizer did nothing. time = 0.001ms.

2021-08-12 11:13:31.957254: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-08-12 11:13:31.957284: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.
fully_quantize: 0, inference_type: 6, input_inference_type: 3, output_inference_type: 3
WARNING:absl:For model inputs containing unsupported operations which cannot be quantized, the `inference_input_type` attribute will default to the original type.

Die interne Quantisierung bleibt die gleiche wie oben, aber Sie können sehen, dass die Eingabe- und Ausgabetensoren jetzt ganzzahliges Format haben:

interpreter = tf.lite.Interpreter(model_content=tflite_model_quant)
input_type = interpreter.get_input_details()[0]['dtype']
print('input: ', input_type)
output_type = interpreter.get_output_details()[0]['dtype']
print('output: ', output_type)
input:  <class 'numpy.uint8'>
output:  <class 'numpy.uint8'>

Jetzt haben Sie eine ganze Zahl quantisiert Modell , dass Anwendungen Integer - Daten für die Eingabe des Modells und Ausgang Tensoren, also ist es kompatibel mit integer-only - Hardware wie der Edge - TPU .

Speichern Sie die Modelle als Dateien

Sie erhalten eine benötigen .tflite Datei Ihr Modell auf anderen Geräten zu implementieren. Lassen Sie uns also die konvertierten Modelle in Dateien speichern und sie dann laden, wenn wir die folgenden Inferenzen ausführen.

import pathlib

tflite_models_dir = pathlib.Path("/tmp/mnist_tflite_models/")
tflite_models_dir.mkdir(exist_ok=True, parents=True)

# Save the unquantized/float model:
tflite_model_file = tflite_models_dir/"mnist_model.tflite"
tflite_model_file.write_bytes(tflite_model)
# Save the quantized model:
tflite_model_quant_file = tflite_models_dir/"mnist_model_quant.tflite"
tflite_model_quant_file.write_bytes(tflite_model_quant)
24280

Führen Sie die TensorFlow Lite-Modelle aus

Jetzt werden wir Schlüsse laufen die TensorFlow Lite mit Interpreter die Modellgenauigkeit zu vergleichen.

Zuerst benötigen wir eine Funktion, die eine Inferenz mit einem bestimmten Modell und Bildern durchführt und dann die Vorhersagen zurückgibt:

# Helper function to run inference on a TFLite model
def run_tflite_model(tflite_file, test_image_indices):
  global test_images

  # Initialize the interpreter
  interpreter = tf.lite.Interpreter(model_path=str(tflite_file))
  interpreter.allocate_tensors()

  input_details = interpreter.get_input_details()[0]
  output_details = interpreter.get_output_details()[0]

  predictions = np.zeros((len(test_image_indices),), dtype=int)
  for i, test_image_index in enumerate(test_image_indices):
    test_image = test_images[test_image_index]
    test_label = test_labels[test_image_index]

    # Check if the input type is quantized, then rescale input data to uint8
    if input_details['dtype'] == np.uint8:
      input_scale, input_zero_point = input_details["quantization"]
      test_image = test_image / input_scale + input_zero_point

    test_image = np.expand_dims(test_image, axis=0).astype(input_details["dtype"])
    interpreter.set_tensor(input_details["index"], test_image)
    interpreter.invoke()
    output = interpreter.get_tensor(output_details["index"])[0]

    predictions[i] = output.argmax()

  return predictions

Testen Sie die Modelle auf einem Bild

Jetzt vergleichen wir die Leistung des Float-Modells und des quantisierten Modells:

  • tflite_model_file ist das ursprüngliche TensorFlow Lite - Modell mit Gleitkommadaten.
  • tflite_model_quant_file ist das letzte Modell , das wir nur ganzzahlige-Quantisierung unter Verwendung umgewandelt (es verwendet uint8 Daten zur Eingabe und Ausgabe).

Lassen Sie uns eine weitere Funktion erstellen, um unsere Vorhersagen zu drucken:

import matplotlib.pylab as plt

# Change this to test a different image
test_image_index = 1

## Helper function to test the models on one image
def test_model(tflite_file, test_image_index, model_type):
  global test_labels

  predictions = run_tflite_model(tflite_file, [test_image_index])

  plt.imshow(test_images[test_image_index])
  template = model_type + " Model \n True:{true}, Predicted:{predict}"
  _ = plt.title(template.format(true= str(test_labels[test_image_index]), predict=str(predictions[0])))
  plt.grid(False)

Testen Sie nun das Float-Modell:

test_model(tflite_model_file, test_image_index, model_type="Float")

png

Und testen Sie das quantisierte Modell:

test_model(tflite_model_quant_file, test_image_index, model_type="Quantized")

png

Bewerten Sie die Modelle auf allen Bildern

Lassen Sie uns nun beide Modelle mit allen Testbildern ausführen, die wir zu Beginn dieses Tutorials geladen haben:

# Helper function to evaluate a TFLite model on all images
def evaluate_model(tflite_file, model_type):
  global test_images
  global test_labels

  test_image_indices = range(test_images.shape[0])
  predictions = run_tflite_model(tflite_file, test_image_indices)

  accuracy = (np.sum(test_labels== predictions) * 100) / len(test_images)

  print('%s model accuracy is %.4f%% (Number of test samples=%d)' % (
      model_type, accuracy, len(test_images)))

Bewerten Sie das Float-Modell:

evaluate_model(tflite_model_file, model_type="Float")
Float model accuracy is 98.0000% (Number of test samples=10000)

Bewerten Sie das quantisierte Modell:

evaluate_model(tflite_model_quant_file, model_type="Quantized")
Quantized model accuracy is 97.9700% (Number of test samples=10000)

Sie haben jetzt also ein ganzzahliges quantisiertes Modell mit fast keinem Unterschied in der Genauigkeit im Vergleich zum Float-Modell.

Mehr über andere Quantisierung Strategien, lesen , um zu erfahren TensorFlow Lite Modelloptimierung .