Cómo agregar metadatos a modelos de LiteRT

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

Todos los modelos de imágenes publicados en Kaggle Los modelos se propagaron con metadatos.

Modelo con formato de metadatos

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

Los metadatos del modelo se definen en metadata_schema.fbs: pañal FlatBuffer . Como se muestra en la Figura 1, estos se almacenan metadatos del modelo TFLite esquema, con el nombre "TFLITE_METADATA". Algunos modelos pueden incluir archivos asociados, como etiqueta de clasificación .tfvars. Estos archivos se concatenan al final del archivo de modelo original como un archivo ZIP con el archivo ZipFile "append" automático (modo 'a'). TFLite El intérprete puede consumir el nuevo formato de archivo de la misma manera que antes. Consulta Paquete los archivos asociados para obtener más información.

Consulta las siguientes instrucciones para propagar, visualizar y leer metadatos.

Configura las herramientas de metadatos

Antes de agregar metadatos a tu modelo, necesitarás un comando de del entorno de ejecución para ejecutar TensorFlow. Hay una guía detallada sobre cómo puedes configurar esto aquí.

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

pip install tflite-support

Las herramientas de metadatos de LiteRT son compatibles con Python 3.

Agrega metadatos con la API de Flatbuffers para Python

Los metadatos del modelo tienen tres partes esquema:

  1. Información del modelo: Descripción general del modelo, así como de los elementos como los términos de la licencia. Consulta ModelMetadata.
    1. Información de entrada: Es la descripción de las entradas y el procesamiento previo. como la normalización. Consulta SubGraphMetadata.input_tensor_metadata.
      1. Información del resultado: descripción de la salida y el procesamiento previo requerido, como la asignación de etiquetas. Consulta SubGraphMetadata.output_tensor_metadata.

Como LiteRT solo admite un subgrafo en este momento, el Generador de código LiteRT y la Vinculación de AA de Android Studio atributo usarán ModelMetadata.name y ModelMetadata.description, en lugar de SubGraphMetadata.name y SubGraphMetadata.description, cuando se muestran metadatos y la generación de código.

Tipos de entrada y salida admitidos

Los metadatos LiteRT de entrada y salida no están diseñados los tipos de modelo, sino los de entrada y salida. No importa qué que hace el modelo funcionalmente, siempre que los tipos de entrada y salida constan lo siguiente, o una combinación de los siguientes, es compatible con TensorFlow Metadatos Lite:

  • Atributo: números que son números enteros sin firma o float32.
  • Imagen: Actualmente, los metadatos admiten imágenes RGB y en escala de grises.
  • Cuadro de límite: son cuadros de límite de forma rectangular. El esquema admite un variedad de numeración esquemas.

Empaqueta los archivos asociados

Los modelos LiteRT pueden incluir diferentes archivos asociados. Por ejemplo: los modelos de lenguaje natural generalmente tienen archivos de vocabulario que asignan fragmentos de palabras a palabras IDs; 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 agrupar con el modelo a través de los metadatos. biblioteca de Python. El nuevo modelo LiteRT se convierte en un archivo ZIP que contiene el modelo y los archivos asociados. Puede desempaquetarse con archivos ZIP comunes con herramientas de visualización. Este nuevo formato de modelo sigue usando la misma extensión de archivo: .tflite. Integra es compatible con el framework y el intérprete de TFLite existentes. Consulta Empaquetar metadatos y archivos asociados en la model para obtener más información.

La información del archivo asociado se puede registrar en los metadatos. Según el tipo de archivo y al que está adjunto el archivo (es decir, ModelMetadata, SubGraphMetadata y TensorMetadata), el código LiteRT de Android generador puede aplicar los valores previos y posteriores se procesan automáticamente en el objeto. Consulta el <Uso de Codegen> sección de cada archivo asociado tipo en el esquema para obtener más detalles.

Parámetros de normalización y cuantización

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

La cuantización del modelo es una técnica que permite reducir las representaciones de precisión de los pesos y, opcionalmente, para almacenar y procesar datos.

En términos de procesamiento previo y posterior, la normalización y la cuantización son dos pasos independientes. A continuación, le indicamos los detalles.

Normalización Cuantización

Un ejemplo de la valores de parámetros del imagen de entrada en MobileNet para números de punto flotante y modelos cuantitativos, respectivamente.
Modelo de número de punto flotante:
- media: 127.5
- estándar: 127.5
Modelo cuantitativo:
- media: 127.5
- estándar: 127,5
Modelo de número de punto flotante:
- zeroPoint: 0
- escala: 1.0
Modelo cuantitativo:
- zeroPoint: 128.0
- scale:0.0078125f




¿Cuándo se debe invocar?


Inputs: Si se trata de una entrada los datos se normalizan en el entrenamiento, la entrada datos de necesidades de inferencia para normalizar según corresponda.
Resultados: Resultado los datos no serán normalizados en general.
Los modelos flotantes hacen no necesitan cuantización.
Un modelo cuantificado puede o que no necesites cuantización en el rendimiento previo y posterior el procesamiento de datos. Depende sobre el tipo de datos de de entrada y salida.
- tensores de número de punto flotante: no cuantización en el rendimiento previo y posterior el procesamiento necesario. Quant op y op decuantitativa en el modelo gráfico.
- Tensores de int8 y uint8: necesitan cuantización en procesamiento previo y posterior.


Fórmula


entrada_normalizada = (entrada: media) / std
Cuantizar las entradas:
q = f / escala + zeroPoint
Decuantizar para resultados:
f = (q - zeroPoint) * escala

¿Dónde se encuentran parámetros
Completado por el creador del modelo y se almacenan en el modelo metadatos, como NormalizationOptions Completado automáticamente por conversor de TFLite y almacenado en un modelo de tflite .
Cómo obtener la parámetros? Mediante la API de MetadataExtractor [2] A través de TFLite API de Tensor [1] o mediante la API de MetadataExtractor [2]
Usar números de punto flotante y cuantitativos los modelos comparten el mismo valor? Sí, número de punto flotante y cuantita tienen el mismo Normalización parámetros No, el modelo de número de punto flotante no necesitan cuantización.
¿TFLite codifica generador o Android Vinculación de AA de Studio generar automáticamente en el procesamiento de datos?

[1] El LiteRT Java Java API y la clase de lenguaje LiteRT C++, de la API.
[2] La biblioteca de extractor de metadatos

Cuando se procesan datos de imágenes para modelos de uint8, la normalización y la cuantización se a veces se omiten. Es correcto hacerlo cuando los valores de los píxeles están en el rango de [0, 255]. Pero, en general, siempre debes procesar los datos de acuerdo con los parámetros de normalización y cuantización cuando corresponda.

Ejemplos

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

Clasificación de imágenes

Descarga la secuencia de comandos aquí , que completa los metadatos mobilenet_v1_0.75_160_quantized.tflite. Ejecuta la secuencia de comandos de la siguiente manera:

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

Si quieres propagar metadatos para otros modelos de clasificación de imágenes, agrega las especificaciones del modelo Me gusta este en el guion. En el resto de esta guía, se destacarán algunas de las secciones clave en el ejemplo de clasificación de imágenes para ilustrar los elementos clave.

Análisis detallado del ejemplo de clasificación de imágenes

Información del modelo

Los metadatos comienzan con la creación de una nueva información del 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 y salida

En esta sección, se muestra cómo describir la firma de entrada y salida de tu modelo. Los generadores automáticos de código pueden usar estos metadatos para crear predicciones el código de procesamiento. Para crear información de entrada o salida sobre un tensor, haz lo siguiente:

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

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

Entrada de imágenes

La imagen es un tipo de entrada común para el aprendizaje automático. Metadatos de LiteRT admite información como el espacio de color y la información de procesamiento previo, como normalización. La dimensión de la imagen no requiere especificación manual dado que ya está proporcionada por la forma del tensor de entrada se infieren 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 la etiqueta

La etiqueta puede asignarse a un tensor de salida mediante un archivo asociado con 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]

Crea los búferes planos de metadatos

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

# 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 creados los búferes planos de metadatos, los metadatos y el archivo de etiquetas escrito en el archivo TFLite con el método populate:

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

Puedes empaquetar tantos archivos asociados como desees en el modelo load_associated_files Sin embargo, es necesario empaquetar al menos esos archivos. documentados en los metadatos. En este ejemplo, empaquetar el archivo de etiquetas es es obligatorio.

Visualiza los metadatos

Puedes usar Netron para visualizar tus o puedes leerlos de un modelo LiteRT a un archivo JSON con 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 admite la visualización de metadatos a través del AA de Android Studio Vinculación función.

Control de versiones de metadatos

Los metadatos esquema cuenta con un número de control semántico que rastrea el archivo de esquema y la identificación del archivo Flatbuffers, que indica la compatibilidad de versiones verdadera.

El número de control de versiones semántico

El esquema de metadatos tiene control de versiones a través del control de versiones semántico número, como MAJOR.MINOR.PATCH. Hace un seguimiento de los cambios de esquema según las reglas. aquí. Conoce la historia de campos agregado después de la versión 1.0.0.

La identificación del archivo FlatBuffers

El control de versiones semántico garantiza la compatibilidad si se siguen las reglas, pero no implica la verdadera incompatibilidad. Al aumentar el número MAJOR, no necesariamente significa que la retrocompatibilidad no funcione. Por lo tanto, usa el archivo Flatbuffers identificación, file_identifier, para indicar la verdadera compatibilidad del esquema de metadatos. El identificador de archivo es exactamente 4 caracteres. Se fija en un esquema de metadatos determinado, sujeta a cambios por parte de los usuarios. Si la retrocompatibilidad del esquema de metadatos debe fallar por algún motivo, el file_identifier aparecerá, por ejemplo, de “M001” a “M002”. Se espera que File_identifier cambie mucho menos. con frecuencia que metadata_version.

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

El analizador de metadatos mínimo necesario versión es la versión mínima del analizador de metadatos (el código generado por Flatbuffers) que puedan leer los metadatos FlatBuffers por completo. La versión es efectivamente el mayor número de versión entre las versiones de todos los campos completados y el versión compatible más pequeña indicada por el identificador del archivo. El mínimo la versión necesaria del analizador de metadatos se completa automáticamente MetadataPopulator cuando los metadatos se propagan a un modelo de TFLite. Consulta la extractor de metadatos para obtener más información se usa la versión mínima necesaria del analizador de metadatos.

Lee los metadatos de los modelos

La biblioteca de extracción de metadatos es una herramienta práctica para leer los metadatos y asociados a partir de un modelo en distintas plataformas (consulta la documentación de Java versión y el código C++ versión). Puedes crear tu propia herramienta de extracción de metadatos en otros lenguajes con el Biblioteca de FlatBuffers.

Lee los metadatos en Java

Para usar la biblioteca del extractor de metadatos en tu app para Android, te recomendamos usar las AAR de metadatos de LiteRT alojadas en MavenCentral. Contiene la clase MetadataExtractor y FlatBuffers Java vinculaciones para los metadatos esquema y el modelo esquema.

Puedes especificarlo en tus dependencias de build.gradle de la siguiente manera:

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

Para usar instantáneas nocturnas, asegúrate de haber agregado Instantánea de Sonatype Cloud Storage.

Puedes inicializar un objeto MetadataExtractor con un ByteBuffer que apunte al modelo:

public MetadataExtractor(ByteBuffer buffer);

El ByteBuffer debe permanecer igual durante toda la vida útil de la MetadataExtractor. La inicialización puede fallar si el archivo Flatbuffers de metadatos del modelo no coincide con el del analizador de metadatos. Consulta control de versiones de metadatos para obtener más información.

Con los identificadores de archivo coincidentes, el extractor de metadatos leerá correctamente los metadatos generados a partir de todos los esquemas pasados y futuros debido a los y el mecanismo de retrocompatibilidad. Sin embargo, los campos de valores Los extractores más antiguos no pueden extraer esquemas. El mínimo necesario versión del analizador de los metadatos indica la versión mínima del analizador de metadatos que puede leer los metadatos búferes planos completos. Puedes usar el siguiente método para verificar si la duración se cumple la condición necesaria de la versión del analizador:

public final boolean isMinimumParserVersionSatisfied();

Se permite pasar un modelo sin metadatos. Sin embargo, invocar métodos que leer de los metadatos provocará errores de tiempo de ejecución. Puedes comprobar si un modelo tiene metadatos invocando el método hasMetadata:

public boolean hasMetadata();

MetadataExtractor proporciona funciones prácticas para que obtengas la de tensores de entrada y salida metadatos. 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);

Si bien el modelo LiteRT esquema admite varios subgrafos, el intérprete de TFLite actualmente solo admite en un solo subgrafo. Por lo tanto, MetadataExtractor omite el índice de subgrafo como entrada. argumento en sus métodos.

Leer los archivos asociados de modelos

El modelo LiteRT con metadatos y archivos asociados es, en esencia, un que se puede descomprimir con herramientas ZIP comunes para obtener los archivos asociados. Por ejemplo, puedes descomprimir mobilenet_v1_0.75_160_quantized y extrae 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 puedes leer los archivos asociados a través de la biblioteca del extractor de metadatos.

En Java, pasa el nombre del archivo a MetadataExtractor.getAssociatedFile. método:

public InputStream getAssociatedFile(String fileName);

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

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