Ganzzahlquantisierung nach dem Training mit int16-Aktivierungen

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

Überblick

TensorFlow Lite unterstützt jetzt die Konvertierung von Aktivierungen in 16-Bit-Ganzzahlwerte und Gewichte in 8-Bit-Ganzzahlwerte während der Modellkonvertierung von TensorFlow in das Flat Buffer-Format von TensorFlow Lite. Wir bezeichnen diesen Modus als "16x8-Quantisierungsmodus". Dieser Modus kann die Genauigkeit des quantisierten Modells erheblich verbessern, wenn Aktivierungen für die Quantisierung empfindlich sind, während die Modellgröße immer noch fast um das 3-4-fache reduziert wird. Darüber hinaus kann dieses vollständig quantisierte Modell von nur ganzzahligen Hardwarebeschleunigern verwendet werden.

Einige Beispiele für Modelle, die von diesem Modus der Quantisierung nach dem Training profitieren, sind:

  • Superauflösung,
  • Audiosignalverarbeitung wie Rauschunterdrückung und Strahlformung,
  • Bildentrauschen,
  • HDR-Rekonstruktion aus einem einzelnen Bild

In diesem Tutorial trainieren Sie ein MNIST-Modell von Grund auf neu, überprüfen seine Genauigkeit in TensorFlow und konvertieren das Modell dann in diesem Modus in einen Tensorflow Lite-Flatbuffer. Am Ende überprüfen Sie die Genauigkeit des konvertierten Modells und vergleichen es mit dem ursprünglichen float32-Modell. Beachten Sie, dass dieses Beispiel die Verwendung dieses Modus demonstriert und keine Vorteile gegenüber anderen verfügbaren Quantisierungstechniken in TensorFlow Lite zeigt.

Erstellen Sie ein MNIST-Modell

Einrichten

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

import tensorflow as tf
from tensorflow import keras
import numpy as np
import pathlib

Überprüfen Sie, ob der 16x8-Quantisierungsmodus verfügbar ist

tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8
<OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8: 'EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8'>

Trainieren und exportieren Sie das Modell

# Load MNIST dataset
mnist = 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 / 255.0
test_images = test_images / 255.0

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

# Train the digit classification model
model.compile(optimizer='adam',
              loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
model.fit(
  train_images,
  train_labels,
  epochs=1,
  validation_data=(test_images, test_labels)
)
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step
1875/1875 [==============================] - 13s 2ms/step - loss: 0.2827 - accuracy: 0.9209 - val_loss: 0.1246 - val_accuracy: 0.9664
<tensorflow.python.keras.callbacks.History at 0x7fc6d432cd50>

In diesem Beispiel haben Sie das Modell nur für eine einzelne Epoche trainiert, sodass es nur mit einer Genauigkeit von ~ 96% trainiert wird.

Konvertieren Sie in ein TensorFlow Lite-Modell

Mit dem Python TFLiteConverter können Sie das trainierte Modell jetzt in ein TensorFlow Lite-Modell konvertieren.

Konvertieren Sie nun das Modell mit TFliteConverter in das Standardformat float32:

converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()
INFO:tensorflow:Assets written to: /tmp/tmpsw317yw_/assets

Schreiben Sie es in eine .tflite Datei:

tflite_models_dir = pathlib.Path("/tmp/mnist_tflite_models/")
tflite_models_dir.mkdir(exist_ok=True, parents=True)
tflite_model_file = tflite_models_dir/"mnist_model.tflite"
tflite_model_file.write_bytes(tflite_model)
84552

Um das Modell stattdessen in den 16x8-Quantisierungsmodus zu quantisieren, setzen Sie zuerst das optimizations , um Standardoptimierungen zu verwenden. Geben Sie dann in der Zielspezifikation an, dass der 16x8-Quantisierungsmodus die erforderliche unterstützte Operation ist:

converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]

Wie im Fall der int8-Quantisierung nach dem Training ist es möglich, ein vollständig ganzzahliges quantisiertes Modell zu erstellen, indem die Konverteroptionen inference_input(output)_type auf tf.int16 gesetzt werden.

Stellen Sie die Kalibrierungsdaten ein:

mnist_train, _ = tf.keras.datasets.mnist.load_data()
images = tf.cast(mnist_train[0], tf.float32) / 255.0
mnist_ds = tf.data.Dataset.from_tensor_slices((images)).batch(1)
def representative_data_gen():
  for input_value in mnist_ds.take(100):
    # Model has only one input so each data point has one element.
    yield [input_value]
converter.representative_dataset = representative_data_gen

Konvertieren Sie das Modell abschließend wie gewohnt. Beachten Sie, dass das konvertierte Modell standardmäßig weiterhin Float-Ein- und Ausgänge verwendet, um den Aufruf zu vereinfachen.

tflite_16x8_model = converter.convert()
tflite_model_16x8_file = tflite_models_dir/"mnist_model_quant_16x8.tflite"
tflite_model_16x8_file.write_bytes(tflite_16x8_model)
INFO:tensorflow:Assets written to: /tmp/tmpaq8qqppx/assets
INFO:tensorflow:Assets written to: /tmp/tmpaq8qqppx/assets
24832

Beachten Sie, dass die resultierende Datei ungefähr 1/3 der Größe hat.

ls -lh {tflite_models_dir}
total 112K
-rw-rw-r-- 1 kbuilder kbuilder 83K May 15 11:12 mnist_model.tflite
-rw-rw-r-- 1 kbuilder kbuilder 25K May 15 11:12 mnist_model_quant_16x8.tflite

Führen Sie die TensorFlow Lite-Modelle aus

Führen Sie das TensorFlow Lite-Modell mit dem Python TensorFlow Lite-Interpreter aus.

Laden Sie das Modell in die Interpreter

interpreter = tf.lite.Interpreter(model_path=str(tflite_model_file))
interpreter.allocate_tensors()
interpreter_16x8 = tf.lite.Interpreter(model_path=str(tflite_model_16x8_file))
interpreter_16x8.allocate_tensors()

Testen Sie die Modelle an einem Bild

test_image = np.expand_dims(test_images[0], axis=0).astype(np.float32)

input_index = interpreter.get_input_details()[0]["index"]
output_index = interpreter.get_output_details()[0]["index"]

interpreter.set_tensor(input_index, test_image)
interpreter.invoke()
predictions = interpreter.get_tensor(output_index)
import matplotlib.pylab as plt

plt.imshow(test_images[0])
template = "True:{true}, predicted:{predict}"
_ = plt.title(template.format(true= str(test_labels[0]),
                              predict=str(np.argmax(predictions[0]))))
plt.grid(False)

png

test_image = np.expand_dims(test_images[0], axis=0).astype(np.float32)

input_index = interpreter_16x8.get_input_details()[0]["index"]
output_index = interpreter_16x8.get_output_details()[0]["index"]

interpreter_16x8.set_tensor(input_index, test_image)
interpreter_16x8.invoke()
predictions = interpreter_16x8.get_tensor(output_index)
plt.imshow(test_images[0])
template = "True:{true}, predicted:{predict}"
_ = plt.title(template.format(true= str(test_labels[0]),
                              predict=str(np.argmax(predictions[0]))))
plt.grid(False)

png

Bewerten Sie die Modelle

# A helper function to evaluate the TF Lite model using "test" dataset.
def evaluate_model(interpreter):
  input_index = interpreter.get_input_details()[0]["index"]
  output_index = interpreter.get_output_details()[0]["index"]

  # Run predictions on every image in the "test" dataset.
  prediction_digits = []
  for test_image in test_images:
    # Pre-processing: add batch dimension and convert to float32 to match with
    # the model's input data format.
    test_image = np.expand_dims(test_image, axis=0).astype(np.float32)
    interpreter.set_tensor(input_index, test_image)

    # Run inference.
    interpreter.invoke()

    # Post-processing: remove batch dimension and find the digit with highest
    # probability.
    output = interpreter.tensor(output_index)
    digit = np.argmax(output()[0])
    prediction_digits.append(digit)

  # Compare prediction results with ground truth labels to calculate accuracy.
  accurate_count = 0
  for index in range(len(prediction_digits)):
    if prediction_digits[index] == test_labels[index]:
      accurate_count += 1
  accuracy = accurate_count * 1.0 / len(prediction_digits)

  return accuracy
print(evaluate_model(interpreter))
0.9664

Wiederholen Sie die Auswertung für das quantisierte 16x8-Modell:

# NOTE: This quantization mode is an experimental post-training mode,
# it does not have any optimized kernels implementations or
# specialized machine learning hardware accelerators. Therefore,
# it could be slower than the float interpreter.
print(evaluate_model(interpreter_16x8))
0.9662

In diesem Beispiel haben Sie ein Modell ohne Unterschied in der Genauigkeit auf 16 x 8 quantisiert, jedoch mit der 3-fach reduzierten Größe.