Aggiunta di metadati ai modelli LiteRT

I metadati LiteRT forniscono uno standard per le descrizioni dei modelli. La i metadati sono un'importante fonte di conoscenza su cosa fa il modello e sulle sue informazioni di input / output. I metadati sono costituiti da

Tutti i modelli di immagine pubblicati su Kaggle I modelli sono stati compilati con metadati.

Modello con formato metadati

model_with_metadata
Figura 1. Modello TFLite con metadati e file associati.

I metadati del modello sono definiti metadata_schema.fbs, un FlatBuffer . Come mostrato nella Figura 1, viene archiviato metadati campo del modello TFLite di testo, sotto il nome "TFLITE_METADATA". Alcuni modelli potrebbero essere forniti con file associati, come etichetta di classificazione file. Questi file sono concatenati alla fine del file del modello originale come file ZIP utilizzando l'elemento ZipFile "append" (modalità 'a'). TFLite La modalità Interprete può utilizzare il nuovo formato file come prima. Vedi Pacchetto i file associati per ulteriori informazioni.

Per informazioni su come compilare, visualizzare e leggere i metadati, consulta le istruzioni riportate di seguito.

Configurare gli strumenti per i metadati

Prima di aggiungere i metadati al modello, è necessario un file di programmazione Python per eseguire TensorFlow. È disponibile una guida dettagliata configuralo qui.

Dopo aver configurato l'ambiente di programmazione Python, devi installare strumenti aggiuntivi:

pip install tflite-support

Lo strumento per i metadati LiteRT supporta Python 3.

Aggiunta di metadati utilizzando l'API Python Flatbuffers

I metadati del modello sono costituiti da tre parti schema:

  1. Informazioni sul modello: descrizione complessiva del modello e degli elementi come i termini di licenza. Consulta: ModelMetadata.
    1. Informazioni di input: descrizione degli input e pre-elaborazione come la normalizzazione. Consulta: SubGraphMetadata.input_tensor_metadata.
      1. Informazioni di output: la descrizione dell'output e e la post-elaborazione richiesta, come la mappatura alle etichette. Consulta: SubGraphMetadata.output_tensor_metadata.

Poiché a questo punto LiteRT supporta solo un singolo grafico secondario, Generatore di codice LiteRT e Android Studio ML Binding funzionalità utilizzerà ModelMetadata.name e ModelMetadata.description, al posto di SubGraphMetadata.name e SubGraphMetadata.description quando vengono visualizzati metadati e generazione del codice.

Tipi di input / output supportati

I metadati LiteRT per l'input e l'output non sono progettati con specifiche tipi di modelli, ma piuttosto di tipi di input e output. Non importa cosa funzionalmente il modello, purché i tipi di input e output siano costituiti come segue o in una combinazione dei seguenti, è supportato da TensorFlow Metadati Lite:

  • Funzione: numeri che sono numeri interi senza segno o float32.
  • Immagine: al momento, i metadati supportano le immagini RGB e in scala di grigi.
  • Riquadro di delimitazione: riquadri di delimitazione rettangolari. Lo schema supporta un varietà di numerazione schemi di machine learning.

Comprimere i file associati

I modelli LiteRT possono essere forniti con file associati diversi. Ad esempio: i modelli di linguaggio naturale di solito hanno file di vocaboli che mappano parti di parole a parole ID; I modelli di classificazione possono avere file di etichette che indicano categorie di oggetti. Senza i file associati (se presenti), il modello non funzionerà correttamente.

Ora i file associati possono essere raggruppati con il modello tramite i metadati nella libreria Python. Il nuovo modello LiteRT diventa un file ZIP che contiene sia il modello che i file associati. Può essere scomposto con il file zip comune i nostri strumenti. Questo nuovo formato di modello continua a utilizzare la stessa estensione di file, .tflite. it è compatibile con il framework TFLite e la modalità Interprete esistenti. Consulta Metadati dei pacchetti e file associati modello per ulteriori dettagli.

Le informazioni del file associate possono essere registrate nei metadati. In base a il tipo di file e la posizione in cui è allegato (ad esempio, ModelMetadata, SubGraphMetadata e TensorMetadata), il codice Android LiteRT generatore può applicare i pre/post corrispondenti automaticamente all'oggetto. Vedi l'<utilizzo di Codegen> sezione di ogni file associato tipo nello schema per ulteriori dettagli.

Parametri di normalizzazione e quantizzazione

La normalizzazione è una tecnica di pre-elaborazione dei dati comune nel machine learning. La l'obiettivo della normalizzazione è modificare i valori in una scala comune, senza distorcere le differenze nell'intervallo di valori.

La quantizzazione dei modelli è una tecnica che consente rappresentazioni di precisione ridotta delle ponderazioni e, facoltativamente, sia per l'archiviazione che per il calcolo.

In termini di pre-elaborazione e post-elaborazione, normalizzazione e quantizzazione sono due passaggi indipendenti. Di seguito sono riportati i dettagli:

Normalizzazione Quantizzazione

Un esempio i valori dei parametri immagine di input in MobileNet per numeri in virgola mobile e modelli quantitativi, rispettivamente.
Modello in virgola mobile:
- media: 127,5
- standard: 127,5
Modello Quant:
- media: 127,5
- standard: 127,5
Modello in virgola mobile:
- zeroPoint: 0
- scala: 1,0
Modello Quant:
- zeroPoint: 128,0
- scala:0,0078125f




Quando attivare la chiamata?


Input: se l'input vengono normalizzati l'addestramento, l'input dei dati delle esigenze di inferenza da normalizzare di conseguenza.
Output: output i dati non saranno normalizzati in generale.
I modelli in virgola mobile non necessitano di quantizzazione.
Il modello quantizzato può o potrebbe non aver bisogno quantizzazione e l'elaborazione dei dati. Dipende sul tipo di dati tensori di input/output.
- tensori a virgola mobile: no quantizzazione l'elaborazione necessaria. Quant op e dequant op sono integrate nel modello grafico.
- tensori int8/uint8: la quantizzazione pre e post-elaborazione.


Formula


input_normalizzato = (input - media) / std
Quantifica per gli input:
q = f / scala + zeroPoint
Dequantizza per :
f = (q - zeroPoint) * scala

Dove si trovano parametri
Compilato dal creatore del modello e archiviati nel modello metadati, NormalizationOptions Compilato automaticamente da il convertitore TFLite e archiviati in un modello tflite .
Come ottenere il parametri? Tramite API MetadataExtractor [2]. Tramite TFLite API Tensor [1] oppure tramite API MetadataExtractor [2].
Fluttua e quantifica condividono lo stesso ? Sì, in virgola mobile e quantitativo hanno lo stesso Normalizzazione parametri No, il modello in virgola mobile non necessitano di quantizzazione.
TFLite Code generatore o Android Associazione Studio ML genera automaticamente nell'elaborazione dei dati?

[1] La libreria LiteRT Java tramite Google Cloud e LiteRT C++ l'API.
[2] La libreria di estrazione dei metadati

Durante l'elaborazione dei dati di immagine per i modelli uint8, la normalizzazione e la quantizzazione sono a volte ignorati. È possibile farlo quando i valori dei pixel rientrano nell'intervallo [0, 255]. Ma in generale, dovresti sempre elaborare i dati in base alle dei parametri di normalizzazione e quantizzazione, se applicabili.

Esempi

Puoi trovare esempi su come compilare i metadati per diversi tipi di modelli qui:

Classificazione delle immagini

Scarica lo script qui , che compila i metadati in mobilenet_v1_0.75_160_quantized.tflite. Esegui lo script come segue:

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

Per compilare i metadati per altri modelli di classificazione delle immagini, aggiungi le specifiche del modello Mi piace questo nello script. Il resto di questa guida evidenzierà alcune delle sezioni principali nell'esempio di classificazione delle immagini per illustrare gli elementi chiave.

Approfondimento sull'esempio di classificazione delle immagini

Informazioni sul modello

Per prima cosa, i metadati creano una nuova informazione sul modello:

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

Informazioni di input / output

Questa sezione mostra come descrivere la firma di input e di output del modello. Questi metadati possono essere utilizzati da generatori automatici di codice per creare di elaborazione del codice. Per creare informazioni di input o output su un tensore:

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

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

Input immagine

Immagine è un tipo di input comune per il machine learning. Metadati LiteRT supporta informazioni come lo spazio colore e le informazioni di pre-elaborazione come della normalizzazione. La dimensione dell'immagine non richiede una specifica manuale poiché è già fornito dalla forma del tensore di input e può essere dedotti automaticamente.

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

Output etichetta

L'etichetta può essere mappata a un tensore di output tramite un file associato utilizzando 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 i Flatbuffers per i metadati

Il codice seguente combina le informazioni del modello con i dati di input e di output informazioni:

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

Pacchettizzare i metadati e i file associati nel modello

Una volta creati i Flatbuffers dei metadati, i file dei metadati e delle etichette vengono scritto nel file TFLite con il metodo 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()

Puoi comprimere nel modello tutti i file associati che desideri utilizzando load_associated_files. Tuttavia, è necessario comprimere almeno questi file documentati nei metadati. In questo esempio, la pacchettizzazione del file dell'etichetta obbligatorio.

Visualizza i metadati

Puoi utilizzare Netron per visualizzare metadati o puoi leggere i metadati da un modello LiteRT in un file json utilizzando 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 supporta anche la visualizzazione dei metadati tramite Android Studio ML Associazione funzionalità.

Controllo delle versioni dei metadati

I metadati schema il controllo delle versioni viene eseguito tramite il numero di controllo delle versioni semantico, che tiene traccia delle modifiche il file di schema e dall'identificazione del file Flatbuffers, che indica e la compatibilità effettiva delle versioni.

Il numero di controllo delle versioni semantico

Viene eseguito il controllo delle versioni dello schema dei metadati tramite il controllo delle versioni semantico numero, ad esempio MAJOR.MINOR.PATCH. Monitora le modifiche allo schema in base alle regole qui Consulta la storia di campi aggiunto dopo la versione 1.0.0.

Identificazione del file Flatbuffers

Il controllo delle versioni semantico garantisce la compatibilità se si seguono le regole, ma non implica la vera incompatibilità. Quando si aumenta il numero MAJOR, non significa necessariamente che la compatibilità con le versioni precedenti sia interrotta. Pertanto, usa il file Flatbuffers di identificazione, file_identifier, per indicare la vera compatibilità dello schema dei metadati. L'identificatore del file è esattamente 4 caratteri. È fissato a un determinato schema di metadati e non soggetti a modifiche da parte degli utenti. Se la compatibilità con le versioni precedenti dello schema dei metadati deve essere interrotto per qualche motivo, il valore file_identifier si sovrapponga, ad esempio, da “M001” a “M002”. File_identifier dovrebbe essere modificato molto meno spesso di metadata_version.

Versione minima necessaria dell'analizzatore sintattico dei metadati

L'analizzatore sintattico dei metadati minimo necessario versione è la versione minima del parser dei metadati (il codice generato da Flatbuffers) può leggere i Flatbuffers dei metadati per intero. La versione è effettivamente il numero di versione più grande tra le versioni di tutti i campi compilati e la versione compatibile più piccola indicata dall'identificatore del file. Il minimo la versione necessaria dell'analizzatore sintattico dei metadati viene compilata automaticamente MetadataPopulator quando i metadati vengono inseriti in un modello TFLite. Consulta le metadata estrattore per ulteriori informazioni su come viene utilizzata la versione minima necessaria dell'analizzatore sintattico di metadati.

Leggi i metadati dai modelli

La libreria Metadata Extractor è un pratico strumento per leggere i metadati file associati da un modello su piattaforme diverse (vedi il documento Java versione e il tasto C++ dell'audiodescrizione). Puoi creare il tuo strumento di estrazione di metadati in altre lingue utilizzando Libreria Flatbuffers.

Leggi i metadati in Java

Per utilizzare la libreria Metadata Extractor nella tua app per Android, ti consigliamo di usare LiteRT Metadata AAR ospitato sul MavenCentral. Contiene la classe MetadataExtractor, nonché il file Java FlatBuffers associazioni per i metadati schema e il modello del modello.

Puoi specificare questa opzione nelle dipendenze build.gradle come segue:

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

Per utilizzare le istantanee notturne, assicurati di aver aggiunto Sonatype snapshot un repository attendibile.

Puoi inizializzare un oggetto MetadataExtractor con un elemento ByteBuffer che punti al modello:

public MetadataExtractor(ByteBuffer buffer);

ByteBuffer deve rimanere invariato per l'intera durata di Oggetto MetadataExtractor. L'inizializzazione potrebbe non riuscire se il file Flatbuffers l'identificatore dei metadati del modello non corrisponde a quello dell'analizzatore sintattico dei metadati. Consulta: controllo delle versioni dei metadati per ulteriori informazioni.

Con gli identificatori di file corrispondenti, l'estrattore di metadati leggerà correttamente Metadati generati da tutti gli schemi passati e futuri a causa dei Flatbuffer meccanismo di compatibilità avanti e indietro. Tuttavia, i campi futuri gli schemi non possono essere estratti da estrattori di metadati meno recenti. Il minimo necessario dell'analizzatore sintattico dei metadati indica la versione minima del parser dei metadati in grado di leggere i metadati Flatbuffer pieno. Puoi utilizzare il seguente metodo per verificare se il minimo la condizione necessaria per la versione dell'analizzatore sintattico è soddisfatta:

public final boolean isMinimumParserVersionSatisfied();

È consentito il passaggio in un modello senza metadati. Tuttavia, i metodi di richiamo che letti dai metadati provocheranno errori di runtime. Puoi verificare se un modello ha richiamando il metodo hasMetadata:

public boolean hasMetadata();

MetadataExtractor offre pratiche funzioni per aiutarti a ottenere "I tensori di input/output" metadati. Ad esempio,

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

Anche se il modello LiteRT schema supporta più sottografi, TFLite Interpreter supporta attualmente solo con un singolo grafico secondario. Di conseguenza, in MetadataExtractor omette l'indice del sottografo come input nei suoi metodi.

Leggere i file associati dai modelli

Il modello LiteRT con metadati e file associati è essenzialmente una file ZIP che può essere decompresso con i comuni strumenti ZIP per ottenere i file associati. Ad esempio, puoi decomprimere mobilenet_v1_0.75_160_quantized ed estrai il file di etichette nel modello come segue:

$ 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

Puoi anche leggere i file associati tramite la libreria Metadata Extractor.

In Java, passa il nome del file nell'elemento MetadataExtractor.getAssociatedFile :

public InputStream getAssociatedFile(String fileName);

Analogamente, in C++, questa operazione può essere eseguita utilizzando il metodo ModelMetadataExtractor::GetAssociatedFile:

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