Risolvere efficacemente i problemi di convergenza dell’addestramento distribuito con l’ottimizzazione automatica del modello Hyperband di Amazon SageMaker
Efficiently solving convergence problems in distributed training with Amazon SageMaker's automatic model optimization Hyperband
Negli ultimi anni si è registrata una crescita straordinaria delle reti neurali di deep learning (DNN). Questa crescita si manifesta in modelli più accurati e nell’apertura di nuove possibilità con l’IA generativa: grandi modelli di linguaggio (LLM) che sintetizzano il linguaggio naturale, generatori di testo-immagine e altro ancora. Queste capacità aumentate delle DNN comportano però il costo di avere modelli massicci che richiedono risorse computazionali significative per essere addestrati. L’addestramento distribuito affronta questo problema con due tecniche: parallelismo dei dati e parallelismo del modello. Il parallelismo dei dati viene utilizzato per scalare il processo di addestramento su più nodi e lavoratori, mentre il parallelismo del modello divide un modello e lo adatta all’infrastruttura designata. I lavori di addestramento distribuito di Amazon SageMaker ti consentono di impostare un cluster di calcolo distribuito, addestrare un modello, salvare il risultato su Amazon Simple Storage Service (Amazon S3) e spegnere il cluster quando è completo con un solo clic (o una sola chiamata API). Inoltre, SageMaker ha continuamente innovato nello spazio dell’addestramento distribuito, lanciando funzionalità come cluster eterogenei e librerie di addestramento distribuito per il parallelismo dei dati e il parallelismo del modello.
L’addestramento efficiente su un ambiente distribuito richiede l’aggiustamento degli iperparametri. Un esempio comune di buona pratica durante l’addestramento su più GPU è moltiplicare la dimensione del batch (o del mini-batch) per il numero di GPU al fine di mantenere la stessa dimensione del batch per GPU. Tuttavia, l’aggiustamento degli iperparametri influisce spesso sulla convergenza del modello. Pertanto, l’addestramento distribuito deve bilanciare tre fattori: distribuzione, iperparametri e accuratezza del modello.
In questo post, esploreremo l’effetto dell’addestramento distribuito sulla convergenza e come utilizzare l’ottimizzazione automatica dei modelli di Amazon SageMaker per ottimizzare gli iperparametri del modello per l’addestramento distribuito utilizzando il parallelismo dei dati.
Il codice sorgente menzionato in questo post può essere trovato nel repository GitHub (si consiglia un’istanza m5.xlarge).
- Comprendere tutti i dati
- Una palestra open-source per la progettazione assistita da apprendimento automatico dell’architettura informatica
- Produttività alimentata da AI L’AI generativa apre una nuova era di efficienza in tutti i settori
Scalare l’addestramento da un singolo a un ambiente distribuito
Il parallelismo dei dati è un modo per scalare il processo di addestramento su risorse di calcolo multiple e ottenere un tempo di addestramento più rapido. Con il parallelismo dei dati, i dati vengono suddivisi tra i nodi di calcolo e ogni nodo calcola i gradienti in base alla propria suddivisione e aggiorna il modello. Questi aggiornamenti possono essere effettuati utilizzando uno o più server dei parametri in modo asincrono, uno-a-molti o tutti-a-tutti. Un altro modo può essere utilizzare un algoritmo di AllReduce. Ad esempio, nell’algoritmo di ring-allreduce, ogni nodo comunica solo con due dei suoi nodi vicini, riducendo così i trasferimenti complessivi dei dati. Per saperne di più sui server dei parametri e sul ring-allreduce, consulta il lancio di TensorFlow distributed training facilmente con Horovod o i server dei parametri in Amazon SageMaker. Per quanto riguarda la suddivisione dei dati, se ci sono n nodi di calcolo, ogni nodo dovrebbe ottenere un sottoinsieme dei dati, approssimativamente di dimensione 1/n.
Per dimostrare l’effetto dello scaling dell’addestramento sulla convergenza del modello, abbiamo eseguito due semplici esperimenti:
- Addestrare un modello di classificazione delle immagini utilizzando un DNN con livelli completamente connessi e funzioni di attivazione ReLU utilizzando i framework MXNet e Gluon. Per i dati di addestramento, abbiamo utilizzato il dataset MNIST di cifre scritte a mano. Abbiamo utilizzato il codice sorgente fornito nel repository di esempi di SageMaker.
- Addestrare un modello di classificazione binaria utilizzando l’algoritmo XGBoost integrato di SageMaker. Abbiamo utilizzato il dataset di marketing diretto per prevedere i clienti bancari che sono probabilmente a rispondere a un’offerta specifica. Il codice sorgente e i passaggi per riprodurre l’esperimento possono essere trovati sul repository GitHub.
Ogni addestramento del modello è stato eseguito due volte: su un’istanza singola e distribuita su più istanze. Per l’addestramento distribuito del DNN, al fine di utilizzare appieno i processori distribuiti, abbiamo moltiplicato la dimensione del mini-batch per il numero di istanze (quattro). La tabella seguente riassume la configurazione e i risultati.
Tipo di problema | Classificazione delle immagini | Classificazione binaria | ||
Modello | DNN | XGBoost | ||
|
ml.c4.xlarge | ml.m5.2xlarge | ||
Dataset |
MNIST (Immagini etichettate) |
Marketing diretto (tabulare, categorie numeriche e vettoriali) | ||
|
Accuratezza | AUC | ||
Ep oche/Round | 20 | 150 | ||
Numero di istanze | 1 | 4 | 1 | 3 |
Tipo di distribuzione | N/A | Server dei parametri | N/A | AllReduce |
Tempo di addestramento (minuti) | 8 | 3 | 3 | 1 |
Punteggio di validazione finale | 0.97 | 0.11 | 0.78 | 0.63 |
Per entrambi i modelli, il tempo di addestramento è stato ridotto in modo quasi lineare dal fattore di distribuzione. Tuttavia, la convergenza del modello ha subito una significativa riduzione. Questo comportamento è coerente per i due diversi modelli, le diverse istanze di calcolo, i diversi metodi di distribuzione e i diversi tipi di dati. Quindi, perché la distribuzione del processo di addestramento ha influenzato l’accuratezza del modello?
Esistono diverse teorie che cercano di spiegare questo effetto:
- Quando gli aggiornamenti del tensore sono di grandi dimensioni, il traffico tra i worker e il server dei parametri può congestionarsi. Pertanto, i server dei parametri asincroni subiranno una convergenza significativamente peggiore a causa dei ritardi negli aggiornamenti dei pesi [1].
- Aumentare la dimensione del batch può portare a un overfitting e a una scarsa generalizzazione, riducendo quindi l’accuratezza della validazione [2].
- Quando si aggiornano in modo asincrono i parametri del modello, alcuni DNN potrebbero non utilizzare i pesi del modello più recentemente aggiornati; di conseguenza, calcoleranno i gradienti basandosi su pesi che sono alcune iterazioni indietro. Ciò porta a una obsolescenza dei pesi [3] e può essere causato da diverse ragioni.
- Alcuni iperparametri sono specifici del modello o dell’ottimizzatore. Ad esempio, la documentazione ufficiale di XGBoost afferma che il valore “exact” per l’iperparametro “tree_mode” non supporta l’addestramento distribuito perché XGBoost utilizza la distribuzione dei dati per righe mentre il metodo dell’albero “exact” funziona su un formato di colonne ordinate.
- Alcuni ricercatori hanno proposto che la configurazione di un mini-batch più grande possa portare a gradienti con meno stocasticità. Ciò può accadere quando la funzione di perdita contiene minimi locali e punti di sella e non viene apportata alcuna modifica alla dimensione del passo, per ottimizzazione che rimane bloccata in tali minimi locali o punti di sella [4].
Ottimizzare per l’addestramento distribuito
L’ottimizzazione degli iperparametri (HPO) è il processo di ricerca e selezione di un insieme di iperparametri ottimali per un algoritmo di apprendimento. SageMaker Automatic Model Tuning (AMT) fornisce HPO come un servizio gestito eseguendo più lavori di addestramento sul dataset fornito. SageMaker AMT cerca gli intervalli degli iperparametri specificati e restituisce i migliori valori, misurati da una metrica che si sceglie. È possibile utilizzare SageMaker AMT con gli algoritmi integrati o utilizzare algoritmi e contenitori personalizzati.
Tuttavia, l’ottimizzazione per l’addestramento distribuito differisce dall’HPO comune perché invece di lanciare un’unica istanza per lavoro di addestramento, ogni lavoro lancia effettivamente un cluster di istanze. Ciò comporta un impatto maggiore sui costi (soprattutto se si considerano costose istanze GPU accelerate, che sono tipiche per DNN). Oltre ai limiti di AMT, potrebbe essere possibile raggiungere i limiti dell’account SageMaker per il numero di istanze di addestramento simultanee. Infine, il lancio di cluster può introdurre sovraccarichi operativi a causa di tempi di avvio più lunghi. SageMaker AMT ha funzionalità specifiche per affrontare questi problemi. Hyperband con l’arresto anticipato garantisce che le configurazioni degli iperparametri che si comportano bene vengano ottimizzate ulteriormente e quelle che si comportano male vengano interrotte automaticamente. Ciò consente un uso efficiente del tempo di addestramento e riduce i costi superflui. Inoltre, SageMaker AMT supporta pienamente l’utilizzo delle istanze Amazon EC2 Spot, che possono ottimizzare il costo dell’addestramento fino al 90% rispetto alle istanze on-demand. Per quanto riguarda i tempi di avvio lunghi, SageMaker AMT riutilizza automaticamente le istanze di addestramento all’interno di ogni lavoro di ottimizzazione, riducendo così il tempo medio di avvio di ogni lavoro di addestramento di 20 volte. Inoltre, è necessario seguire le migliori pratiche di AMT, come la scelta degli iperparametri rilevanti, i loro intervalli e scale appropriati, il numero migliore di lavori di addestramento simultanei e impostare un seme casuale per riprodurre i risultati.
Nella prossima sezione, vedremo queste funzionalità in azione mentre configuriamo, eseguiamo e analizziamo un lavoro AMT utilizzando l’esempio XGBoost che abbiamo discusso in precedenza.
Configurare, eseguire e analizzare un lavoro di ottimizzazione
Come accennato in precedenza, il codice sorgente può essere trovato nel repository GitHub. Nei passaggi da 1 a 5, scarichiamo e prepariamo i dati, creiamo l’estimatore xgb3
(l’estimatore XGBoost distribuito è impostato per utilizzare tre istanze), eseguiamo i lavori di addestramento e osserviamo i risultati. In questa sezione, descriviamo come configurare il lavoro di ottimizzazione per quell’estimatore, assumendo che tu abbia già completato i passaggi da 1 a 5.
Un lavoro di ottimizzazione calcola gli iperparametri ottimali per i lavori di addestramento che avvia utilizzando una metrica per valutare le prestazioni. È possibile configurare la propria metrica, che SageMaker analizzerà in base a una regex configurata ed emetterà su stdout
, oppure utilizzare le metriche degli algoritmi integrati di SageMaker. In questo esempio, utilizziamo la metrica oggettiva integrata di XGBoost, quindi non è necessario configurare una regex. Per ottimizzare la convergenza del modello, ottimizziamo in base alla metrica AUC di validazione:
objective_metric_name="validation:auc"
Regoliamo sette iperparametri:
- num_round – Numero di round per il boosting durante l’addestramento.
- eta – Valore di riduzione della dimensione del passo utilizzato negli aggiornamenti per prevenire l’overfitting.
- alpha – Termine di regolarizzazione L1 sui pesi.
- min_child_weight – Somma minima del peso delle istanze (hessian) necessaria in un figlio. Se la fase di partizione dell’albero produce un nodo foglia con una somma del peso delle istanze inferiore a
min_child_weight
, il processo di costruzione si interrompe senza ulteriore partizione. - max_depth – Profondità massima di un albero.
- colsample_bylevel – Rapporto di sottocampionamento delle colonne per ogni suddivisione, a ogni livello. Questo sottocampionamento avviene una volta per ogni nuovo livello di profondità raggiunto in un albero.
- colsample_bytree – Rapporto di sottocampionamento delle colonne durante la costruzione di ogni albero. Per ogni albero costruito, il sottocampionamento avviene una volta.
Per saperne di più sugli iperparametri di XGBoost, vedere gli Iperparametri di XGBoost. Il codice seguente mostra i sette iperparametri e i loro intervalli:
hyperparameter_ranges = {
"num_round": IntegerParameter(100, 200),
"eta": ContinuousParameter(0, 1),
"min_child_weight": ContinuousParameter(1, 10),
"alpha": ContinuousParameter(0, 2),
"max_depth": IntegerParameter(1, 10),
"colsample_bylevel": ContinuousParameter(0, 1),
"colsample_bytree": ContinuousParameter(0, 1),
}
Successivamente, forniamo la configurazione per la strategia Hyperband e la configurazione dell’oggetto tuner utilizzando il SDK di SageMaker. HyperbandStrategyConfig
può utilizzare due parametri: max_resource
(opzionale) per il numero massimo di iterazioni da utilizzare per un job di addestramento per raggiungere l’obiettivo, e min_resource
– il numero minimo di iterazioni da utilizzare da un job di addestramento prima di interrompere l’addestramento. Utilizziamo HyperbandStrategyConfig
per configurare StrategyConfig
, che viene successivamente utilizzato nella definizione del job di ottimizzazione. Vedere il codice seguente:
hsc = HyperbandStrategyConfig(max_resource=30, min_resource=1)
sc = StrategyConfig(hyperband_strategy_config=hsc)
Ora creiamo un oggetto HyperparameterTuner
, a cui passiamo le seguenti informazioni:
- L’estimatore XGBoost, impostato per funzionare con tre istanze
- Il nome e la definizione della metrica obiettivo
- I nostri intervalli di iperparametri
- Configurazioni delle risorse di ottimizzazione come il numero totale di job di addestramento da eseguire e quanti job di addestramento possono essere eseguiti in parallelo
- Impostazioni Hyperband (la strategia e la configurazione configurate nell’ultimo passaggio)
- Early stopping (
early_stopping_type
) impostato suOff
Perché impostiamo early stopping su Off? I job di addestramento possono essere interrotti in anticipo quando è improbabile che migliorino la metrica obiettivo del job di ottimizzazione degli iperparametri. Ciò può contribuire a ridurre il tempo di calcolo e a evitare l’overfitting del modello. Tuttavia, Hyperband utilizza un meccanismo avanzato incorporato per applicare l’early stopping. Pertanto, il parametro early_stopping_type
deve essere impostato su Off
quando si utilizza la funzione built-in di early stopping di Hyperband. Vedere il codice seguente:
tuner = HyperparameterTuner(
xgb3,
objective_metric_name,
hyperparameter_ranges,
max_jobs=30,
max_parallel_jobs=4,
strategy="Hyperband",
early_stopping_type="Off",
strategy_config=sc
)
Infine, avviamo il job di ottimizzazione del modello automatico chiamando il metodo fit. Se si desidera avviare il job in modo asincrono, impostare wait
su False
. Vedere il codice seguente:
tuner.fit(
{"train": s3_input_train, "validation": s3_input_validation},
include_cls_metadata=False,
wait=True,
)
È possibile seguire l’avanzamento del job e il riassunto sulla console di SageMaker. Nel riquadro di navigazione, selezionare Addestramento, quindi scegliere Job di ottimizzazione degli iperparametri, quindi selezionare il job di ottimizzazione pertinente. La schermata seguente mostra il job di ottimizzazione con i dettagli dello stato dei job di addestramento e delle prestazioni.
Quando il lavoro di ottimizzazione è completo, possiamo esaminare i risultati. Nell’esempio del notebook, mostriamo come estrarre i risultati usando il SDK di SageMaker. Prima, esaminiamo come il lavoro di ottimizzazione ha aumentato la convergenza del modello. È possibile allegare l’oggetto HyperparameterTuner
utilizzando il nome del lavoro e chiamare il metodo describe. Il metodo restituisce un dizionario contenente i metadati e i risultati del lavoro di ottimizzazione.
Nel codice seguente, recuperiamo il valore del miglior lavoro di addestramento, misurato dalla nostra metrica obiettivo (AUC di validazione):
tuner = HyperparameterTuner.attach(tuning_job_name=tuning_job_name)
tuner.describe()["BestTrainingJob"]["FinalHyperParameterTuningJobObjectiveMetric"]["Value"]
Il risultato è 0.78 in AUC sul set di validazione. Questo è un miglioramento significativo rispetto al valore iniziale di 0.63!
Successivamente, vediamo quanto velocemente è stato eseguito il lavoro di addestramento. Per fare ciò, utilizziamo il metodo HyperparameterTuningJobAnalytics nel SDK per ottenere i risultati sul lavoro di ottimizzazione e li leggiamo in un dataframe di Pandas per l’analisi e la visualizzazione:
tuner_analytics = sagemaker.HyperparameterTuningJobAnalytics(tuning_job_name)
full_df = tuner_analytics.dataframe()
full_df.sort_values(by=["FinalObjectiveValue"], ascending=False).head()
Vediamo quanto tempo in media ha impiegato un lavoro di addestramento con la strategia Hyperband:
full_df["TrainingElapsedTimeSeconds"].mean()
In media, ci sono voluti circa 1 minuto. Questo è coerente con il meccanismo della strategia Hyperband, che interrompe precocemente i lavori di addestramento che non stanno ottenendo risultati soddisfacenti. Per quanto riguarda il costo, il lavoro di ottimizzazione ci è stato addebitato per un totale di 30 minuti di tempo di addestramento. Senza l’arresto anticipato di Hyperband, la durata totale addebitabile per l’addestramento sarebbe stata di 90 minuti (30 lavori * 1 minuto per lavoro * 3 istanze per lavoro). Quindi, si ottiene un risparmio di costi triplicato! Infine, vediamo che il lavoro di ottimizzazione ha eseguito 30 lavori di addestramento e ha impiegato un totale di 12 minuti. Ciò rappresenta quasi il 50% in meno del tempo previsto (30 lavori / 4 lavori in parallelo * 3 minuti per lavoro).
Conclusioni
In questo post, abbiamo descritto alcuni problemi di convergenza osservati durante l’addestramento di modelli con ambienti distribuiti. Abbiamo visto che SageMaker AMT utilizzando Hyperband ha affrontato le principali preoccupazioni introdotte dall’ottimizzazione dell’addestramento distribuito parallelo dei dati: convergenza (che è migliorata di oltre il 10%), efficienza operativa (il lavoro di ottimizzazione ha impiegato il 50% in meno del tempo che avrebbe impiegato un lavoro sequenziale non ottimizzato) ed efficienza dei costi (30 rispetto ai 90 minuti addebitabili per il tempo di lavoro di addestramento). La seguente tabella riassume i nostri risultati:
Metrica di miglioramento | Nessuna ottimizzazione/Implementazione di un modello di ottimizzazione ingenuo | SageMaker Hyperband Automatic Model Tuning | Miglioramento misurato |
Qualità del modello (Misurata da AUC di validazione) | 0.63 | 0.78 | 15% |
Costo (Misurato in minuti di addestramento addebitabili) | 90 | 30 | 66% |
Efficienza operativa (Misurata dal tempo totale di esecuzione) | 24 | 12 | 50% |
Per ottimizzare l’adattamento in base alla scalabilità (dimensione del cluster), è possibile ripetere l’operazione di ottimizzazione con diverse configurazioni di cluster e confrontare i risultati per trovare gli iperparametri ottimali che soddisfano velocità e precisione del modello.
Nella sezione finale del notebook abbiamo incluso i passaggi per raggiungere questo obiettivo.
Riferimenti
[1] Lian, Xiangru, et al. “Asynchronous decentralized parallel stochastic gradient descent.” International Conference on Machine Learning. PMLR, 2018.
[2] Keskar, Nitish Shirish, et al. “On large-batch training for deep learning: Generalization gap and sharp minima.” arXiv preprint arXiv:1609.04836 (2016).
[3] Dai, Wei, et al. “Toward understanding the impact of staleness in distributed machine learning.” arXiv preprint arXiv:1810.03264 (2018).
[4] Dauphin, Yann N., et al. “Identifying and attacking the saddle point problem in high-dimensional non-convex optimization.” Advances in neural information processing systems 27 (2014).