La quantizzazione post-addestramento è una tecnica di conversione che può ridurre le dimensioni del modello migliorando al contempo la latenza della CPU e dell'acceleratore hardware, con un peggioramento dell'accuratezza del modello. Puoi quantificare un numero in virgola mobile già addestrato il modello TensorFlow quando lo converti in formato LiteRT utilizzando Convertitore LiteRT.
Metodi di ottimizzazione
Sono disponibili diverse opzioni di quantizzazione post-addestramento tra cui scegliere. Ecco un una tabella di riepilogo delle opzioni e i vantaggi che offrono:
Tecnica | Vantaggi | Hardware |
---|---|---|
Intervallo dinamico quantizzazione | 4 volte più piccola, velocità 2x-3x | CPU |
Numero intero intero quantizzazione | 4 volte più piccola, 3 volte più veloce | CPU, Edge TPU Microcontrollori |
quantizzazione in Float16 | 2 volte più piccola, GPU accelerazione | CPU, GPU |
Il seguente albero decisionale può aiutare a determinare quale quantizzazione post-addestramento più adatto al tuo caso d'uso:
Nessuna quantizzazione
La conversione a un modello TFLite senza la quantizzazione è consigliata per iniziare punto di accesso. Verrà generato un modello TFLite in virgola mobile.
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) tflite_quant_model = converter.convert()
Ti consigliamo di eseguire questa operazione come primo passaggio per verificare che l'originale Gli operatori del modello TF sono compatibili con TFLite e possono essere utilizzati anche come per eseguire il debug degli errori di quantizzazione introdotti dal successivo addestramento metodi di quantizzazione. Ad esempio, se un modello TFLite quantizzato genera risultati imprevisti, mentre il modello TFLite in virgola mobile è accurato, possiamo il problema degli errori introdotti dalla versione quantizzata degli operatori TFLite.
quantizzazione dell'intervallo dinamico
La quantizzazione dell'intervallo dinamico consente di ridurre l'utilizzo della memoria e velocizzare il calcolo senza dover fornire un set di dati rappresentativo per la calibrazione. Questo tipo di quantizzazione, quantifica in modo statico solo i pesi in virgola mobile a un valore intero al momento della conversione, che fornisce 8 bit di precisione:
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.optimizations = [tf.lite.Optimize.DEFAULT] tflite_quant_model = converter.convert()
Per ridurre ulteriormente la latenza durante l'inferenza, operatori quantificare dinamicamente le attivazioni in base all'intervallo fino a 8 bit ed eseguire con pesi a 8 bit e attivazioni. Questa ottimizzazione fornisce le latenze vicine alle inferenze a punto completamente fisso. Tuttavia, gli output sono comunque memorizzati utilizzando la rappresentazione in virgola mobile, in modo che la maggiore velocità delle operazioni con intervallo dinamico sia minore rispetto a un calcolo completo a punto fisso.
quantizzazione di interi interi
Puoi ottenere ulteriori miglioramenti della latenza, riduzioni dei picchi di utilizzo della memoria e compatibilità con acceleratori o dispositivi hardware solo con numeri interi, assicurandosi tutta la matematica del modello è quantificata in numero intero.
Per la quantizzazione completa dei numeri interi, devi calibrare o stimare l'intervallo,
ovvero (min, max) di tutti i tensori a virgola mobile nel modello. A differenza della costante
tensori come ponderazioni e bias, tensori variabili come input del modello,
(output degli strati intermedi) e l'output del modello non
calibrata, a meno che non eseguiamo alcuni cicli di inferenza. Di conseguenza, l'utente che ha completato
richiede un set di dati rappresentativo
per calibrarli. Questo set di dati può essere un insieme
sottoinsieme (circa 100-500 campioni) dei dati di addestramento o convalida. Consulta
la funzione representative_dataset()
riportata di seguito.
A partire dalla versione TensorFlow 2.7, è possibile specificare il set di dati rappresentativo tramite Una firma, come nell'esempio seguente:
def representative_dataset(): for data in dataset: yield { "image": data.image, "bias": data.bias, }
Se il modello TensorFlow specificato include più firme, puoi specificare più set di dati specificando le chiavi di firma:
def representative_dataset(): # Feed data set for the "encode" signature. for data in encode_signature_dataset: yield ( "encode", { "image": data.image, "bias": data.bias, } ) # Feed data set for the "decode" signature. for data in decode_signature_dataset: yield ( "decode", { "image": data.image, "hint": data.hint, }, )
Puoi generare il set di dati rappresentativo fornendo un elenco di tensori di input:
def representative_dataset(): for data in tf.data.Dataset.from_tensor_slices((images)).batch(1).take(100): yield [tf.dtypes.cast(data, tf.float32)]
A partire dalla versione TensorFlow 2.7, consigliamo di utilizzare l'approccio basato sulle firme sull'approccio basato su elenco di tensori di input perché l'ordinamento dei tensori di input può possono essere facilmente capovolti.
A scopo di test, puoi utilizzare un set di dati fittizio come segue:
def representative_dataset(): for _ in range(100): data = np.random.rand(1, 244, 244, 3) yield [data.astype(np.float32)]
Numero intero con numero in virgola mobile di riserva (con input/output predefinito in virgola mobile)
Al fine di quantificare completamente un modello, utilizza gli operatori in virgola mobile quando non hai un'implementazione di tipo intero (per garantire che la conversione avvenga senza problemi), utilizza segui questi passaggi:
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.representative_dataset = representative_dataset tflite_quant_model = converter.convert()
Solo numero intero
La creazione di modelli solo interi è un caso d'uso comune di LiteRT per Microcontrollori e Corallo Edge TPU.
Inoltre, per garantire la compatibilità con dispositivi che includono solo numeri interi (ad esempio, i dispositivi a 8 bit) microcontroller) e acceleratori (come la TPU Coral Edge), puoi la quantizzazione dei numeri interi completi per tutte le operazioni, compresi l'input e l'output, utilizzando segui questi passaggi:
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.representative_dataset = representative_dataset converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] converter.inference_input_type = tf.int8 # or tf.uint8 converter.inference_output_type = tf.int8 # or tf.uint8 tflite_quant_model = converter.convert()
quantizzazione in Float16
Puoi ridurre le dimensioni di un modello in virgola mobile quantificando le ponderazioni in float16, lo standard IEEE per i numeri in virgola mobile a 16 bit. Per attivare float16 quantizzazione delle ponderazioni, segui questi passaggi:
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.target_spec.supported_types = [tf.float16] tflite_quant_model = converter.convert()
I vantaggi della quantizzazione di float16 sono i seguenti:
- Riduce le dimensioni del modello fino alla metà (poiché tutti i pesi diventano la metà del loro dimensioni originali).
- Causa una perdita minima di precisione.
- Supporta alcuni delegati (ad esempio il delegato GPU) che possono operare direttamente sui dati float16, con un'esecuzione più rapida rispetto a float32 molto altro.
Gli svantaggi della quantizzazione di float16 sono i seguenti:
- Non riduce la latenza tanto quanto una quantizzazione in un calcolo matematico a punto fisso.
- Per impostazione predefinita, un modello quantizzato float16 "dequantizza" i valori delle ponderazioni in float32 quando viene eseguito sulla CPU. Tieni presente che il delegato GPU non eseguirà questa dequantizzazione, poiché può operare su dati float16.)
Solo numero intero: attivazioni a 16 bit con pesi a 8 bit (sperimentale)
Questo è uno schema di quantizzazione sperimentale. È simile a "solo numero intero" ma le attivazioni sono quantificate in base al loro intervallo a 16 bit, i pesi sono quantizzati in numeri interi a 8 bit e i bias vengono quantificati in numeri interi a 64 bit. Questo è detta "quantizzazione 16x8".
Il vantaggio principale di questa quantizzazione è che può migliorare l'accuratezza ma aumenta di poco le dimensioni del modello.
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.representative_dataset = representative_dataset converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8] tflite_quant_model = converter.convert()
Se la quantizzazione 16x8 non è supportata per alcuni operatori nel modello, il modello può comunque essere quantizzato, ma gli operatori non supportati vengono mantenuti in numero in virgola mobile. La Per consentire questa operazione, è necessario aggiungere la seguente opzione a target_spec.
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.representative_dataset = representative_dataset converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8, tf.lite.OpsSet.TFLITE_BUILTINS] tflite_quant_model = converter.convert()
Esempi di casi d'uso in cui i miglioramenti dell'accuratezza forniti da questo schema di quantizzazione include:
- super risoluzione,
- elaborazione dei segnali audio come la cancellazione del rumore e il beamforming,
- riduzione del rumore nell'immagine,
- Ricostruzione HDR da una singola immagine.
Lo svantaggio di questa quantizzazione è:
- Attualmente l'inferenza è notevolmente più lenta del numero intero intero a 8 bit a causa della dell'implementazione del kernel ottimizzata.
- Attualmente non è compatibile con la soluzione TFLite con accelerazione hardware esistente delegati.
È disponibile un tutorial per questa modalità di quantizzazione qui
Precisione del modello
Poiché i pesi sono quantificati dopo l'addestramento, potrebbe verificarsi una perdita di accuratezza, in particolare per le reti più piccole. I modelli completamente quantizzati preaddestrati sono fornite per emittenti specifiche su Kaggle Modelli di Google. È importante controllare l'accuratezza del modello quantizzato per verificare che qualsiasi peggioramento dell'accuratezza rientri nei limiti accettabili. Esistono strumenti per valutare il modello LiteRT la precisione.
In alternativa, se il calo della precisione è troppo elevato, valuta la possibilità di utilizzare la quantizzazione consapevolezza formazione di Google. Tuttavia, questo processo richiede modifiche durante l'addestramento del modello per aggiungere nodi di quantizzazione, mentre le tecniche di quantizzazione post-addestramento utilizza un modello preaddestrato esistente.
Rappresentazione dei tensori quantizzati
La quantizzazione a 8 bit approssima i valori in virgola mobile utilizzando: formula.
\[real\_value = (int8\_value - zero\_point) \times scale\]
La rappresentazione ha due parti principali:
Pesi per asse (noto anche come per canale) o per tensore rappresentati da int8 due valori di complemento nell'intervallo [-127, 127] con punto zero uguale a 0.
Attivazioni/input per tensore rappresentati da valori di complemento di int8 a due l'intervallo [-128, 127], con un punto zero nell'intervallo [-128, 127].
Per una visione dettagliata del nostro schema di quantizzazione, consulta la quantizzazione del modello. Fornitori di hardware che vogliono collegarsi a TensorFlow Consigliamo all'interfaccia di delega di Lite di implementare lo schema di quantizzazione descritti qui.