Ver en TensorFlow.org | Ejecutar en Google Colab | Ver fuente en GitHub | Descargar cuaderno |
Descripción general
TensorFlow Lite ahora soporta la conversión de activaciones para valores enteros de 16 bits y los pesos de 8-bit número entero valores durante la conversión de modelo de TensorFlow a formato tampón plana de TensorFlow Lite. Nos referimos a este modo como el "modo de cuantificación 16x8". Este modo puede mejorar la precisión del modelo cuantificado de manera significativa, cuando las activaciones son sensibles a la cuantificación, mientras se logra una reducción de casi 3-4x en el tamaño del modelo. Además, este modelo totalmente cuantificado puede ser consumido por aceleradores de hardware de solo enteros.
Algunos ejemplos de modelos que se benefician de este modo de cuantificación posterior al entrenamiento incluyen:
- súper resolución,
- procesamiento de señales de audio, como cancelación de ruido y formación de haces,
- eliminación de ruido en la imagen,
- Reconstrucción HDR a partir de una sola imagen
En este tutorial, entrena un modelo MNIST desde cero, verifica su precisión en TensorFlow y luego convierte el modelo en un búfer plano de Tensorflow Lite usando este modo. Al final, verifica la precisión del modelo convertido y lo compara con el modelo float32 original. Tenga en cuenta que este ejemplo demuestra el uso de este modo y no muestra beneficios sobre otras técnicas de cuantificación disponibles en TensorFlow Lite.
Construye un modelo MNIST
Configuración
import logging
logging.getLogger("tensorflow").setLevel(logging.DEBUG)
import tensorflow as tf
from tensorflow import keras
import numpy as np
import pathlib
Compruebe que el modo de cuantificación 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'>
Entrene y exporte el modelo
# 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>
Por ejemplo, entrenó el modelo solo durante una época, por lo que solo entrena con una precisión de ~ 96%.
Convertir a un modelo de TensorFlow Lite
Utilizando el pitón TFLiteConverter , ahora se puede convertir el modelo entrenado en un modelo TensorFlow Lite.
Ahora, convertir el modelo usando TFliteConverter
en formato float32 por defecto:
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.
Escribirlo a un .tflite
archivo:
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
Para cuantificar lugar el modelo de 16x8 modo de cuantificación, establecido por primera vez la optimizations
la bandera de optimizaciones uso por defecto. Luego, especifique que el modo de cuantificación 16x8 es la operación admitida requerida en la especificación de destino:
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]
Como en el caso de int8 cuantificación post-formación, es posible producir un modelo totalmente número entero cuantificado mediante el establecimiento de opciones del convertidor inference_input(output)_type
a tf.int16.
Configure los datos de calibración:
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
Finalmente, convierta el modelo como de costumbre. Tenga en cuenta que, de forma predeterminada, el modelo convertido seguirá utilizando entradas y salidas flotantes para la conveniencia de la invocación.
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
Nótese cómo el archivo resultante es aproximadamente 1/3
del tamaño.
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
Ejecute los modelos de TensorFlow Lite
Ejecute el modelo de TensorFlow Lite con el intérprete de Python TensorFlow Lite.
Cargue el modelo en los intérpretes
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()
Pruebe los modelos en una imagen
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)
Evaluar los modelos
# 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
Repita la evaluación en el modelo cuantificado 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
En este ejemplo, ha cuantificado un modelo a 16x8 sin diferencia en la precisión, pero con un tamaño reducido 3x.
,Ver en TensorFlow.org | Ejecutar en Google Colab | Ver fuente en GitHub | Descargar cuaderno |
Descripción general
TensorFlow Lite ahora soporta la conversión de activaciones para valores enteros de 16 bits y los pesos de 8-bit número entero valores durante la conversión de modelo de TensorFlow a formato tampón plana de TensorFlow Lite. Nos referimos a este modo como el "modo de cuantificación 16x8". Este modo puede mejorar la precisión del modelo cuantificado de manera significativa, cuando las activaciones son sensibles a la cuantificación, mientras se logra una reducción de casi 3-4x en el tamaño del modelo. Además, este modelo totalmente cuantificado puede ser consumido por aceleradores de hardware de solo enteros.
Algunos ejemplos de modelos que se benefician de este modo de cuantificación posterior al entrenamiento incluyen:
- súper resolución,
- procesamiento de señales de audio, como cancelación de ruido y formación de haces,
- eliminación de ruido en la imagen,
- Reconstrucción HDR a partir de una sola imagen
En este tutorial, entrena un modelo MNIST desde cero, verifica su precisión en TensorFlow y luego convierte el modelo en un búfer plano de Tensorflow Lite usando este modo. Al final, verifica la precisión del modelo convertido y lo compara con el modelo float32 original. Tenga en cuenta que este ejemplo demuestra el uso de este modo y no muestra beneficios sobre otras técnicas de cuantificación disponibles en TensorFlow Lite.
Construye un modelo MNIST
Configuración
import logging
logging.getLogger("tensorflow").setLevel(logging.DEBUG)
import tensorflow as tf
from tensorflow import keras
import numpy as np
import pathlib
Compruebe que el modo de cuantificación 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'>
Entrene y exporte el modelo
# 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>
Por ejemplo, entrenó el modelo solo durante una época, por lo que solo entrena con una precisión de ~ 96%.
Convertir a un modelo de TensorFlow Lite
Utilizando el pitón TFLiteConverter , ahora se puede convertir el modelo entrenado en un modelo TensorFlow Lite.
Ahora, convertir el modelo usando TFliteConverter
en formato float32 por defecto:
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.
Escribirlo a un .tflite
archivo:
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
Para cuantificar lugar el modelo de 16x8 modo de cuantificación, establecido por primera vez la optimizations
la bandera de optimizaciones uso por defecto. Luego, especifique que el modo de cuantificación 16x8 es la operación admitida requerida en la especificación de destino:
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]
Como en el caso de int8 cuantificación post-formación, es posible producir un modelo totalmente número entero cuantificado mediante el establecimiento de opciones del convertidor inference_input(output)_type
a tf.int16.
Configure los datos de calibración:
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
Finalmente, convierta el modelo como de costumbre. Tenga en cuenta que, de forma predeterminada, el modelo convertido seguirá utilizando entradas y salidas flotantes para la conveniencia de la invocación.
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
Nótese cómo el archivo resultante es aproximadamente 1/3
del tamaño.
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
Ejecute los modelos de TensorFlow Lite
Ejecute el modelo de TensorFlow Lite con el intérprete de Python TensorFlow Lite.
Cargue el modelo en los intérpretes
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()
Pruebe los modelos en una imagen
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)
Evaluar los modelos
# 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
Repita la evaluación en el modelo cuantificado 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
En este ejemplo, ha cuantificado un modelo a 16x8 sin diferencia en la precisión, pero con un tamaño reducido 3x.