Gradient Accumulation
Scopri come l’accumulo dei gradienti consenta batch size effettive più grandi con una memoria GPU limitata, grazie a indicazioni pratiche su PyTorch e sull’addestramento di Ultralytics YOLO.
L'accumulo dei gradienti è una tecnica di addestramento che somma i gradienti di diversi batch piccoli, chiamati microbatch, prima di eseguire un singolo aggiornamento dei pesi del modello. Approssima l'addestramento con una dimensione del batch maggiore quando la memoria GPU disponibile non è sufficiente a contenere l'intero batch in una sola volta. In questo modo il gradient descent ad alto consumo di memoria diventa praticabile senza modificare l'architettura del modello o ridurre la risoluzione dell'input.
Come funziona l'accumulo dei gradienti#
Durante l'addestramento normale, ogni batch segue tre passaggi principali: calcolare la loss, usare la backpropagation per calcolare i gradienti e lasciare che l'ottimizzatore aggiorni i pesi del modello. I gradienti vengono quindi azzerati prima del batch successivo.
L'accumulo dei gradienti ritarda l'aggiornamento dell'ottimizzatore. Ogni microbatch esegue un passaggio forward e backward, ma i suoi gradienti rimangono in memoria e vengono sommati a quelli dei microbatch successivi. Questo comportamento deriva naturalmente dall'operazione backward di PyTorch, che accumula i valori nel campo dei gradienti di ciascun parametro.
Dopo il numero configurato di passaggi di accumulo:
- L'ottimizzatore aggiorna i pesi del modello.
- I gradienti vengono reimpostati usando un'operazione come Optimizer.zero_grad.
- Inizia una nuova finestra di accumulo.
La dimensione effettiva del batch è:
microbatch size x accumulation steps x number of training devices
Ad esempio, un microbatch di 4 immagini accumulato per 8 passaggi si comporta approssimativamente come un batch di 32 immagini su una GPU. Con quattro GPU, la dimensione effettiva globale del batch diventa 128.
Effetti su memoria, velocità e apprendimento#
L'accumulo dei gradienti riduce la memoria di picco necessaria per le attivazioni, perché nella rete passa un solo microbatch alla volta. Non riduce in modo sostanziale la memoria utilizzata dai parametri del modello, dai gradienti o dallo stato dell'ottimizzatore.
Inoltre, di solito non accelera l'addestramento. L'elaborazione di otto microbatch richiede comunque otto passaggi forward e backward e i batch più piccoli possono utilizzare la GPU in modo meno efficiente. Il vantaggio principale consiste nel far rientrare un batch effettivo desiderato in una memoria limitata. Un vantaggio secondario può verificarsi nell'addestramento distribuito, in cui le implementazioni possono evitare di sincronizzare i gradienti fino alla fine di una finestra di accumulo usando funzionalità come DistributedDataParallel no_sync.
Un'implementazione manuale divide comunemente la loss di ogni microbatch per il numero di passaggi di accumulo, in modo che il gradiente risultante rappresenti una media anziché una somma. I trainer di alto livello possono gestire automaticamente la normalizzazione, quindi un'ulteriore scalatura può produrre aggiornamenti errati.
L'accumulo può approssimare un batch grande reale, ma i risultati non sono sempre identici. Le statistiche della batch normalization vengono calcolate sui singoli microbatch, mentre anche le operazioni stocastiche e l'ordine dei calcoli in virgola mobile possono introdurre differenze. Pertanto, potrebbe essere necessario convalidare il learning rate anziché scalarlo automaticamente.
Tecniche correlate e differenze principali#
L'accumulo dei gradienti viene spesso confuso con altre tecniche per la memoria o la stabilità:
- Il gradient checkpointing riduce la memoria delle attivazioni ricalcolando operazioni selezionate del passaggio forward durante la backpropagation. La documentazione di PyTorch sull'activation checkpointing descrive questo compromesso tra calcolo e memoria. L'accumulo, invece, suddivide un batch grande in microbatch più piccoli.
- La mixed precision memorizza o calcola operazioni selezionate con tipi di dati a precisione inferiore. Può ridurre la memoria e migliorare il throughput, mentre l'accumulo modifica la frequenza degli aggiornamenti dell'ottimizzatore. Le tecniche possono essere combinate seguendo il corretto workflow di accumulo con automatic mixed precision.
- Il gradient clipping limita l'ampiezza del gradiente per ridurre l'instabilità causata da aggiornamenti insolitamente grandi. Non crea un batch effettivo più grande. Quando viene combinato con l'accumulo, il clipping dovrebbe normalmente essere eseguito dopo l'accumulo completo del gradiente, usando un'operazione come clip_grad_norm.
Applicazioni nel mondo reale#
Nella segmentazione di immagini mediche ad alta risoluzione, una GPU da 12 GB potrebbe contenere solo due scansioni grandi alla volta. L'accumulo dei gradienti su otto microbatch produce un batch effettivo di 16, preservando al contempo la risoluzione necessaria per identificare piccole strutture anatomiche. Il compromesso consiste in un intervallo più lungo tra gli aggiornamenti dell'ottimizzatore.
Per il rilevamento di oggetti aerei, un team di ingegneria potrebbe addestrare il modello su quattro GPU con sei immagini per dispositivo e quattro passaggi di accumulo. Il batch globale effettivo è di 96 immagini. Questo può stabilizzare gli aggiornamenti per scene contenenti molti veicoli o edifici di piccole dimensioni, mantenendo ogni dispositivo entro il proprio limite di memoria. I team possono gestire esperimenti cloud, dataset ed esecuzioni di addestramento tramite l'addestramento cloud di Ultralytics Platform.
Accumulo dei gradienti con Ultralytics YOLO#
Il workflow di addestramento del modello di Ultralytics deriva il comportamento dell'accumulo dalle impostazioni fisiche batch e nominali nbs. Con batch=4 e nbs=64, il trainer punta a un batch nominale di 64 rimandando gli aggiornamenti dell'ottimizzatore su più microbatch.
from ultralytics import YOLO
# Load a pretrained YOLO26 detection model
model = YOLO("yolo26n.pt")
# Use a small physical batch and a larger nominal batch
results = model.train(
data="coco8.yaml",
epochs=10,
batch=4,
nbs=64,
)Il trainer di alto livello gestisce la backpropagation, l'accumulo, i passaggi dell'ottimizzatore e l'azzeramento dei gradienti. Il suo comportamento è documentato nel riferimento Ultralytics BaseTrainer. In pratica, scegli il microbatch più grande che rientri in modo affidabile nella memoria, calcola il batch effettivo desiderato e confronta i risultati di convalida quando modifichi il numero di passaggi di accumulo, il learning rate o il numero di dispositivi.









