Voir sur TensorFlow.org | Exécuter dans Google Colab | Voir la source sur GitHub | Télécharger le cahier |
Aperçu
Tensorflow Lite prend désormais la conversion des activations des valeurs et des poids à 8 bits entier des nombres entiers de 16 bits lors de la conversion du modèle de tensorflow au format tampon plat de tensorflow Lite. Nous appelons ce mode le "mode de quantification 16x8". Ce mode peut améliorer considérablement la précision du modèle quantifié, lorsque les activations sont sensibles à la quantification, tout en atteignant une réduction de près de 3 à 4 fois la taille du modèle. De plus, ce modèle entièrement quantifié peut être consommé par des accélérateurs matériels à nombre entier uniquement.
Voici quelques exemples de modèles qui bénéficient de ce mode de quantification post-entraînement :
- super-résolution,
- traitement du signal audio tel que la suppression du bruit et la formation de faisceaux,
- débruitage d'image,
- Reconstruction HDR à partir d'une seule image
Dans ce didacticiel, vous entraînez un modèle MNIST à partir de zéro, vérifiez sa précision dans TensorFlow, puis convertissez le modèle en un flatbuffer Tensorflow Lite à l'aide de ce mode. À la fin, vous vérifiez l'exactitude du modèle converti et le comparez au modèle float32 d'origine. Notez que cet exemple illustre l'utilisation de ce mode et ne montre pas les avantages par rapport aux autres techniques de quantification disponibles dans TensorFlow Lite.
Construire un modèle MNIST
Installer
import logging
logging.getLogger("tensorflow").setLevel(logging.DEBUG)
import tensorflow as tf
from tensorflow import keras
import numpy as np
import pathlib
Vérifiez que le mode de quantification 16x8 est disponible
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'>
Former et exporter le modèle
# 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.2797 - accuracy: 0.9224 - val_loss: 0.1224 - val_accuracy: 0.9641 <keras.callbacks.History at 0x7f6f19eff210>
Pour l'exemple, vous avez entraîné le modèle pour une seule époque, de sorte qu'il n'est entraîné qu'à environ 96 % de précision.
Convertir en un modèle TensorFlow Lite
En utilisant Python TFLiteConverter , vous pouvez convertir le modèle formé dans un modèle tensorflow Lite.
Maintenant, convertir le modèle en utilisant TFliteConverter
en format par défaut de float32:
converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()
2021-10-30 11:55:42.971843: 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/tmpbriefkal/assets 2021-10-30 11:55:43.402148: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format. 2021-10-30 11:55:43.402187: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.
Écrivez-un .tflite
fichier:
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
Pour le modèle à la place quantifie à 16x8 mode de quantification, définissez d' abord l' optimizations
drapeau pour utiliser les optimisations par défaut. Spécifiez ensuite que le mode de quantification 16x8 est l'opération prise en charge requise dans la spécification cible :
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]
Comme dans le cas de la quantification après la formation int8, il est possible de produire un modèle entier entièrement quantifié par le paramétrage des options de conversion inference_input(output)_type
à tf.int16.
Définissez les données d'étalonnage :
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
Enfin, convertissez le modèle comme d'habitude. Notez que par défaut, le modèle converti utilisera toujours les entrées et sorties flottantes pour faciliter l'invocation.
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/tmpfxn_2jql/assets INFO:tensorflow:Assets written to: /tmp/tmpfxn_2jql/assets 2021-10-30 11:55:44.514461: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format. 2021-10-30 11:55:44.514507: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency. 24768
Notez comment le fichier résultant est d' environ 1/3
de la taille.
ls -lh {tflite_models_dir}
total 136K -rw-rw-r-- 1 kbuilder kbuilder 83K Oct 30 11:55 mnist_model.tflite -rw-rw-r-- 1 kbuilder kbuilder 24K Oct 30 11:54 mnist_model_quant.tflite -rw-rw-r-- 1 kbuilder kbuilder 25K Oct 30 11:55 mnist_model_quant_16x8.tflite
Exécuter les modèles TensorFlow Lite
Exécutez le modèle TensorFlow Lite à l'aide de l'interpréteur Python TensorFlow Lite.
Charger le modèle dans les interpréteurs
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()
Testez les modèles sur une image
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)
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)
Évaluer les modèles
# 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.9641
Répétez l'évaluation sur le modèle quantifié 16x8 :
# 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.964
Dans cet exemple, vous avez quantifié un modèle à 16x8 sans différence de précision, mais avec une taille réduite de 3x.
,Voir sur TensorFlow.org | Exécuter dans Google Colab | Voir la source sur GitHub | Télécharger le cahier |
Aperçu
Tensorflow Lite prend désormais la conversion des activations des valeurs et des poids à 8 bits entier des nombres entiers de 16 bits lors de la conversion du modèle de tensorflow au format tampon plat de tensorflow Lite. Nous appelons ce mode le "mode de quantification 16x8". Ce mode peut améliorer considérablement la précision du modèle quantifié, lorsque les activations sont sensibles à la quantification, tout en atteignant une réduction de près de 3 à 4 fois la taille du modèle. De plus, ce modèle entièrement quantifié peut être consommé par des accélérateurs matériels à nombre entier uniquement.
Voici quelques exemples de modèles qui bénéficient de ce mode de quantification post-entraînement :
- super-résolution,
- traitement du signal audio tel que la suppression du bruit et la formation de faisceaux,
- débruitage d'image,
- Reconstruction HDR à partir d'une seule image
Dans ce didacticiel, vous entraînez un modèle MNIST à partir de zéro, vérifiez sa précision dans TensorFlow, puis convertissez le modèle en un flatbuffer Tensorflow Lite à l'aide de ce mode. À la fin, vous vérifiez l'exactitude du modèle converti et le comparez au modèle float32 d'origine. Notez que cet exemple illustre l'utilisation de ce mode et ne montre pas les avantages par rapport aux autres techniques de quantification disponibles dans TensorFlow Lite.
Construire un modèle MNIST
Installer
import logging
logging.getLogger("tensorflow").setLevel(logging.DEBUG)
import tensorflow as tf
from tensorflow import keras
import numpy as np
import pathlib
Vérifiez que le mode de quantification 16x8 est disponible
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'>
Former et exporter le modèle
# 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.2797 - accuracy: 0.9224 - val_loss: 0.1224 - val_accuracy: 0.9641 <keras.callbacks.History at 0x7f6f19eff210>
Pour l'exemple, vous avez entraîné le modèle pour une seule époque, de sorte qu'il n'est entraîné qu'à environ 96 % de précision.
Convertir en un modèle TensorFlow Lite
En utilisant Python TFLiteConverter , vous pouvez convertir le modèle formé dans un modèle tensorflow Lite.
Maintenant, convertir le modèle en utilisant TFliteConverter
en format par défaut de float32:
converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()
2021-10-30 11:55:42.971843: 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/tmpbriefkal/assets 2021-10-30 11:55:43.402148: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format. 2021-10-30 11:55:43.402187: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.
Écrivez-un .tflite
fichier:
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
Pour le modèle à la place quantifie à 16x8 mode de quantification, définissez d' abord l' optimizations
drapeau pour utiliser les optimisations par défaut. Spécifiez ensuite que le mode de quantification 16x8 est l'opération prise en charge requise dans la spécification cible :
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]
Comme dans le cas de la quantification après la formation int8, il est possible de produire un modèle entier entièrement quantifié par le paramétrage des options de conversion inference_input(output)_type
à tf.int16.
Définissez les données d'étalonnage :
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
Enfin, convertissez le modèle comme d'habitude. Notez que par défaut, le modèle converti utilisera toujours les entrées et sorties flottantes pour faciliter l'invocation.
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/tmpfxn_2jql/assets INFO:tensorflow:Assets written to: /tmp/tmpfxn_2jql/assets 2021-10-30 11:55:44.514461: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format. 2021-10-30 11:55:44.514507: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency. 24768
Notez comment le fichier résultant est d' environ 1/3
de la taille.
ls -lh {tflite_models_dir}
total 136K -rw-rw-r-- 1 kbuilder kbuilder 83K Oct 30 11:55 mnist_model.tflite -rw-rw-r-- 1 kbuilder kbuilder 24K Oct 30 11:54 mnist_model_quant.tflite -rw-rw-r-- 1 kbuilder kbuilder 25K Oct 30 11:55 mnist_model_quant_16x8.tflite
Exécuter les modèles TensorFlow Lite
Exécutez le modèle TensorFlow Lite à l'aide de l'interpréteur Python TensorFlow Lite.
Charger le modèle dans les interpréteurs
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()
Testez les modèles sur une image
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)
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)
Évaluer les modèles
# 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.9641
Répétez l'évaluation sur le modèle quantifié 16x8 :
# 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.964
Dans cet exemple, vous avez quantifié un modèle à 16x8 sans différence de précision, mais avec une taille réduite de 3x.