7.15. Scriverne uno proprio¶
Quando il catalogo non copre un modello – una rete di ricerca la cui disposizione di output è su misura, una modifica a un’architettura esistente, un tensore la cui interpretazione semantica è specifica dell’applicazione – l’applicazione fornisce il proprio post-processore. Il protocollo è semplice: un callable che prende (model, inputs, outputs) e restituisce qualunque cosa l’applicazione si aspetti da predict().
Una classe con __call__ è la forma convenzionale:
class MyPostprocessor:
def __init__(self, threshold=0.5):
self.threshold = threshold
def __call__(self, model, inputs, outputs):
...
return result
Funziona anche una semplice funzione – il motore verifica solo che l’oggetto sia callable.
7.15.1. Collegarlo¶
Due punti di collegamento. Il kwarg postprocess= nel costruttore associa il callable a ogni chiamata di predict() sul modello:
model = ml.Model("/rom/my_model.tflite",
postprocess=MyPostprocessor())
Per sovrascrivere l’associazione per una singola chiamata – scambiare i decodificatori senza ricaricare il modello – passa callback= direttamente a predict:
result = model.predict([img], callback=MyOtherPostprocessor())
La firma del callable è la stessa in entrambi i casi.
7.15.2. Cosa riceve il callable¶
model– l’istanzaModel, utile per i parametri di quantizzazione (output_scale,output_zero_point,output_dtype) e per le dimensioni di input (input_shape).inputs– la lista di input che l’applicazione ha passato apredict(). Il primo elemento è solitamente l’istanzaNormalizationassociata; il suo attributoroiè ciò cheNMSsi aspetta per rimappare i box nell’immagine originale.outputs– i tensori di output grezzi come una lista di oggettindarray, nel loro dtype nativo. Gli output float arrivano così come sono; gli output interi arrivano quantizzati.
7.15.3. Aritmetica quantizzata¶
I decodificatori forniti ricorrono tutti agli stessi helper in ml.utils, e uno personalizzato di solito vuole lo stesso schema: quantize() solleva una soglia float nello spazio quantizzato del modello, threshold() filtra senza dequantizzare l’intero tensore, e dequantize() viene eseguito una volta sui sopravvissuti. sigmoid() e logit() sono disponibili per reti i cui canali di output sono logit pre-sigmoide (i rilevatori MediaPipe sono il caso canonico).
Per i modelli con output float – teste di regressione, modelli con un livello finale di dequantizzazione integrato – gli helper di quantizzazione passano invariati, quindi lo stesso codice del post-processore funziona con entrambi i dtype senza casi speciali.
7.15.4. Valore di ritorno¶
Qualunque cosa il callable restituisca è ciò che predict() restituisce. Per i decodificatori che emettono box la convenzione è inviare i candidati attraverso un NMS e restituire le sue liste per classe – la forma di chiamata documentata in non-max suppression e costruita in contesto nella spiegazione dettagliata di YOLOv8. Per qualsiasi altra cosa, restituisci ciò che l’applicazione trova comodo: un singolo ndarray, una stringa di etichetta, una tupla (class, score, embedding), un dizionario.