Hti sei imbattuto in scenari in cui è facile ottenere un aumento iniziale di precisione ma una volta raggiunto il 90%, devi spingere davvero tanto per ottenere qualsiasi miglioramento delle prestazioni? Il tuo modello impiega troppo tempo per l’addestramento?
In questo articolo esamineremo una tecnica interessante per potenziare la tua configurazione di allenamento e ottenere quel tocco di prestazione in più che stavi cercando e allenarti più velocemente. In sostanza, lavoreremo per modificare dinamicamente il tasso di apprendimento nel corso delle epoche utilizzando una politica chiamata Tasso di apprendimento a un ciclo.
Originariamente menzionato in un articolo di Leslie Smith, il Programma di tassi di apprendimento a ciclo unico(1), (2) si concentra su una strategia unica per aggiornare dinamicamente il tasso di apprendimento durante il processo di formazione. Sembra un boccone di termini, non preoccuparti, iniziamo prima con una tipica configurazione di allenamento e poi capiremo gradualmente come possiamo migliorare i risultati utilizzando il tasso di apprendimento a ciclo singolo.
Dato che stiamo lavorando per apprendere un trucco accurato (velocità di ciclo) per migliorare le prestazioni del modello, perché non farlo mentre ci godiamo il classico Sasso carta forbici gioco.
Dichiarazione problema
Il gioco sasso-carta-forbici è un classico gioco per bambini in cui due giocatori utilizzano i gesti delle mani (per sasso, carta o forbici) in competizione per sopraffare l’avversario. Ad esempio, il gesto del sasso vince sulle forbici ma il gesto della carta vince sul sasso. Interessante, vero?
Il nostro obiettivo qui è addestrare un modello di classificazione delle immagini in grado di rilevare uno dei tre gesti. Possiamo quindi sfruttare un modello così addestrato per sviluppare un gioco end-to-end. Ai fini di questo articolo, limiteremo l’ambito all’addestramento di un classificatore stesso, il gioco end-to-end completo di un modello distribuibile è probabilmente per un altro articolo.
Il set di dati
Siamo fortunati ad avere già un set di dati etichettato che possiamo sfruttare per addestrare un modello di classificazione con grande efficacia. Il set di dati è ospitato su Set di dati TensorFlow catalogo messo a disposizione da Laurence Moroney (CC BY 2.0). Ha i seguenti attributi:
- Numero di punti dati: 2800
- Numero di classi: 3
- Suddivisione test-train disponibile: sì
- Dimensione del set di dati: 220 MiB
TensorFlow fornisce un’API gradevole e pulita per accedere a tali set di dati, il seguente snippet ci consente di scaricare le suddivisioni del treno e della 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),
)
# plot samples from the dataset
fig = tfds.show_examples(dataset_train_raw, dataset_info)
Di seguito sono riportate alcune immagini di esempio da questo set di dati stesso:
Tasso di apprendimento
Il tasso di apprendimento è uno degli iperparametri chiave che possono creare o distruggere una configurazione, ma è generalmente trascurato. Il motivo per cui viene trascurato è perché la maggior parte delle librerie/pacchetti vengono forniti con valori predefiniti sufficientemente buoni per cominciare. Ma queste impostazioni predefinite possono portarti solo fino a un certo punto.
Ottenere il tasso di apprendimento corretto per un caso d’uso su misura come il nostro è molto importante. Trovare il valore ottimale è un compromesso complicato. Se vai troppo lentamente (o riducilo) con la velocità di apprendimento, il tuo modello difficilmente imparerà nulla. Andare troppo veloce (o troppo grande) e supererà i minimi sempre così misteriosi che tutte le reti neurali mirano a trovare. Lo stesso è raffigurato nell’illustrazione qui sotto per una migliore comprensione.
Discesa del gradiente e ottimizzatori
La discesa del gradiente è il modo standard per addestrare/ottimizzare le reti neurali. Funziona minimizzando la funzione obiettivo aggiornando i parametri della rete nella direzione opposta del gradiente. Senza entrare troppo nei dettagli, aiuta a viaggiare in discesa lungo la pendenza della funzione obiettivo. È disponibile un’introduzione dettagliata alla discesa del gradiente Qui per riferimento.
La comunità del deep learning ha fatto molta strada da quando i modelli iniziali venivano addestrati con la discesa del gradiente vanilla. Nel corso degli anni una serie di miglioramenti hanno contribuito ad allenarsi più velocemente ed evitare evidenti insidie. In breve, alcuni dei più importanti e popolari sono:
AdaGrad
Algoritmo del gradiente adattivo è un algoritmo di ottimizzazione che adatta le velocità di apprendimento dei singoli parametri in base ai loro gradienti storici, consentendo aggiornamenti più ampi per parametri poco frequenti e aggiornamenti più piccoli per quelli frequenti. È progettato per gestire i dati sparsi in modo efficiente. È particolarmente adatto quando si ha a che fare con dati sparsi.
RMSProp
Propagazione quadratica media ottimizza l’apprendimento regolando individualmente i tassi di apprendimento per ciascun parametro. Affronta il problema della diminuzione dei tassi di apprendimento ad AdaGrad utilizzando una media mobile di gradienti quadrati. Ciò aiuta a ridimensionare in modo adattivo i tassi di apprendimento in base alle recenti magnitudini del gradiente.
ADAMO
Stima del momento adattivo è un algoritmo di ottimizzazione che combina idee provenienti dai metodi RMSProp e momentum. Mantiene le medie che decadono esponenzialmente dei gradienti passati e dei gradienti quadrati, utilizzandoli per aggiornare in modo adattivo i parametri. ADAM è noto per la sua efficienza ed efficacia nell’addestramento delle reti neurali profonde.
Il tasso di apprendimento a ciclo unico è un semplice processo in due fasi per improvvisare sul tasso di apprendimento e sullo slancio man mano che la formazione procede. Funziona come segue:
- Passo 1: Iniziamo aumentando inizialmente il tasso di apprendimento da un valore inferiore a uno più alto in modo incrementale lineare per alcune epoche
- Passo 2: Manteniamo il valore più alto del tasso di apprendimento per alcune epoche
- Passaggio 3: Torniamo quindi a un tasso di apprendimento inferiore che decade nel tempo
Durante queste tre fasi, lo slancio viene aggiornato nella direzione esattamente opposta, ovvero quando il tasso di apprendimento aumenta, lo slancio diminuisce e viceversa.
Tasso di apprendimento a ciclo unico in azione
Per prima cosa analizziamo una semplice implementazione per il tasso di apprendimento a ciclo singolo e poi utilizziamola per addestrare il nostro modello. Sfrutteremo un’implementazione pronta all’uso per la pianificazione LR a ciclo unico da Discorso del 2019 di Martin Gorner a Il mondo di TensorFlow come illustrato nell’elenco 2.
def lr_function(epoch):
# set start, min and max value for learning rate
start_lr = 1e-3; min_lr = 1e-3; max_lr = 2e-3# define the number of epochs to increase
# LR lineary and then the decay factor
rampup_epochs = 6; sustain_epochs = 0; exp_decay = .5
# method to update the LR value based on the current epoch
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(Vedere elenco 2) per un numero fisso di epoche per mostrare come cambia il tasso di apprendimento secondo i due passaggi discussi in precedenza. Qui iniziamo con un tasso di apprendimento iniziale di 1e-3 e aumentalo fino a 2e-3 nelle prime epoche. Viene quindi nuovamente ridotto a 1e-3 nel corso delle restanti epoche. Questa curva della velocità di apprendimento dinamico è rappresentata con un’esecuzione campione di 24 epoche nella figura seguente.
Ora metteremo alla prova il nostro pianificatore della velocità di apprendimento a ciclo unico applicandolo quando utilizziamo un modello MobileNetV2 come estrattore di funzionalità mentre addestriamo un capo di classificazione per il nostro caso attuale di sasso-carta-forbici. Lo confronteremo quindi con un semplice test di classificazione della CNN e MobileNetV2+ con l’ottimizzatore Adam standard. Il taccuino completo è disponibile per consultazione su github. Per una rapida panoramica, il frammento seguente descrive come utilizziamo i callback TensorFlow per collegare la nostra utility a frequenza di 1 ciclo.
# Set Image Shape
INPUT_IMG_SHAPE= (128, 128, 3)# Get Pretrained MobileNetV2
base_model = tf.keras.applications.MobileNetV2(
input_shape=INPUT_IMG_SHAPE,
include_top=False,
weights='imagenet',
pooling='avg'
)
# Attach a classification head
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)
))
# compile the model
model_lr.compile(
optimizer=tf.keras.optimizers.Adam(),
loss=tf.keras.losses.sparse_categorical_crossentropy,
metrics=('accuracy')
)
# set number of epochs
initial_epochs = 24
# Set the model for training
# The LearningRateScheduler callback is where we
# plug our custom 1-cycle rate function
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 batch di 64. La figura seguente mostra l’impatto della velocità di apprendimento di 1 ciclo. È in grado di aiutare il nostro modello a raggiungere la convergenza in sole 5 epoche rispetto agli altri due modelli. Il fenomeno della superconvergenza è visibile anche per il set di dati di validazione.
Raggiungiamo valori costanti di precisione di convalida compresi tra il 90 e il 92% entro 10 epoche, che è finora il migliore che abbiamo visto in tutti i nostri modelli. In fase di valutazione, anche le prestazioni del modello sul set di dati di test descrivono la stessa storia, ovvero MobileNetV2_lr supera molto facilmente gli altri due.
# Simple CNN
Test loss: 0.7511898279190063
Test accuracy: 0.7768816947937012# MobileNetV2
Test loss: 0.24527719616889954
Test accuracy: 0.9220430254936218
# MobileNetV2_LR
Test loss: 0.27864792943000793
Test accuracy: 0.9166666865348816
Il superamento del plateau nelle prestazioni del modello oltre la precisione del 90% e l’ottimizzazione del tempo di formazione possono essere raggiunti attraverso l’implementazione del tasso di apprendimento a ciclo unico. Questa tecnica, introdotta da Leslie Smith e dal suo team, regola dinamicamente il tasso di apprendimento durante la formazione, offrendo un approccio strategico per potenziare le prestazioni del modello. Adottando questo metodo, puoi affrontare in modo efficiente le complessità delle configurazioni di formazione e sbloccare il potenziale per modelli di deep learning più rapidi ed efficaci. Sfrutta la potenza del tasso di apprendimento a ciclo unico per migliorare la tua esperienza di formazione e ottenere risultati superiori!
Fonte: towardsdatascience.com