Merci de vous être connecté à Google I/O. Voir toutes les sessions à la demande Regarder à la demande

Ajouter des métadonnées aux modèles TensorFlow Lite

Les métadonnées TensorFlow Lite fournissent une norme pour les descriptions de modèles. Les métadonnées sont une source importante de connaissances sur ce que fait le modèle et ses informations d'entrée/sortie. Les métadonnées comprennent à la fois

Tous les modèles d'image publiés sur TensorFlow Hub ont été renseignés avec des métadonnées.

Modèle avec format de métadonnées

model_with_metadata
Figure 1. Modèle TFLite avec métadonnées et fichiers associés.

Les métadonnées du modèle sont définies dans metadata_schema.fbs , un fichier FlatBuffer . Comme le montre la figure 1, il est stocké dans le champ de métadonnées du schéma de modèle TFLite , sous le nom "TFLITE_METADATA" . Certains modèles peuvent être accompagnés de fichiers associés, tels que des fichiers d'étiquettes de classification . Ces fichiers sont concaténés à la fin du fichier de modèle d'origine sous forme de ZIP en utilisant le mode "append" ZipFile (mode 'a' ). TFLite Interpreter peut utiliser le nouveau format de fichier de la même manière qu'auparavant. Voir Compresser les fichiers associés pour plus d'informations.

Consultez les instructions ci-dessous pour savoir comment remplir, visualiser et lire les métadonnées.

Configurer les outils de métadonnées

Avant d'ajouter des métadonnées à votre modèle, vous devez configurer un environnement de programmation Python pour exécuter TensorFlow. Il y a un guide détaillé sur la façon de le configurer ici .

Après avoir configuré l'environnement de programmation Python, vous devrez installer des outils supplémentaires :

pip install tflite-support

Les outils de métadonnées TensorFlow Lite sont compatibles avec Python 3.

Ajout de métadonnées à l'aide de l'API Python Flatbuffers

Il y a trois parties dans les métadonnées du modèle dans le schéma :

  1. Informations sur le modèle - Description générale du modèle ainsi que des éléments tels que les termes de la licence. Voir ModelMetadata .
  2. Informations d'entrée - Description des entrées et du prétraitement requis, comme la normalisation. Voir SubGraphMetadata.input_tensor_metadata .
  3. Informations de sortie - Description de la sortie et du post-traitement requis, tels que le mappage aux étiquettes. Voir SubGraphMetadata.output_tensor_metadata .

Étant donné que TensorFlow Lite ne prend en charge qu'un seul sous-graphe à ce stade, le générateur de code TensorFlow Lite et la fonctionnalité Android Studio ML Binding utiliseront ModelMetadata.name et ModelMetadata.description , au lieu de SubGraphMetadata.name et SubGraphMetadata.description , lors de l'affichage des métadonnées et de la génération de code.

Types d'entrée/sortie pris en charge

Les métadonnées TensorFlow Lite pour l'entrée et la sortie ne sont pas conçues avec des types de modèle spécifiques à l'esprit, mais plutôt avec des types d'entrée et de sortie. Peu importe ce que le modèle fait sur le plan fonctionnel, tant que les types d'entrée et de sortie se composent des éléments suivants ou d'une combinaison des éléments suivants, il est pris en charge par les métadonnées TensorFlow Lite :

  • Fonctionnalité - Nombres qui sont des entiers non signés ou float32.
  • Image - Les métadonnées prennent actuellement en charge les images RVB et en niveaux de gris.
  • Boîte englobante - Boîtes englobantes de forme rectangulaire. Le schéma prend en charge une variété de schémas de numérotation .

Emballez les fichiers associés

Les modèles TensorFlow Lite peuvent être livrés avec différents fichiers associés. Par exemple, les modèles de langage naturel ont généralement des fichiers de vocabulaire qui associent des morceaux de mots à des identifiants de mots ; les modèles de classification peuvent avoir des fichiers d'étiquettes qui indiquent les catégories d'objets. Sans les fichiers associés (s'il y en a), un modèle ne fonctionnera pas bien.

Les fichiers associés peuvent désormais être regroupés avec le modèle via la bibliothèque de métadonnées Python. Le nouveau modèle TensorFlow Lite devient un fichier zip qui contient à la fois le modèle et les fichiers associés. Il peut être décompressé avec des outils zip courants. Ce nouveau format de modèle utilise toujours la même extension de fichier, .tflite . Il est compatible avec le framework et l'interpréteur TFLite existants. Voir Compresser les métadonnées et les fichiers associés dans le modèle pour plus de détails.

Les informations de fichier associées peuvent être enregistrées dans les métadonnées. Selon le type de fichier et l'endroit où le fichier est attaché (c'est-à-dire ModelMetadata , SubGraphMetadata et TensorMetadata ), le générateur de code Android TensorFlow Lite peut appliquer automatiquement le pré/post-traitement correspondant à l'objet. Voir la section <Codegen usage> de chaque type de fichier associé dans le schéma pour plus de détails.

Paramètres de normalisation et de quantification

La normalisation est une technique courante de prétraitement des données dans l'apprentissage automatique. Le but de la normalisation est de changer les valeurs à une échelle commune, sans déformer les différences dans les plages de valeurs.

La quantification du modèle est une technique qui permet des représentations de précision réduite des poids et éventuellement des activations pour le stockage et le calcul.

En termes de prétraitement et de post-traitement, la normalisation et la quantification sont deux étapes indépendantes. Voici les détails.

Normalisation Quantification

Un exemple des valeurs de paramètre de l'image d'entrée dans MobileNet pour les modèles float et quant, respectivement.
Modèle flotteur :
- moyenne : 127,5
- norme : 127,5
Quant modèle :
- moyenne : 127,5
- norme : 127,5
Modèle flotteur :
- point zéro : 0
- échelle : 1.0
Quant modèle :
- point zéro : 128,0
- échelle : 0.0078125f




Quand invoquer ?


Entrées : si les données d'entrée sont normalisées lors de la formation, les données d'entrée de l'inférence doivent être normalisées en conséquence.
Sorties : les données de sortie ne seront pas normalisées en général.
Les modèles flottants n'ont pas besoin de quantification.
Le modèle quantifié peut nécessiter ou non une quantification dans le pré/post-traitement. Cela dépend du type de données des tenseurs d'entrée/sortie.
- tenseurs flottants : aucune quantification n'est nécessaire dans le pré/post-traitement. Quant op et dequant op sont intégrés dans le graphe du modèle.
- Tensors int8/uint8 : besoin de quantification en pré/post traitement.


Formule


entrée_normalisée = (entrée - moyenne) / std
Quantifier pour les entrées :
q = f / échelle + point zéro
Déquantifier pour les sorties :
f = (q - point zéro) * échelle

Où sont les paramètres
Rempli par le créateur du modèle et stocké dans les métadonnées du modèle, en tant que NormalizationOptions Rempli automatiquement par le convertisseur TFLite et stocké dans le fichier de modèle tflite.
Comment obtenir les paramètres ? Via l'API MetadataExtractor [2] Via l'API TFLite Tensor [1] ou via l'API MetadataExtractor [2]
Les modèles float et quant partagent-ils la même valeur ? Oui, les modèles float et quant ont les mêmes paramètres de normalisation Non, le modèle flottant n'a pas besoin de quantification.
Le générateur de code TFLite ou la liaison Android Studio ML le génère-t-il automatiquement dans le traitement des données ?
Oui

Oui

[1] L' API Java TensorFlow Lite et l'API C++ TensorFlow Lite .
[2] La bibliothèque d'extraction de métadonnées

Lors du traitement des données d'image pour les modèles uint8, la normalisation et la quantification sont parfois ignorées. C'est bien de le faire lorsque les valeurs de pixel sont dans la plage de [0, 255]. Mais en général, vous devez toujours traiter les données en fonction des paramètres de normalisation et de quantification, le cas échéant.

La bibliothèque de tâches TensorFlow Lite peut gérer la normalisation pour vous si vous configurez NormalizationOptions dans les métadonnées. Le traitement de quantification et de déquantification est toujours encapsulé.

Exemples

Vous pouvez trouver des exemples sur la façon dont les métadonnées doivent être renseignées pour différents types de modèles ici :

Classement des images

Téléchargez le script ici , qui renseigne les métadonnées sur mobilenet_v1_0.75_160_quantized.tflite . Exécutez le script comme ceci :

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

Pour remplir les métadonnées d'autres modèles de classification d'images, ajoutez les spécifications du modèle comme celle -ci dans le script. Le reste de ce guide mettra en évidence certaines des sections clés de l'exemple de classification d'images pour illustrer les éléments clés.

Plongez dans l'exemple de classification d'images

Informations sur le modèle

Les métadonnées commencent par créer une nouvelle information de modèle :

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.")

Informations d'entrée/sortie

Cette section vous montre comment décrire la signature d'entrée et de sortie de votre modèle. Ces métadonnées peuvent être utilisées par des générateurs de code automatiques pour créer du code de pré- et post-traitement. Pour créer des informations d'entrée ou de sortie sur un tenseur :

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

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

Entrée d'images

L'image est un type d'entrée courant pour l'apprentissage automatique. Les métadonnées TensorFlow Lite prennent en charge des informations telles que l'espace colorimétrique et les informations de prétraitement telles que la normalisation. La dimension de l'image ne nécessite pas de spécification manuelle car elle est déjà fournie par la forme du tenseur d'entrée et peut être déduite automatiquement.

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

Sortie d'étiquette

L'étiquette peut être mappée à un tenseur de sortie via un fichier associé à l'aide de 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]

Créer les flatbuffers de métadonnées

Le code suivant combine les informations du modèle avec les informations d'entrée et de sortie :

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

Emballez les métadonnées et les fichiers associés dans le modèle

Une fois les métadonnées Flatbuffers créées, les métadonnées et le fichier d'étiquettes sont écrits dans le fichier TFLite via la méthode 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()

Vous pouvez regrouper autant de fichiers associés que vous le souhaitez dans le modèle via load_associated_files . Cependant, il est nécessaire de compresser au moins les fichiers documentés dans les métadonnées. Dans cet exemple, l'emballage du fichier d'étiquettes est obligatoire.

Visualisez les métadonnées

Vous pouvez utiliser Netron pour visualiser vos métadonnées, ou vous pouvez lire les métadonnées d'un modèle TensorFlow Lite dans un format json en utilisant le 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 prend également en charge l'affichage des métadonnées via la fonctionnalité Android Studio ML Binding .

Versionnement des métadonnées

Le schéma de métadonnées est versionné à la fois par le numéro de version sémantique, qui suit les modifications du fichier de schéma, et par l'identification du fichier Flatbuffers, qui indique la véritable compatibilité de la version.

Le numéro de version sémantique

Le schéma de métadonnées est versionné par le numéro de version sémantique , tel que MAJOR.MINOR.PATCH. Il suit les changements de schéma selon les règles ici . Voir l' historique des champs ajoutés après la version 1.0.0 .

L'identification du fichier Flatbuffers

Le versioning sémantique garantit la compatibilité si l'on suit les règles, mais cela n'implique pas la véritable incompatibilité. Lorsque vous augmentez le nombre MAJEUR, cela ne signifie pas nécessairement que la rétrocompatibilité est rompue. Par conséquent, nous utilisons l' identification de fichier Flatbuffers , file_identifier , pour indiquer la véritable compatibilité du schéma de métadonnées. L'identifiant du fichier comporte exactement 4 caractères. Il est fixé à un certain schéma de métadonnées et n'est pas susceptible d'être modifié par les utilisateurs. Si la rétrocompatibilité du schéma de métadonnées doit être interrompue pour une raison quelconque, le file_identifier passera, par exemple, de « M001 » à « M002 ». File_identifier devrait être modifié beaucoup moins fréquemment que metadata_version.

La version minimale nécessaire de l'analyseur de métadonnées

La version minimale nécessaire de l'analyseur de métadonnées est la version minimale de l'analyseur de métadonnées (le code généré par Flatbuffers) qui peut lire les métadonnées Flatbuffers dans leur intégralité. La version est effectivement le plus grand numéro de version parmi les versions de tous les champs renseignés et la plus petite version compatible indiquée par l'identifiant du fichier. La version minimale nécessaire de l'analyseur de métadonnées est automatiquement renseignée par le MetadataPopulator lorsque les métadonnées sont renseignées dans un modèle TFLite. Consultez l' extracteur de métadonnées pour plus d'informations sur l'utilisation de la version minimale nécessaire de l'analyseur de métadonnées.

Lire les métadonnées des modèles

La bibliothèque Metadata Extractor est un outil pratique pour lire les métadonnées et les fichiers associés d'un modèle sur différentes plateformes (voir la version Java et la version C++ ). Vous pouvez créer votre propre outil d'extraction de métadonnées dans d'autres langages à l'aide de la bibliothèque Flatbuffers.

Lire les métadonnées en Java

Pour utiliser la bibliothèque Metadata Extractor dans votre application Android, nous vous recommandons d'utiliser l' AAR de métadonnées TensorFlow Lite hébergé sur MavenCentral . Il contient la classe MetadataExtractor , ainsi que les liaisons Java FlatBuffers pour le schéma de métadonnées et le schéma de modèle .

Vous pouvez le spécifier dans vos dépendances build.gradle comme suit :

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

Pour utiliser des instantanés nocturnes, assurez-vous d'avoir ajouté le référentiel d'instantanés Sonatype .

Vous pouvez initialiser un objet MetadataExtractor avec un ByteBuffer qui pointe vers le modèle :

public MetadataExtractor(ByteBuffer buffer);

Le ByteBuffer doit rester inchangé pendant toute la durée de vie de l'objet MetadataExtractor . L'initialisation peut échouer si l'identifiant de fichier Flatbuffers des métadonnées du modèle ne correspond pas à celui de l'analyseur de métadonnées. Voir gestion des versions des métadonnées pour plus d'informations.

Avec des identifiants de fichiers correspondants, l'extracteur de métadonnées lira avec succès les métadonnées générées à partir de tous les schémas passés et futurs grâce au mécanisme de compatibilité ascendante et descendante des Flatbuffers. Cependant, les champs des futurs schémas ne peuvent pas être extraits par les anciens extracteurs de métadonnées. La version minimale nécessaire de l'analyseur des métadonnées indique la version minimale de l'analyseur de métadonnées qui peut lire les métadonnées Flatbuffers dans leur intégralité. Vous pouvez utiliser la méthode suivante pour vérifier si la condition de version minimale nécessaire de l'analyseur est remplie :

public final boolean isMinimumParserVersionSatisfied();

La transmission d'un modèle sans métadonnées est autorisée. Cependant, l'appel de méthodes qui lisent à partir des métadonnées entraînera des erreurs d'exécution. Vous pouvez vérifier si un modèle contient des métadonnées en appelant la méthode hasMetadata :

public boolean hasMetadata();

MetadataExtractor fournit des fonctions pratiques pour vous permettre d'obtenir les métadonnées des tenseurs d'entrée/sortie. Par exemple,

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

Bien que le schéma du modèle TensorFlow Lite prenne en charge plusieurs sous-graphes, l'interpréteur TFLite ne prend actuellement en charge qu'un seul sous-graphe. Par conséquent, MetadataExtractor omet l'index de sous-graphe comme argument d'entrée dans ses méthodes.

Lire les fichiers associés à partir des modèles

Le modèle TensorFlow Lite avec métadonnées et fichiers associés est essentiellement un fichier zip qui peut être décompressé avec des outils zip courants pour obtenir les fichiers associés. Par exemple, vous pouvez décompresser mobilenet_v1_0.75_160_quantized et extraire le fichier d'étiquette dans le modèle comme suit :

$ 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

Vous pouvez également lire les fichiers associés via la bibliothèque Metadata Extractor.

En Java, transmettez le nom du fichier dans la méthode MetadataExtractor.getAssociatedFile :

public InputStream getAssociatedFile(String fileName);

De même, en C++, cela peut être fait avec la méthode ModelMetadataExtractor::GetAssociatedFile :

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