7.4. Caricamento di un modello#

ml.Model legge un file di modello dalla flash, lo analizza, alloca la RAM di cui la rete ha bisogno durante l’inferenza e restituisce un oggetto che contiene tutto ciò che il resto dello script deve sapere sulla rete caricata.

7.4.1. Il costruttore#

Il costruttore accetta un percorso e un post-processor opzionale:

model = ml.Model("/rom/blazeface_front_128.tflite",
                 postprocess=BlazeFace())

I modelli su /rom/ (il filesystem residente in flash) vengono letti in loco: i pesi della rete restano in flash e il modello caricato occupa solo la RAM corrispondente all’arena dei tensori. I modelli su /sdcard/ vengono copiati in RAM al momento del caricamento, quindi il costo totale è la dimensione del file del modello più l’arena dei tensori. Entrambi i percorsi funzionano; il compromesso è la RAM.

Se esiste un file .txt di pari livello con lo stesso nome base, il suo contenuto viene caricato automaticamente in labels. La parola chiave postprocess= registra un oggetto invocabile che predict() esegue dopo ogni inferenza.

7.4.2. Proprietà di sola lettura#

Un modello caricato espone un piccolo insieme di proprietà di sola lettura che descrivono la rete senza che nessuno la esegua.

File e memoria.

  • len – dimensione del file del modello su disco, in byte.

  • ram – dimensione dell”arena dei tensori di cui la rete ha bisogno per le sue attivazioni intermedie durante l’inferenza, in byte.

Tensori di input.

  • input_shape – un elenco di tuple, una per ogni tensore di input, che indica la forma attesa dalla rete. Le reti di visione hanno un solo input con forma (1, H, W, C).

  • input_dtype – elenco di codici dtype a carattere singolo ('b' int8, 'B' uint8, 'h' int16, 'H' uint16, 'f' float32), uno per ogni input.

  • input_scale e input_zero_point – i parametri di quantizzazione che convertono tra l’input a valori reali su cui la rete è stata addestrata e la rappresentazione intera con cui la camera la esegue.

Tensori di output. Speculari rispetto all’insieme di input: output_shape, output_dtype, output_scale, output_zero_point. Le reti di rilevamento producono due o tre tensori di output (box, punteggi di confidenza, talvolta probabilità di classe); le reti di classificazione ne producono uno.

Extra. labels è l’elenco dei nomi delle classi caricato dal file .txt di pari livello, oppure None. postprocess è il post-processor registrato, oppure None.

7.4.3. Ispezione di BlazeFace#

Il caricamento del modello BlazeFace fornito e la stampa di ogni proprietà restituiscono i numeri effettivi:

import ml
from ml.postprocessing.mediapipe import BlazeFace

model = ml.Model("/rom/blazeface_front_128.tflite",
                 postprocess=BlazeFace())

print("file size:    ", model.len, "bytes")
print("tensor arena: ", model.ram, "bytes")
print("input shape:  ", model.input_shape)
print("input dtype:  ", model.input_dtype)
print("input scale:  ", model.input_scale)
print("input zp:     ", model.input_zero_point)
print("output shape: ", model.output_shape)
print("output dtype: ", model.output_dtype)
print("output scale: ", model.output_scale)
print("output zp:    ", model.output_zero_point)

I numeri identificano concretamente l’interfaccia della rete: un singolo tensore di input int8 (1, 128, 128, 3) e due output int8 – uno per i coefficienti di regressione dei box, uno per i punteggi di confidenza per anchor. I parametri di quantizzazione descrivono come quei valori int8 si mappano sui float reali contro cui la rete è stata addestrata; il post-processor li usa per annullare la quantizzazione prima di decodificare i box.

Ogni proprietà è l’unica fonte di verità per ciò che descrive. Gli script leggono input_shape per sapere a quale risoluzione catturare, leggono output_scale e output_zero_point per decodificare i tensori manualmente, e leggono labels per i nomi delle classi leggibili dall’uomo – mai cablati nel codice, mai dati per scontati.