Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Cuantización post-entrenamiento

La cuantización posterior al entrenamiento es una técnica de conversión que puede reducir el tamaño del modelo al tiempo que mejora la latencia del acelerador de hardware y CPU, con poca degradación en la precisión del modelo. Puede cuantificar un modelo flotante TensorFlow ya entrenado cuando lo convierte al formato TensorFlow Lite utilizando el convertidor TensorFlow Lite .

Métodos de optimización

Hay varias opciones de cuantificación posteriores al entrenamiento para elegir. Aquí hay una tabla resumen de las opciones y los beneficios que proporcionan:

Técnica Beneficios Hardware
Cuantificación de rango dinámico 4 veces más pequeño, aceleración 2x-3x UPC
Cuantización completa de enteros 4x más pequeño, 3x + aceleración CPU, Edge TPU, Microcontroladores
Float16 cuantización 2 veces más pequeño, aceleración GPU CPU, GPU

El siguiente árbol de decisión puede ayudar a determinar qué método de cuantificación posterior al entrenamiento es mejor para su caso de uso:

opciones de optimización post-entrenamiento

Cuantificación de rango dinámico

La forma más simple de cuantización posterior al entrenamiento cuantifica estáticamente solo los pesos desde punto flotante a entero, que tiene 8 bits de precisión:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_quant_model = converter.convert()

En la inferencia, los pesos se convierten de 8 bits de precisión a coma flotante y se calculan utilizando núcleos de coma flotante. Esta conversión se realiza una vez y se almacena en caché para reducir la latencia.

Para mejorar aún más la latencia, los operadores de "rango dinámico" cuantifican dinámicamente las activaciones en función de su rango de 8 bits y realizan cálculos con pesos y activaciones de 8 bits. Esta optimización proporciona latencias cercanas a la inferencia de punto totalmente fijo. Sin embargo, las salidas todavía se almacenan utilizando coma flotante, de modo que la aceleración con operaciones de rango dinámico es menor que un cálculo completo de punto fijo.

Cuantización completa de enteros

Puede obtener más mejoras de latencia, reducciones en el uso máximo de memoria y compatibilidad con dispositivos de hardware o aceleradores enteros solo asegurándose de que todas las matemáticas del modelo estén cuantizadas con enteros.

Para una cuantización completa de enteros, debe medir el rango dinámico de activaciones y entradas suministrando datos de entrada de muestra al convertidor. Consulte la función representative_dataset_gen() utilizada en el siguiente código.

Entero con retroceso flotante (utilizando entrada / salida flotante predeterminada)

Para cuantificar por completo un modelo, pero use operadores flotantes cuando no tengan una implementación entera (para garantizar que la conversión se realice sin problemas), siga estos pasos:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
def representative_dataset_gen():
  for _ in range(num_calibration_steps):
    # Get sample input data as a numpy array in a method of your choosing.
    yield [input]
converter.representative_dataset = representative_dataset_gen
tflite_quant_model = converter.convert()

Solo entero

La creación de modelos enteros es un caso de uso común para TensorFlow Lite para microcontroladores y TPU Coral Edge .

Además, para garantizar la compatibilidad con dispositivos de número entero (como microcontroladores de 8 bits) y aceleradores (como el TPU Coral Edge), puede aplicar la cuantización de enteros completos para todas las operaciones, incluidas la entrada y la salida, mediante los siguientes pasos:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
def representative_dataset_gen():
  for _ in range(num_calibration_steps):
    # Get sample input data as a numpy array in a method of your choosing.
    yield [input]
converter.representative_dataset = representative_dataset_gen
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8  # or tf.uint8
converter.inference_output_type = tf.int8  # or tf.uint8
tflite_quant_model = converter.convert()

Float16 cuantización

Puede reducir el tamaño de un modelo de coma flotante cuantificando los pesos para flotar16, el estándar IEEE para números de coma flotante de 16 bits. Para habilitar la cuantificación de pesos float16, utilice los siguientes pasos:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float16]
tflite_quant_model = converter.convert()

Las ventajas de la cuantización float16 son las siguientes:

  • Reduce el tamaño del modelo hasta la mitad (ya que todos los pesos se convierten en la mitad de su tamaño original).
  • Causa una pérdida mínima de precisión.
  • Admite algunos delegados (por ejemplo, el delegado de GPU) que pueden operar directamente en datos float16, lo que resulta en una ejecución más rápida que los cálculos de float32.

Las desventajas de la cuantización float16 son las siguientes:

  • No reduce la latencia tanto como una cuantización a matemática de punto fijo.
  • Por defecto, un modelo cuantizado float16 "descuantificará" los valores de los pesos a float32 cuando se ejecute en la CPU. (Tenga en cuenta que el delegado de GPU no realizará esta descuantificación, ya que puede operar en datos float16).

Solo entero: activaciones de 16 bits con pesos de 8 bits (experimental)

Este es un esquema de cuantificación experimental. Es similar al esquema "solo entero", pero las activaciones se cuantifican en función de su rango de 16 bits, los pesos se cuantifican en un entero de 8 bits y el sesgo se cuantifica en un entero de 64 bits. Esto se conoce como cuantificación 16x8 adicionalmente.

La principal ventaja de esta cuantización es que puede mejorar la precisión significativamente, pero solo aumenta ligeramente el tamaño del modelo.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
def representative_dataset_gen():
  for _ in range(num_calibration_steps):
    # Get sample input data as a numpy array in a method of your choosing.
    yield [input]
converter.representative_dataset = representative_dataset_gen
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]
tflite_quant_model = converter.convert()

Si la cuantificación de 16x8 no es compatible con algunos operadores en el modelo, entonces el modelo aún puede cuantificarse, pero los operadores no admitidos se mantienen flotantes. La siguiente opción debe agregarse a target_spec para permitir esto.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
def representative_dataset_gen():
  for _ in range(num_calibration_steps):
    # Get sample input data as a numpy array in a method of your choosing.
    yield [input]
converter.representative_dataset = representative_dataset_gen
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
tf.lite.OpsSet.TFLITE_BUILTINS ]
tflite_quant_model = converter.convert()

Los ejemplos de casos de uso en los que las mejoras de precisión proporcionadas por este esquema de cuantificación incluyen: * superresolución, * procesamiento de señal de audio como cancelación de ruido y formación de haz, * eliminación de ruido de imagen, * reconstrucción de HDR a partir de una sola imagen.

La desventaja de esta cuantización es:

  • Actualmente la inferencia es notablemente más lenta que el entero completo de 8 bits debido a la falta de implementación optimizada del núcleo.
  • Actualmente es incompatible con los delegados TFLite acelerados por hardware existentes.

Precisión del modelo

Dado que los pesos se cuantifican después del entrenamiento, podría haber una pérdida de precisión, particularmente para redes más pequeñas. Se proporcionan modelos totalmente cuantificados previamente entrenados para redes específicas en el repositorio de modelos TensorFlow Lite . Es importante verificar la precisión del modelo cuantificado para verificar que cualquier degradación en la precisión esté dentro de los límites aceptables. Existen herramientas para evaluar la precisión del modelo TensorFlow Lite .

Alternativamente, si la caída de precisión es demasiado alta, considere usar capacitación consciente de cuantización . Sin embargo, hacerlo requiere modificaciones durante el entrenamiento del modelo para agregar nodos de cuantificación falsos, mientras que las técnicas de cuantificación posteriores al entrenamiento en esta página utilizan un modelo pre-entrenado existente.

Representación para tensores cuantificados.

La cuantificación de 8 bits se aproxima a los valores de coma flotante utilizando la siguiente fórmula.

$$ real \ _value = (int8 \ _value - zero \ _point) \ times scale $$

La representación tiene dos partes principales:

  • Por eje (también conocido como por canal) o por tensor pesos representados por valores de complemento de dos int8 en el rango [-127, 127] con punto cero igual a 0.

  • Activaciones / entradas por tensor representadas por valores de complemento de dos int8 en el rango [-128, 127], con un punto cero en el rango [-128, 127].

Para obtener una vista detallada de nuestro esquema de cuantificación, consulte nuestras especificaciones de cuantización . Se alienta a los proveedores de hardware que desean conectarse a la interfaz de delegado de TensorFlow Lite a implementar el esquema de cuantificación que se describe allí.