Supercharge l’addestramento dei tuoi modelli di Deep Learning

Migliora l'addestramento dei tuoi modelli di Deep Learning al massimo

Super convergenza con tassi di apprendimento a ciclo singolo

Foto di Philip Swinburn su Unsplash

Ti è capitato di imbatterti in situazioni in cui è facile ottenere un’iniziale esplosione di accuratezza, ma una volta raggiunto il 90%, devi fare davvero molta fatica per ottenere ulteriori miglioramenti delle prestazioni? Il tuo modello impiega troppo tempo per allenarsi?

In questo articolo, esamineremo una tecnica interessante per potenziare la tua configurazione di allenamento e ottenere quel piccolo extra di prestazioni che cercavi e allenarti più velocemente. Fondamentalmente, lavoreremo per cambiare dinamicamente il tasso di apprendimento nel corso delle epoche utilizzando una politica chiamata One-Cycle Learning Rate.

Originariamente menzionato in un articolo di Leslie Smith, il one-cycle learning rate schedule[1], [2] si concentra su una strategia unica per aggiornare dinamicamente il tasso di apprendimento durante il processo di allenamento. Sembra un po’ complicato, ma non preoccuparti, iniziamo con una tipica configurazione di allenamento e gradualmente capiremo come migliorare i risultati utilizzando il one-cycle learning rate.

Allenare un classificatore di immagini

Mentre lavoriamo per imparare un bel trucco (il ciclo di tasso) per migliorare le prestazioni del modello, perché non farlo mentre ci godiamo il classico gioco del rock-paper-scissors.

Foto di Markus Spiske su Unsplash

Problema

Il gioco del rock-paper-scissors è un classico gioco per bambini che coinvolge due giocatori che utilizzano gesti delle mani (per sasso, carta o forbici) per competere e sopraffare il proprio avversario. Ad esempio, il gesto del sasso vince sulle forbici, ma il gesto della carta vince sul sasso. Interessante, vero?

Il nostro obiettivo qui è allenare un modello di classificazione delle immagini in grado di rilevare uno dei tre gesti. Possiamo poi sfruttare un modello addestrato del genere per sviluppare un gioco completo end-to-end. Per scopi di questo articolo, limiteremo l’ambito all’allenamento del solo classificatore. Probabilmente un articolo separato tratterà del gioco completo con un modello pronto per la distribuzione.

Il dataset

Siamo fortunati perché abbiamo già un dataset etichettato che possiamo utilizzare per addestrare un modello di classificazione con grande effetto. Il dataset è ospitato nel catalogo di TensorFlow dataset reso disponibile da Laurence Moroney (CC BY 2.0). Ha le seguenti caratteristiche:

  • Numero di punti dati: 2800
  • Numero di classi: 3
  • Divisione disponibile tra train e test: Sì
  • Dimensione del dataset: 220 MiB

TensorFlow fornisce un’API semplice e pulita per accedere a tali dataset, il seguente snippet ci consente di scaricare le divisioni di addestramento e di convalida

import tensorflow_datasets as tfdsDATASET_NAME = 'rock_paper_scissors'(dataset_train_raw, dataset_test_raw), dataset_info = tfds.load(    name=DATASET_NAME,    data_dir='tmp',    with_info=True,    as_supervised=True,    split=[tfds.Split.TRAIN, tfds.Split.TEST],)# mostra campioni dal datasetfig = tfds.show_examples(dataset_train_raw, dataset_info)

Di seguito ci sono alcune immagini campione direttamente da questo dataset:

Figura: Esempi di punti dati nel dataset Rock Paper Scissors

Tasso di Apprendimento

Il tasso di apprendimento è uno dei principali iperparametri che possono determinare il successo o il fallimento di un’implementazione, tuttavia è spesso trascurato. Viene trascurato principalmente perché la maggior parte delle librerie/pacchetti fornisce valori predefiniti sufficientemente buoni. Ma questi valori predefiniti possono portarti solo fino a un certo punto.

Trovare il tasso di apprendimento corretto per un caso d’uso personalizzato come il nostro è molto importante. È un compromesso delicato trovare il valore ottimale. Se il tasso di apprendimento è troppo lento (o piccolo), il modello imparerà pochissimo. Se è troppo veloce (o grande), supererà il tanto misterioso “minimo” che tutte le reti neurali cercano di trovare. Questo concetto è illustrato nella seguente immagine per una migliore comprensione.

Figura: Impatto del Tasso di Apprendimento sulla capacità del Modello di apprendere l'obiettivo (minimo). Fonte: Autore

Gradiente Discendente e Ottimizzatori

Il gradiente discendente è il metodo standard per addestrare/ottimizzare le reti neurali. Funziona minimizzando la funzione obiettivo aggiornando i parametri della rete nella direzione opposta al gradiente. Senza entrare nei dettagli, aiuta a scendere lungo la pendenza della funzione obiettivo. È disponibile una panoramica dettagliata del gradiente discendente qui per riferimento.

La comunità del deep learning ha fatto molti progressi da quando gli initiali modelli venivano addestrati con il semplice gradiente discendente. Nel corso degli anni, numerose migliorie hanno contribuito ad addestrare in modo più rapido ed evitare errori comuni. Ecco alcune delle più note e popolari:

AdaGradl’algoritmo gradiente adattivo è un algoritmo di ottimizzazione che adatta i tassi di apprendimento dei singoli parametri in base ai loro gradienti storici, consentendo aggiornamenti maggiori per i parametri meno frequenti e minori per quelli più frequenti. È progettato per gestire efficientemente i dati sparsi ed è particolarmente adatto a tale scopo.

RMSPropla propagazione radice della media quadratica ottimizza l’apprendimento regolando i tassi di apprendimento per ciascun parametro in modo individuale. Risolve il problema dei tassi di apprendimento in diminuzione di AdaGrad utilizzando una media mobile dei gradienti al quadrato. Ciò consente di adattare dinamicamente i tassi di apprendimento in base alle grandezze dei gradienti recenti.

ADAMStima adattiva dei momenti è un algoritmo di ottimizzazione che combina idee sia da RMSProp che dai metodi del momento. Mantiene medie decadenti in modo esponenziale dei gradienti passati e dei gradienti al quadrato, utilizzandoli per adattare dinamicamente i parametri. ADAM è noto per la sua efficienza ed efficacia nell’addestramento di reti neurali profonde.

Tasso di Apprendimento One-Cycle e Super Convergenza

Il tasso di apprendimento One-Cycle è un semplice processo in due fasi per migliorare il tasso di apprendimento e l’inerzia man mano che avanza l’addestramento. Funziona nel seguente modo:

  • Fase 1: Iniziamo aumentando gradualmente il tasso di apprendimento da un valore basso a uno più alto in modo incrementale per alcune epoche
  • Fase 2: Manteniamo il valore più alto del tasso di apprendimento per alcune epoche
  • Fase 3: Torniamo a un tasso di apprendimento più basso che diminuisce nel tempo

Durante queste tre fasi, l’inerzia viene aggiornata nella direzione esattamente opposta, ovvero quando il tasso di apprendimento aumenta, l’inerzia diminuisce e viceversa.

Tasso di Apprendimento One-Cycle in Azione

Iniziamo con un’implementazione semplice per il tasso di apprendimento one-cycle e poi lo utilizzeremo per addestrare il nostro modello. Sfrutteremo un’implementazione già pronta per l’uso del programma del tasso di apprendimento one-cycle di Martin Gorner nella sua presentazione del 2019 a TensorFlow World come illustrato nel listato 2.

def lr_function(epoch):    # impostiamo il valore iniziale, minimo e massimo per il tasso di apprendimento    start_lr = 1e-3; min_lr = 1e-3; max_lr = 2e-3    # definiamo il numero di epoche per incrementare     # linearmente il tasso di apprendimento, poi il fattore di decadimento    rampup_epochs = 6; sustain_epochs = 0; exp_decay = .5    # metodo per aggiornare il valore del tasso di apprendimento in base all'epoca corrente    def lr(epoch, start_lr, min_lr, max_lr, rampup_epochs,           sustain_epochs, exp_decay):        if epoch < rampup_epochs:            lr = ((max_lr - start_lr) / rampup_epochs                        * epoch + start_lr)        elif epoch < rampup_epochs + sustain_epochs:            lr = max_lr        else:            lr = ((max_lr - min_lr) *                      exp_decay**(epoch - rampup_epochs -                                    sustain_epochs) + min_lr)        return lr    return lr(epoch, start_lr, min_lr, max_lr,              rampup_epochs, sustain_epochs, exp_decay)

Eseguiamo questa funzione (vedi elenco 2) per un numero fisso di epoche per mostrare come il tasso di apprendimento cambia secondo i due passaggi discussi in precedenza. Qui partiamo con un tasso di apprendimento iniziale di 1e-3 e lo aumentiamo a 2e-3 nelle prime poche epoche. Viene poi ridotto nuovamente a 1e-3 nel corso delle epoche rimanenti. Questa curva dinamica del tasso di apprendimento è rappresentata con un esempio di 24 epoche nella figura seguente.

Politica del tasso di apprendimento a ciclo singolo per 24 epoche. Il tasso di apprendimento aumenta linearmente, seguito da un lento decadimento nelle epoche rimanenti. Fonte dell'immagine: Autore

Metteremo ora alla prova il nostro scheduler del tasso di apprendimento a ciclo singolo applicandolo durante l’utilizzo di un modello MobileNetV2 come estrattore di caratteristiche nell’addestramento di una testa di classificazione per il nostro caso attuale di sasso-carta-forbici. Confronteremo quindi questo approccio con una semplice rete CNN e con MobileNetV2+testa di classificazione con l’ottimizzatore Adam standard. Il notebook completo è disponibile per riferimento su github. Per avere una panoramica veloce, il seguente snippet illustra come utilizziamo i callback di TensorFlow per integrare la nostra utilità del tasso di ciclo singolo.

# Imposta la forma dell'immagine
INPUT_IMG_SHAPE = (128, 128, 3)
# Ottieni il MobileNetV2 preaddestrato come base
base_model = tf.keras.applications.MobileNetV2(
  input_shape=INPUT_IMG_SHAPE,
  include_top=False,
  weights='imagenet',
  pooling='avg')
# Attacca una testa di classificazione
model_lr = tf.keras.models.Sequential()
model_lr.add(base_model)
model_lr.add(tf.keras.layers.Dropout(0.5))
model_lr.add(tf.keras.layers.Dense(
    units=NUM_CLASSES,
    activation=tf.keras.activations.softmax,
    kernel_regularizer=tf.keras.regularizers.l2(l=0.01)))
# Compila il modello
model_lr.compile(
    optimizer=tf.keras.optimizers.Adam(),
    loss=tf.keras.losses.sparse_categorical_crossentropy,
    metrics=['accuracy'])
# Imposta il numero di epoche
initial_epochs = 24
# Imposta il modello per l'addestramento
# Il callback LearningRateScheduler è dove
# inseriamo la nostra funzione personalizzata del tasso di ciclo singolo
training_history_lr = model_lr.fit(
    x=dataset_train_augmented_shuffled.repeat(),
    validation_data=dataset_test_shuffled.repeat(),
    epochs=initial_epochs,
    steps_per_epoch=steps_per_epoch,
    validation_steps=validation_steps,
    callbacks=[
        tf.keras.callbacks.LearningRateScheduler(lambda epoch: \                                             lr_function(epoch),
                                             verbose=True)
    ],
    verbose=1)

Addestriamo tutti e 3 i modelli per 24 epoche con una dimensione del batch di 64. La figura seguente illustra l’impatto del tasso di apprendimento a ciclo singolo. È in grado di aiutare il nostro modello a raggiungere la convergenza in soli 5 epoche rispetto agli altri due modelli. Il fenomeno della super-convergenza è visibile anche per il dataset di convalida.

MobileNetV2 con tasso di apprendimento a ciclo singolo (mobileNetV2_lr) supera le architetture MobileNetV2 e semplice CNN raggiungendo la convergenza in soli 5 epoche

Raggiungiamo valori costanti di accuratezza di convalida compresi tra il 90% e il 92% entro 10 epoche, che finora è il migliore tra tutti i nostri modelli. Alla valutazione, le prestazioni del modello sul dataset di test riflettono la stessa situazione, ossia MobileNetV2_lr supera gli altri due con facilità.

# Semplice CNNErrore di prova: 0,7511898279190063Accuratezza di prova: 0,7768816947937012# MobileNetV2Errore di prova: 0,24527719616889954Accuratezza di prova: 0,9220430254936218# MobileNetV2_LRErrore di prova: 0,27864792943000793Accuratezza di prova: 0,9166666865348816

Conclusion

Superare la fase di plateau delle prestazioni dei modelli oltre il 90% di accuratezza e ottimizzare il tempo di allenamento può essere raggiunto mediante l’implementazione della One-Cycle Learning Rate. Questa tecnica, introdotta da Leslie Smith e dal suo team, regola dinamicamente il tasso di apprendimento durante l’allenamento, offrendo un approccio strategico per potenziare le prestazioni del modello. Adottando questo metodo, puoi navigare in modo efficiente le complessità delle configurazioni di allenamento e sbloccare il potenziale per modelli di deep learning più rapidi ed efficaci. Abbraccia il potere della One-Cycle Learning Rate per elevare la tua esperienza di allenamento e ottenere risultati superiori!