Eine Frage haben? Verbinden Sie sich mit der Community im TensorFlow Forum Visit Forum

Float16-Quantisierung nach dem Training

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

Überblick

TensorFlow Lite unterstützt jetzt die Konvertierung von Gewichten in 16-Bit-Gleitkommawerte während der Modellkonvertierung von TensorFlow in das flache Pufferformat von TensorFlow Lite. Dies führt zu einer zweifachen Reduzierung der Modellgröße. Einige Hardware, wie z. B. GPUs, können in dieser Arithmetik mit reduzierter Genauigkeit nativ berechnen und so eine Beschleunigung gegenüber der herkömmlichen Gleitkommaausführung erzielen. Der Tensorflow Lite-GPU-Delegat kann so konfiguriert werden, dass er auf diese Weise ausgeführt wird. Ein in float16-Gewichte konvertiertes Modell kann jedoch weiterhin ohne zusätzliche Änderung auf der CPU ausgeführt werden: Die float16-Gewichte werden vor der ersten Inferenz auf float32 hochgesampelt. Dies ermöglicht eine signifikante Reduzierung der Modellgröße im Austausch gegen minimale Auswirkungen auf Latenz und Genauigkeit.

In diesem Tutorial trainieren Sie ein MNIST-Modell von Grund auf neu, überprüfen seine Genauigkeit in TensorFlow und konvertieren das Modell anschließend in einen Tensorflow Lite-Flatbuffer mit float16-Quantisierung. Überprüfen Sie abschließend die Genauigkeit des konvertierten Modells und vergleichen Sie es mit dem ursprünglichen float32-Modell.

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
tf.float16
tf.float16

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)
)
1875/1875 [==============================] - 6s 2ms/step - loss: 0.2991 - accuracy: 0.9149 - val_loss: 0.1515 - val_accuracy: 0.9572
<tensorflow.python.keras.callbacks.History at 0x7eff7574fed0>

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.

Laden Sie nun das Modell mit dem TFLiteConverter :

converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()
INFO:tensorflow:Assets written to: /tmp/tmpc71pc8p_/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 beim Export stattdessen auf float16 zu quantisieren, setzen Sie zuerst das optimizations , um Standardoptimierungen zu verwenden. Geben Sie dann an, dass float16 der unterstützte Typ auf der Zielplattform ist:

converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float16]

Konvertieren Sie das Modell schließlich wie gewohnt. Beachten Sie, dass das konvertierte Modell standardmäßig weiterhin Float-Ein- und Ausgaben verwendet, um den Aufruf zu vereinfachen.

tflite_fp16_model = converter.convert()
tflite_model_fp16_file = tflite_models_dir/"mnist_model_quant_f16.tflite"
tflite_model_fp16_file.write_bytes(tflite_fp16_model)
INFO:tensorflow:Assets written to: /tmp/tmp9zjlljmb/assets
INFO:tensorflow:Assets written to: /tmp/tmp9zjlljmb/assets
44432

Beachten Sie, dass die resultierende Datei ungefähr 1/2 groß ist.

ls -lh {tflite_models_dir}
total 156K
-rw-rw-r-- 1 kbuilder kbuilder 83K May 15 11:13 mnist_model.tflite
-rw-rw-r-- 1 kbuilder kbuilder 25K May 15 11:12 mnist_model_quant_16x8.tflite
-rw-rw-r-- 1 kbuilder kbuilder 44K May 15 11:13 mnist_model_quant_f16.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_fp16 = tf.lite.Interpreter(model_path=str(tflite_model_fp16_file))
interpreter_fp16.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_fp16.get_input_details()[0]["index"]
output_index = interpreter_fp16.get_output_details()[0]["index"]

interpreter_fp16.set_tensor(input_index, test_image)
interpreter_fp16.invoke()
predictions = interpreter_fp16.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.9572

Wiederholen Sie die Auswertung am quantisierten float16-Modell, um Folgendes zu erhalten:

# NOTE: Colab runs on server CPUs. At the time of writing this, TensorFlow Lite
# doesn't have super optimized server CPU kernels. For this reason this may be
# slower than the above float interpreter. But for mobile CPUs, considerable
# speedup can be observed.
print(evaluate_model(interpreter_fp16))
0.9572

In diesem Beispiel haben Sie ein Modell ohne Unterschied in der Genauigkeit auf float16 quantisiert.

Es ist auch möglich, das quantisierte fp16-Modell auf der GPU auszuwerten. Um alle Arithmetik mit den reduzierten Genauigkeitswerte durchführen, sollten Sie die erstellen TfLiteGPUDelegateOptions struct in Ihrer Anwendung und Set precision_loss_allowed auf 1 , wie folgt aus :

//Prepare GPU delegate.
const TfLiteGpuDelegateOptions options = {
  .metadata = NULL,
  .compile_options = {
    .precision_loss_allowed = 1,  // FP16
    .preferred_gl_object_type = TFLITE_GL_OBJECT_TYPE_FASTEST,
    .dynamic_batch_enabled = 0,   // Not fully functional yet
  },
};

Eine ausführliche Dokumentation zum TFLite-GPU-Delegaten und zur Verwendung in Ihrer Anwendung finden Sie hier