¡El Día de la Comunidad de ML es el 9 de noviembre! Únase a nosotros para recibir actualizaciones de TensorFlow, JAX, y más Más información

Agregar metadatos a los modelos de TensorFlow Lite

Los metadatos de TensorFlow Lite proporcionan un estándar para las descripciones de modelos. Los metadatos son una fuente importante de conocimiento sobre lo que hace el modelo y su información de entrada / salida. Los metadatos constan de ambos

Todos los modelos publicados en la imagen TensorFlow Lite organizadas modelos y TensorFlow Hub se han rellenado con metadatos.

Modelo con formato de metadatos

model_with_metadata
Figura 1. Modelo TFLite con metadatos y archivos asociados.

Metadatos modelo se define en metadata_schema.fbs , un FlatBuffer archivo. Como se muestra en la Figura 1, se almacena en el metadatos campo del esquema modelo TFLite , bajo el nombre, "TFLITE_METADATA" . Algunos modelos pueden venir con archivos asociados, tales como archivos de etiquetas de clasificación . Estos archivos se concatenan para el final del archivo modelo original como una postal utilizando el ZipFile modo "append" ( 'a' modo). TFLite Interpreter puede consumir el nuevo formato de archivo de la misma manera que antes. Ver Pack de los archivos asociados para obtener más información.

Consulte las instrucciones a continuación sobre cómo completar, visualizar y leer metadatos.

Configurar las herramientas de metadatos

Antes de agregar metadatos a su modelo, necesitará una configuración de entorno de programación Python para ejecutar TensorFlow. Hay una guía detallada sobre cómo configurar esta opción aquí .

Después de configurar el entorno de programación de Python, deberá instalar herramientas adicionales:

pip install tflite-support

Las herramientas de metadatos de TensorFlow Lite son compatibles con Python 3.

Agregar metadatos usando Flatbuffers Python API

Hay tres partes en los metadatos modelo en el esquema :

  1. Información del modelo - Descripción general del modelo, así como elementos tales como términos de licencia. Ver ModelMetadata .
  2. La información de entrada - Descripción de las entradas y pre-tratamiento requerido tales como la normalización. Ver SubGraphMetadata.input_tensor_metadata .
  3. Información de salida - Descripción de la salida y de post-procesamiento necesarios, tales como el mapeo de etiquetas. Ver SubGraphMetadata.output_tensor_metadata .

Desde TensorFlow Lite sólo admite una sola subgrafo en este punto, el generador de código TensorFlow Lite y la función de unión Android Studio ML utilizarán ModelMetadata.name y ModelMetadata.description , en lugar de SubGraphMetadata.name y SubGraphMetadata.description , cuando se muestran los metadatos y la generación de código.

Tipos de entrada / salida admitidos

Los metadatos de TensorFlow Lite para entrada y salida no están diseñados con tipos de modelos específicos en mente, sino más bien con tipos de entrada y salida. No importa lo que haga funcionalmente el modelo, siempre que los tipos de entrada y salida consistan en lo siguiente o una combinación de lo siguiente, es compatible con los metadatos de TensorFlow Lite:

  • Característica: números que son enteros sin signo o float32.
  • Imagen: actualmente, los metadatos admiten imágenes RGB y en escala de grises.
  • Cuadro delimitador: cuadros delimitadores de forma rectangular. El esquema es compatible con una variedad de esquemas de numeración .

Empaque los archivos asociados

Los modelos de TensorFlow Lite pueden venir con diferentes archivos asociados. Por ejemplo, los modelos de lenguaje natural suelen tener archivos de vocabulario que asignan partes de palabras a ID de palabras; Los modelos de clasificación pueden tener archivos de etiquetas que indiquen categorías de objetos. Sin los archivos asociados (si los hay), un modelo no funcionará bien.

Los archivos asociados ahora se pueden empaquetar con el modelo a través de la biblioteca Python de metadatos. El nuevo modelo de TensorFlow Lite se convierte en un archivo zip que contiene tanto el modelo como los archivos asociados. Se puede desembalar con herramientas zip comunes. Este nuevo formato modelo mantiene con la misma extensión de archivo, .tflite . Es compatible con el intérprete y el framework TFLite existente. Ver metadatos paquete y los archivos asociados en el modelo para más detalles.

La información del archivo asociado se puede registrar en los metadatos. Dependiendo del tipo de archivo y donde el archivo está unido a (es decir ModelMetadata , SubGraphMetadata , y TensorMetadata ), el generador de código TensorFlow Lite Android puede aplicar pre / post-procesamiento correspondiente automáticamente al objeto. Ver la sección <uso Codegen> de cada tipo de archivo adjunto en el esquema para más detalles.

Parámetros de normalización y cuantificación

La normalización es una técnica de preprocesamiento de datos común en el aprendizaje automático. El objetivo de la normalización es cambiar los valores a una escala común, sin distorsionar las diferencias en los rangos de valores.

Cuantificación Modelo es una técnica que permite la reducción de las representaciones de precisión de los pesos y opcionalmente, activaciones tanto para el almacenamiento y computación.

En términos de preprocesamiento y posprocesamiento, la normalización y la cuantificación son dos pasos independientes. Aquí están los detalles.

Normalización Cuantización

Un ejemplo de los valores de los parámetros de la imagen de entrada en MobileNet para modelos flotantes y cuantitativos, respectivamente.
Modelo de flotación:
- media: 127,5
- estándar: 127,5
Modelo cuantitativo:
- media: 127,5
- estándar: 127,5
Modelo de flotación:
- zeroPoint: 0
- escala: 1.0
Modelo cuantitativo:
- zeroPoint: 128.0
- escala: 0.0078125f




¿Cuándo invocar?


Entradas: Si los datos de entrada se normaliza en el entrenamiento, los datos de entrada de las necesidades de inferencia a normalizarse en consecuencia.
Salidas: datos de salida no se normalizarán en general.
Modelos flotador no necesitan cuantificación.
Modelo Quantized puede o no necesitar cuantificación en pre / post-procesamiento. Depende del tipo de datos de los tensores de entrada / salida.
- Tensores de flotación: no se necesita cuantificación en pre / post procesamiento. La operación cuántica y la operación decuante se incorporan al gráfico del modelo.
- Tensores int8 / uint8: necesitan cuantificación en pre / post procesamiento.


Fórmula


normalized_input = (entrada - media) / std
Cuantificar los insumos:
q = f / escala + punto cero
Descuantificar para las salidas:
f = (q - zeroPoint) * escala

¿Dónde están los parámetros?
Llenado por modelo creador y almacenado en los metadatos del modelo, como NormalizationOptions Completado automáticamente por el convertidor TFLite y almacenado en el archivo de modelo tflite.
¿Cómo obtener los parámetros? A través de la MetadataExtractor API [2] A través de la TFLite Tensor API [1] o a través de la MetadataExtractor API [2]
¿Los modelos flotantes y cuantitativos comparten el mismo valor? Sí, los modelos flotantes y cuantitativos tienen los mismos parámetros de normalización No, el modelo flotante no necesita cuantificación.
¿El generador de código TFLite o el enlace de Android Studio ML lo generan automáticamente en el procesamiento de datos?

[1] El TensorFlow Lite API de Java y la API TensorFlow Lite C ++ .
[2] La biblioteca extractor de metadatos

Al procesar datos de imagen para modelos uint8, a veces se omiten la normalización y la cuantificación. Está bien hacerlo cuando los valores de los píxeles están en el rango de [0, 255]. Pero, en general, siempre debe procesar los datos de acuerdo con los parámetros de normalización y cuantificación cuando corresponda.

TensorFlow Biblioteca de tareas Lite puede manejar la normalización para usted si se configura NormalizationOptions en los metadatos. El procesamiento de cuantificación y descuantificación siempre está encapsulado.

Ejemplos de

Puede encontrar ejemplos sobre cómo se deben completar los metadatos para diferentes tipos de modelos aquí:

Clasificación de imágenes

Descargar el script de aquí , que puebla los metadatos a mobilenet_v1_0.75_160_quantized.tflite . Ejecute el script así:

python ./metadata_writer_for_image_classifier.py \
    --model_file=./model_without_metadata/mobilenet_v1_0.75_160_quantized.tflite \
    --label_file=./model_without_metadata/labels.txt \
    --export_directory=model_with_metadata

Para poblar metadatos para otros modelos de clasificación de imágenes, añadir las especificaciones modelo como este en el guión. El resto de esta guía destacará algunas de las secciones clave en el ejemplo de clasificación de imágenes para ilustrar los elementos clave.

Profundice en el ejemplo de clasificación de imágenes

Información del modelo

Los metadatos comienzan creando una nueva información de modelo:

from tflite_support import flatbuffers
from tflite_support import metadata as _metadata
from tflite_support import metadata_schema_py_generated as _metadata_fb

""" ... """
"""Creates the metadata for an image classifier."""

# Creates model info.
model_meta = _metadata_fb.ModelMetadataT()
model_meta.name = "MobileNetV1 image classifier"
model_meta.description = ("Identify the most prominent object in the "
                          "image from a set of 1,001 categories such as "
                          "trees, animals, food, vehicles, person etc.")
model_meta.version = "v1"
model_meta.author = "TensorFlow"
model_meta.license = ("Apache License. Version 2.0 "
                      "http://www.apache.org/licenses/LICENSE-2.0.")

Información de entrada / salida

Esta sección le muestra cómo describir la firma de entrada y salida de su modelo. Estos metadatos pueden ser utilizados por generadores de código automáticos para crear código de procesamiento previo y posterior. Para crear información de entrada o salida sobre un tensor:

# Creates input info.
input_meta = _metadata_fb.TensorMetadataT()

# Creates output info.
output_meta = _metadata_fb.TensorMetadataT()

Entrada de imagen

La imagen es un tipo de entrada común para el aprendizaje automático. Los metadatos de TensorFlow Lite admiten información como el espacio de color y la información de procesamiento previo, como la normalización. La dimensión de la imagen no requiere una especificación manual, ya que la forma del tensor de entrada ya la proporciona y se puede inferir automáticamente.

input_meta.name = "image"
input_meta.description = (
    "Input image to be classified. The expected image is {0} x {1}, with "
    "three channels (red, blue, and green) per pixel. Each value in the "
    "tensor is a single byte between 0 and 255.".format(160, 160))
input_meta.content = _metadata_fb.ContentT()
input_meta.content.contentProperties = _metadata_fb.ImagePropertiesT()
input_meta.content.contentProperties.colorSpace = (
    _metadata_fb.ColorSpaceType.RGB)
input_meta.content.contentPropertiesType = (
    _metadata_fb.ContentProperties.ImageProperties)
input_normalization = _metadata_fb.ProcessUnitT()
input_normalization.optionsType = (
    _metadata_fb.ProcessUnitOptions.NormalizationOptions)
input_normalization.options = _metadata_fb.NormalizationOptionsT()
input_normalization.options.mean = [127.5]
input_normalization.options.std = [127.5]
input_meta.processUnits = [input_normalization]
input_stats = _metadata_fb.StatsT()
input_stats.max = [255]
input_stats.min = [0]
input_meta.stats = input_stats

Salida de etiqueta

Etiqueta puede estar asignada a un tensor de salida a través de un archivo asociado utilizando TENSOR_AXIS_LABELS .

# Creates output info.
output_meta = _metadata_fb.TensorMetadataT()
output_meta.name = "probability"
output_meta.description = "Probabilities of the 1001 labels respectively."
output_meta.content = _metadata_fb.ContentT()
output_meta.content.content_properties = _metadata_fb.FeaturePropertiesT()
output_meta.content.contentPropertiesType = (
    _metadata_fb.ContentProperties.FeatureProperties)
output_stats = _metadata_fb.StatsT()
output_stats.max = [1.0]
output_stats.min = [0.0]
output_meta.stats = output_stats
label_file = _metadata_fb.AssociatedFileT()
label_file.name = os.path.basename("your_path_to_label_file")
label_file.description = "Labels for objects that the model can recognize."
label_file.type = _metadata_fb.AssociatedFileType.TENSOR_AXIS_LABELS
output_meta.associatedFiles = [label_file]

Crear los búferes planos de metadatos

El siguiente código combina la información del modelo con la información de entrada y salida:

# Creates subgraph info.
subgraph = _metadata_fb.SubGraphMetadataT()
subgraph.inputTensorMetadata = [input_meta]
subgraph.outputTensorMetadata = [output_meta]
model_meta.subgraphMetadata = [subgraph]

b = flatbuffers.Builder(0)
b.Finish(
    model_meta.Pack(b),
    _metadata.MetadataPopulator.METADATA_FILE_IDENTIFIER)
metadata_buf = b.Output()

Empaquetar metadatos y archivos asociados en el modelo

Una vez creado el Flatbuffers de metadatos, los metadatos y el archivo de etiquetas se escriben en el archivo TFLite a través de la populate método:

populator = _metadata.MetadataPopulator.with_model_file(model_file)
populator.load_metadata_buffer(metadata_buf)
populator.load_associated_files(["your_path_to_label_file"])
populator.populate()

Puede empaquetar todos los archivos asociados como desee en el modelo a través de load_associated_files . Sin embargo, es necesario empaquetar al menos los archivos documentados en los metadatos. En este ejemplo, es obligatorio empaquetar el archivo de etiquetas.

Visualiza los metadatos

Puede utilizar Netron para visualizar los metadatos, o puede leer los metadatos de un modelo TensorFlow Lite en un formato JSON utilizando el MetadataDisplayer :

displayer = _metadata.MetadataDisplayer.with_model_file(export_model_path)
export_json_file = os.path.join(FLAGS.export_directory,
                    os.path.splitext(model_basename)[0] + ".json")
json_file = displayer.get_metadata_json()
# Optional: write out the metadata as a json file
with open(export_json_file, "w") as f:
  f.write(json_file)

Android Studio también permite mostrar los metadatos a través de la función de unión Android Studio ML .

Control de versiones de metadatos

El esquema de metadatos se versiona tanto por el número de versiones Semántica, que rastrea los cambios en el archivo de esquema, y por la identificación de archivo Flatbuffers, lo que indica la verdadera compatibilidad de la versión.

El número de versión semántica

El esquema de metadatos está versionada por el número de versiones Semántica , tales como MAJOR.MINOR.PATCH. Realiza un seguimiento de los cambios de esquema de acuerdo con las reglas aquí . Ver la historia de los campos añadidos después de la versión 1.0.0 .

La identificación del archivo Flatbuffers

El versionado semántico garantiza la compatibilidad si se siguen las reglas, pero no implica la verdadera incompatibilidad. Al aumentar el número PRINCIPAL, no significa necesariamente que la compatibilidad con versiones anteriores esté rota. Por lo tanto, utilizamos la identificación del archivo Flatbuffers , file_identifier , para denotar la verdadera compatibilidad del esquema de metadatos. El identificador de archivo tiene exactamente 4 caracteres. Está fijado a un determinado esquema de metadatos y no está sujeto a cambios por parte de los usuarios. Si la compatibilidad con versiones anteriores del esquema de metadatos tiene que romperse por alguna razón, el identificador de archivo aumentará, por ejemplo, de “M001” a “M002”. Se espera que File_identifier se cambie con mucha menos frecuencia que metadata_version.

La versión mínima necesaria del analizador de metadatos

La versión mínima necesaria analizador de metadatos es la versión mínima del programa de análisis de metadatos (los Flatbuffers generan código) que puede leer los metadatos Flatbuffers en su totalidad. La versión es efectivamente el número de versión más grande entre las versiones de todos los campos rellenados y la versión compatible más pequeña indicada por el identificador de archivo. La versión de metadatos analizador mínima necesaria se rellena automáticamente por el MetadataPopulator cuando los metadatos se rellena en un modelo TFLite. Ver el extractor de metadatos para obtener más información sobre cómo se utiliza la versión mínima necesaria analizador de metadatos.

Leer los metadatos de los modelos

La biblioteca de metadatos Extractor es herramienta conveniente para leer los metadatos y los ficheros asociados a los modelos a través de diferentes plataformas (véase la versión de Java y la versión de C ++ ). Puede crear su propia herramienta de extracción de metadatos en otros idiomas utilizando la biblioteca Flatbuffers.

Leer los metadatos en Java

Para utilizar la biblioteca de metadatos Extractor en su aplicación para Android, se recomienda utilizar el TensorFlow Lite metadatos AAR alojado en MavenCentral . Contiene el MetadataExtractor clase, así como los enlaces FlatBuffers Java para el esquema de metadatos y el esquema de modelo .

Puede especificar esto en sus build.gradle dependencias de la siguiente manera:

dependencies {
    implementation 'org.tensorflow:tensorflow-lite-metadata:0.1.0'
}

Para utilizar instantáneas nocturnas, asegúrese de que ha agregado repositorio Sonatype instantánea .

Puede inicializar un MetadataExtractor objeto con un ByteBuffer que los puntos en el modelo:

public MetadataExtractor(ByteBuffer buffer);

El ByteBuffer debe permanecer sin cambios durante toda la vida útil de la MetadataExtractor objeto. La inicialización puede fallar si el identificador de archivo Flatbuffers de los metadatos del modelo no coincide con el del analizador de metadatos. Ver metadatos de versiones para más información.

Con identificadores de archivo coincidentes, el extractor de metadatos leerá con éxito los metadatos generados a partir de todos los esquemas pasados ​​y futuros debido al mecanismo de compatibilidad hacia adelante y hacia atrás de Flatbuffers. Sin embargo, los extractores de metadatos más antiguos no pueden extraer campos de esquemas futuros. La versión mínima necesaria analizador de los metadatos indica la versión mínima del programa de análisis de metadatos que puede leer los metadatos Flatbuffers en su totalidad. Puede utilizar el siguiente método para verificar si se cumple la condición mínima necesaria de la versión del analizador:

public final boolean isMinimumParserVersionSatisfied();

Se permite pasar un modelo sin metadatos. Sin embargo, invocar métodos que leen de los metadatos provocará errores en tiempo de ejecución. Puede comprobar si tiene un modelo de metadatos mediante la invocación del hasMetadata método:

public boolean hasMetadata();

MetadataExtractor ofrece funciones convenientes para usted para obtener los metadatos de los tensores de entrada / salida. Por ejemplo,

public int getInputTensorCount();
public TensorMetadata getInputTensorMetadata(int inputIndex);
public QuantizationParams getInputTensorQuantizationParams(int inputIndex);
public int[] getInputTensorShape(int inputIndex);
public int getoutputTensorCount();
public TensorMetadata getoutputTensorMetadata(int inputIndex);
public QuantizationParams getoutputTensorQuantizationParams(int inputIndex);
public int[] getoutputTensorShape(int inputIndex);

Aunque el modelo de esquema TensorFlow Lite es compatible con varios subgrafos, el intérprete TFLite actualmente sólo es compatible con un solo subgrafo. Por lo tanto, MetadataExtractor omite índice subgrafo como un argumento de entrada en sus métodos.

Leer los archivos asociados de los modelos

El modelo de TensorFlow Lite con metadatos y archivos asociados es esencialmente un archivo zip que se puede descomprimir con herramientas zip comunes para obtener los archivos asociados. Por ejemplo, se puede descomprimir mobilenet_v1_0.75_160_quantized y extraer el archivo de etiquetas en el modelo de la siguiente manera:

$ unzip mobilenet_v1_0.75_160_quantized_1_metadata_1.tflite
Archive:  mobilenet_v1_0.75_160_quantized_1_metadata_1.tflite
 extracting: labels.txt

También puede leer archivos asociados a través de la biblioteca Metadata Extractor.

En Java, pasar el nombre de archivo en la MetadataExtractor.getAssociatedFile método:

public InputStream getAssociatedFile(String fileName);

Similarmente, en C ++, esto se puede hacer con el método, ModelMetadataExtractor::GetAssociatedFile :

tflite::support::StatusOr<absl::string_view> GetAssociatedFile(
      const std::string& filename) const;