Kwantyzacja zakresu dynamicznego po treningu

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło na GitHub Pobierz notatnik Zobacz model piasty TF

Przegląd

TensorFlow Lite obsługuje konwersję wagi do 8 bitowej precyzji w ramach modelu konwersji z graphdefs tensorflow do płaskiego formatu bufora TensorFlow Lite. Kwantyzacja zakresu dynamicznego zapewnia 4-krotne zmniejszenie rozmiaru modelu. Ponadto TFLite obsługuje kwantyzację w locie i dekwantyzację aktywacji, aby umożliwić:

  1. Używanie skwantyzowanych jąder do szybszej implementacji, jeśli jest to możliwe.
  2. Mieszanie jąder zmiennoprzecinkowych ze skwantowanymi jądrami dla różnych części grafu.

Aktywacje są zawsze przechowywane w postaci zmiennoprzecinkowej. W przypadku operacji obsługujących skwantowane jądra aktywacje są kwantowane dynamicznie do 8 bitów precyzji przed przetwarzaniem i są dekwantowane do precyzji zmiennoprzecinkowej po przetworzeniu. W zależności od konwertowanego modelu może to przyspieszyć obliczenia w stosunku do obliczeń zmiennoprzecinkowych.

W przeciwieństwie do kwantyzacji świadomego szkolenia , wagi są kwantowane szkolenie post i aktywacje są krokowe dynamicznie przy wnioskowaniu w tej metodzie. W związku z tym wagi modelu nie są ponownie trenowane, aby skompensować błędy wywołane kwantyzacją. Ważne jest, aby sprawdzić dokładność modelu skwantowanego, aby upewnić się, że degradacja jest akceptowalna.

Ten samouczek szkoli model MNIST od podstaw, sprawdza jego dokładność w TensorFlow, a następnie konwertuje model na płaski bufor Tensorflow Lite z kwantyzacją zakresu dynamicznego. Na koniec sprawdza dokładność przekonwertowanego modelu i porównuje go z oryginalnym modelem swobodnym.

Zbuduj model MNIST

Ustawiać

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

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

Wytrenuj model TensorFlow

# 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.3260 - accuracy: 0.9063 - val_loss: 0.1721 - val_accuracy: 0.9499
<keras.callbacks.History at 0x7fb7a1c4ed90>

Na przykład, ponieważ trenowałeś model tylko dla jednej epoki, trenuje on tylko z dokładnością ~96%.

Konwersja na model TensorFlow Lite

Używanie Pythona TFLiteConverter można teraz przekształcić wyszkolony modelu do modelu TensorFlow Lite.

Teraz załadować model używając TFLiteConverter :

converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()
2021-11-02 11:23:32.211024: 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/tmpua453ven/assets
2021-11-02 11:23:32.640259: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-11-02 11:23:32.640302: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.

Zapisz to do pliku tflite:

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)
84500

Do kwantowania modelu na eksport, ustaw optimizations flagę optymalizacja pod kątem wielkości:

converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_quant_model = converter.convert()
tflite_model_quant_file = tflite_models_dir/"mnist_model_quant.tflite"
tflite_model_quant_file.write_bytes(tflite_quant_model)
INFO:tensorflow:Assets written to: /tmp/tmpaw0wsb_y/assets
INFO:tensorflow:Assets written to: /tmp/tmpaw0wsb_y/assets
2021-11-02 11:23:33.235475: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-11-02 11:23:33.235512: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.
23904

Zauważ, że plik wynikowy, wynosi około 1/4 wielkości.

ls -lh {tflite_models_dir}
total 136K
-rw-rw-r-- 1 kbuilder kbuilder 83K Nov  2 11:23 mnist_model.tflite
-rw-rw-r-- 1 kbuilder kbuilder 24K Nov  2 11:23 mnist_model_quant.tflite
-rw-rw-r-- 1 kbuilder kbuilder 25K Nov  2 11:20 mnist_model_quant_16x8.tflite

Uruchom modele TFLite

Uruchom model TensorFlow Lite za pomocą interpretera Python TensorFlow Lite.

Załaduj model do interpretera

interpreter = tf.lite.Interpreter(model_path=str(tflite_model_file))
interpreter.allocate_tensors()
interpreter_quant = tf.lite.Interpreter(model_path=str(tflite_model_quant_file))
interpreter_quant.allocate_tensors()

Przetestuj model na jednym obrazie

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

Oceń modele

# 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.9499

Powtórz ocenę na skwantowanym modelu zakresu dynamicznego, aby uzyskać:

print(evaluate_model(interpreter_quant))
0.95

W tym przykładzie skompresowany model nie ma różnicy w dokładności.

Optymalizacja istniejącego modelu

Resnet z warstwami preaktywacji (Resnet-v2) są szeroko stosowane w aplikacjach wizyjnych. Pre-przeszkolony mrożone wykres dla resnet-v2-101 jest dostępny na Tensorflow Hub .

Możesz przekonwertować zamrożony wykres do płaskiego bufora TensorFLow Lite z kwantyzacją przez:

import tensorflow_hub as hub

resnet_v2_101 = tf.keras.Sequential([
  keras.layers.InputLayer(input_shape=(224, 224, 3)),
  hub.KerasLayer("https://tfhub.dev/google/imagenet/resnet_v2_101/classification/4")
])

converter = tf.lite.TFLiteConverter.from_keras_model(resnet_v2_101)
# Convert to TF Lite without quantization
resnet_tflite_file = tflite_models_dir/"resnet_v2_101.tflite"
resnet_tflite_file.write_bytes(converter.convert())
WARNING:tensorflow:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.
WARNING:tensorflow:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.
INFO:tensorflow:Assets written to: /tmp/tmpxtji1amp/assets
INFO:tensorflow:Assets written to: /tmp/tmpxtji1amp/assets
2021-11-02 11:23:57.616139: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-11-02 11:23:57.616201: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.
178509352
# Convert to TF Lite with quantization
converter.optimizations = [tf.lite.Optimize.DEFAULT]
resnet_quantized_tflite_file = tflite_models_dir/"resnet_v2_101_quantized.tflite"
resnet_quantized_tflite_file.write_bytes(converter.convert())
WARNING:tensorflow:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.
WARNING:tensorflow:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.
INFO:tensorflow:Assets written to: /tmp/tmpg169iato/assets
INFO:tensorflow:Assets written to: /tmp/tmpg169iato/assets
2021-11-02 11:24:12.965799: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-11-02 11:24:12.965851: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.
46256864
ls -lh {tflite_models_dir}/*.tflite
-rw-rw-r-- 1 kbuilder kbuilder  83K Nov  2 11:23 /tmp/mnist_tflite_models/mnist_model.tflite
-rw-rw-r-- 1 kbuilder kbuilder  24K Nov  2 11:23 /tmp/mnist_tflite_models/mnist_model_quant.tflite
-rw-rw-r-- 1 kbuilder kbuilder  25K Nov  2 11:20 /tmp/mnist_tflite_models/mnist_model_quant_16x8.tflite
-rw-rw-r-- 1 kbuilder kbuilder 171M Nov  2 11:23 /tmp/mnist_tflite_models/resnet_v2_101.tflite
-rw-rw-r-- 1 kbuilder kbuilder  45M Nov  2 11:24 /tmp/mnist_tflite_models/resnet_v2_101_quantized.tflite

Rozmiar modelu zmniejsza się ze 171 MB do 43 MB. Dokładność tego modelu na IMAGEnet można ocenić za pomocą skryptów przewidzianych Dokładność pomiaru TFLite .

Zoptymalizowana dokładność modelu top-1 wynosi 76,8, tak samo jak w modelu zmiennoprzecinkowym.