Separare microbatch, passaggio all'indietro e aggiornamento
Il microbatch è il gruppo di esempi trattato da un passaggio in avanti su una replica. Il passaggio all'indietro calcola il suo contributo ai gradienti. L'aggiornamento dell'ottimizzatore usa i gradienti disponibili per modificare i parametri. Con l'accumulo, diversi passaggi in avanti/all'indietro precedono questo aggiornamento; i parametri restano invariati durante il gruppo.
In PyTorch, i gradienti si accumulano nei tensori previsti a questo scopo. Azzerare i gradienti dopo ogni microbatch annullerebbe quindi l'accumulo desiderato. Al contrario, dimenticare di riportarli a zero tra due gruppi farebbe contribuire esempi dell'aggiornamento precedente.
Definisci la tua unità di registrazione: numero di microbatch, aggiornamento dell'ottimizzatore, esempi o token visti. La sola parola «step» è ambigua. Una curva di perdita non si confronta correttamente se l'asse rappresenta otto volte più esempi in uno degli esperimenti.
Fonti tecniche: PyTorch — accumulo e azzeramento dei gradienti
Calcolare il batch effettivo senza contare due volte le GPU
Indichiamo con m il numero di esempi per microbatch e per replica, con A il numero di microbatch accumulati, con D il numero di repliche di parallelismo dei dati. Se queste dimensioni sono costanti e gli esempi correttamente distribuiti, il numero di esempi che contribuiscono a un aggiornamento globale è m × A × D.
Il fattore D non indica necessariamente tutte le schede della macchina. GPU che condividono uno stesso modello tramite parallelismo tensoriale o di pipeline non diventano altrettante repliche di dati. Inserisci i gruppi realmente configurati, non semplicemente la quantità commerciale del lotto.
Esempio aritmetico: due esempi per microbatch, otto accumulazioni e due repliche danno 32 esempi per aggiornamento globale. Ogni replica elabora sedici esempi in questo gruppo. La tabella confronta dei conteggi; non ne classifica la memoria o la velocità.
| m | A | D | Esempi per aggiornamento globale |
|---|---|---|---|
| 2 | 8 | 2 | 32 |
| 1 | 16 | 2 | 32 |
| 4 | 4 | 2 | 32 |
| 2 | 8 | 1 | 16 |
Fonti tecniche: PyTorch — batch effettivo e accumulazione in precisione mista · PyTorch — comportamento delle repliche DistributedDataParallel
Normalizzare la perdita in base agli elementi effettivamente valutati
Per una perdita media su microbatch contenenti lo stesso numero di elementi rilevanti, dividere ogni contributo per A dà la media del gruppo. Questa regola presuppone che il framework non effettui già questa normalizzazione. Con uno strumento che gestisce l’accumulazione, rileggi il suo contratto prima di aggiungere una divisione manuale.
Per una perdita media per token, lunghezze diverse cambiano il denominatore. Occorre rapportare la somma delle perdite ai token effettivamente supervisionati del gruppo, esclusi padding e posizioni ignorate. La media delle medie dei microbatch non dà generalmente lo stesso obiettivo.
Esempio teorico: un microbatch conta 512 token supervisionati con una perdita media di 2; un altro ne conta 1.536 con una media di 4. La media ponderata vale (512 × 2 + 1.536 × 4) ÷ 2.048 = 3,5. La media non ponderata vale 3 e sovrappesa il gruppo piccolo. Questi valori illustrano unicamente il calcolo.
Fonti tecniche: Hugging Face Accelerate — accumulazione con esempi di dimensioni variabili
Organizzare un gruppo di accumulazione completo
Prepara prima i confini del gruppo e il suo denominatore. Per ogni microbatch, calcola l’output, la perdita normalizzata e il passaggio all’indietro senza aggiornamento intermedio. Libera gli output di cui non hai più bisogno; conservare perdite collegate al loro grafo in una lista può prolungare la vita delle allocazioni.
Dopo l’ultimo contributo, applica le operazioni previste sul gradiente completo, poi l’aggiornamento. Reimposta quindi i gradienti per il gruppo successivo. Se il percorso termina con meno di A microbatch, scegli esplicitamente di trattare questo gruppo parziale con il suo vero denominatore o di scartarlo; annota gli esempi coinvolti.
Con una precisione mista che usa GradScaler, il fattore di scala resta costante durante l’accumulazione. Il riscalamento reale e un eventuale clipping intervengono dopo i contributi; l’aggiornamento dello scaler segue il tentativo di passo. I controlli di valori non finiti possono impedire la modifica dei parametri.
Lo scheduler deve seguire l’unità annunciata dal tuo ciclo. Se è definito per aggiornamento dell’ottimizzatore, chiamarlo a ogni microbatch cambierebbe il calendario. Registra separatamente i tentativi e gli aggiornamenti realmente applicati quando il tuo sistema può saltarne alcuni.
Fonti tecniche: PyTorch — grafi autograd e tensori conservati per backward · PyTorch — accumulazione, unscale, clipping e GradScaler
In multi-GPU, verificare riduzione e distribuzione degli esempi
DistributedDataParallel sincronizza i gradienti tra le repliche. Nel suo comportamento usuale, la riduzione li media; una perdita sommata e una perdita mediata localmente non hanno quindi la stessa scala. Con numeri di token diversi tra le repliche, il denominatore globale e questa riduzione devono essere considerati insieme.
Verifica gli ID effettivamente elaborati: duplicare involontariamente gli stessi esempi su tutte le schede non aumenta di altrettanto l’informazione del gruppo. Per ritardare le comunicazioni intermedie, no_sync può essere impiegato sui microbatch che precedono la sincronizzazione finale; il suo contesto deve coprire anche il passaggio in avanti.
Non trasporre questa regola a tutti i sistemi distribuiti. Sharding degli stati, pipeline, hook di comunicazione e framework possono cambiare le operazioni effettive. Parti dalla configurazione supportata dal tuo strumento, poi controlla un gruppo completo su ogni replica.
Fonti tecniche: PyTorch — riduzione dei gradienti e portata di no_sync in DDP
Perché lo stesso batch effettivo non garantisce la stessa esperienza
L'uguaglianza m × A × D è un conteggio. Per ritrovare un gradiente di un batch grande occorrono in particolare contributi correttamente pesati, lo stesso stato dei parametri durante il gruppo e operazioni compatibili con questa scomposizione. La prossimità numerica si verifica con una tolleranza adeguata; non si deduce dal solo prodotto.
BatchNorm calcola statistiche a partire dagli input del suo passaggio: più microbatch piccoli non gli presentano gli stessi gruppi di un batch grande. Anche le operazioni casuali, l'ordine dei calcoli e gli arrotondamenti possono variare. Non promettere pesi finali identici bit per bit.
Un cambiamento del batch globale può anche modificare il numero di aggiornamenti per lo stesso numero di esempi visti. Fissa in anticipo l'asse di confronto e la tua regola di qualità. Non cambiare simultaneamente il learning rate, lo scheduler e la durata senza documentare queste nuove ipotesi.
Fonti tecniche: PyTorch — statistiche di BatchNorm1d · PyTorch — limiti di riproducibilità
Controllare la memoria e decidere il seguito
Strumenta un gruppo che includa i passaggi all'indietro e il primo aggiornamento, poi i gruppi successivi. Una riuscita in forward non convalida i gradienti o gli stati creati dall'optimizer. I contatori devono mantenere il loro perimetro per device. Il dossier memoria fornisce il metodo di lettura delle baseline e dei picchi.
Se un gruppo fallisce, riduci il microbatch e ricalcola A per conservare il batch effettivo desiderato quando questa scelta resta pertinente. Questa modifica non garantisce né una divisione proporzionale del picco né una durata migliore. Se i pesi o gli stati dominano, la sola accumulazione può essere insufficiente.
Prima di una campagna, controlla un aggiornamento su un piccolo set sotto controllo: stessi esempi, perdita pesata, gradienti finiti, confine di gruppo e numero di step. Poi valuta la qualità con il protocollo scelto. Il piccolo MLP di inferenza del dossier scaricabile non esegue questa ricetta di addestramento; non sostituisce questo controllo.
La tua scheda finale riunisce m, A, D, i token supervisionati, la precisione, la normalizzazione, il trattamento dell'ultimo gruppo e i picchi osservati. Torna poi alla scelta della configurazione e al budget di esperimenti, separando preparazione, prove e risultati realmente accettati.
- Perdita anormalmente piccola: cerca una doppia divisione per l'accumulazione.
- Risultato che varia con la suddivisione: verifica i token ignorati e la media delle medie.
- Accumulazione senza effetto: controlla zero_grad e optimizer.step.
- Memoria crescente: cerca i riferimenti conservati tra i microbatch.
- Calendario sfasato: distingui passaggi all'indietro e aggiornamenti.
Fonti tecniche: Hugging Face — posti di memoria di un addestramento
Domande pratiche
Accumulare sedici microbatch moltiplica la memoria per sedici?
Non necessariamente: i contributi sono trattati in successione. I gradienti persistono, mentre le attivazioni inutili possono essere liberate. Il picco dipende però dal modello, dai riferimenti conservati e dagli stati dell'optimizer; misura il gruppo completo.
Due GPU raddoppiano sempre il batch effettivo?
Solo se queste GPU partecipano come due repliche di dati con il microbatch annunciato. Schede che condividono uno stesso modello non costituiscono automaticamente due repliche. Verifica i gruppi distribuiti e gli esempi trattati.
Posso dividere tutte le perdite per il numero di accumulazioni?
Questa regola semplice corrisponde a microbatch di peso uguale, senza normalizzazione già gestita dal framework. Con numeri variabili di token supervisionati o un ultimo gruppo incompleto, usa il denominatore reale dell'obiettivo.