Vanishing Gradient
Il problema del gradiente evanescente si verifica quando i gradienti si riducono strato dopo strato durante la retropropagazione, impedendo ai primi strati di continuare ad apprendere. Panoramica delle cause e delle soluzioni.
Il problema del gradiente evanescente si verifica quando i gradienti che la retropropagazione invia dalla funzione di perdita verso i primi strati di una rete neurale profonda si riducono geometricamente con la profondità, per cui gli strati iniziali ricevono aggiornamenti troppo piccoli per apprendere alcunché. Poiché il gradiente di uno strato è il prodotto delle derivate locali di tutti gli strati che lo sovrastano, una rete i cui strati moltiplicano ciascuno il gradiente per un fattore inferiore a 1 può perdere molti ordini di grandezza tra output e input. Sepp Hochreiter analizzò questo effetto nella sua tesi di laurea del 1991, e ciò continuò a rendere difficili da addestrare le reti neurali feedforward profonde e le reti neurali ricorrenti (RNNs) finché non furono introdotte funzioni di attivazione, inizializzazioni e architetture migliori.
Perché i gradienti svaniscono#
La backpropagation applica la regola della catena: il gradiente che raggiunge uno strato è il gradiente a monte moltiplicato per la matrice dei pesi e la derivata della funzione di attivazione di ogni strato successivo. La derivata della sigmoide non supera mai 0,25, valore che assume con un input pari a 0, e tende a 0 quando l'unità satura con input molto positivi o negativi. La derivata della tanh raggiunge un massimo di 1 e tende anch'essa a 0 quando la funzione è satura. Venti strati con sigmoide moltiplicano quindi il gradiente al massimo per 0,25²⁰, un valore inferiore a 10⁻¹², prima ancora di considerare i pesi. La scala dei pesi è importante quanto la funzione di attivazione: Glorot e Bengio attribuirono gran parte della difficoltà all'inizializzazione e proposero varianze dei pesi scalate in base al numero di input e output di ciascuno strato, in modo da mantenere approssimativamente costanti le varianze delle attivazioni e dei gradienti tra gli strati.
L'effetto si misura facilmente confrontando le dimensioni dei gradienti dei pesi in cima e alla base di una rete con 20 strati a sigmoide, con e senza connessioni residuali:
import torch
torch.manual_seed(0)
x = torch.randn(64, 32)
# The same 20-layer sigmoid network, without and with residual shortcuts
for residual in (False, True):
layers = [torch.nn.Linear(32, 32) for _ in range(20)]
h = x
for layer in layers:
out = torch.sigmoid(layer(h))
h = h + out if residual else out
h.sum().backward()
# Compare the weight-gradient size at the last layer and the first layer
last, first = layers[-1].weight.grad.norm(), layers[0].weight.grad.norm()
print(f"residual={residual}: layer 20 gradient {last:.1e}, layer 1 gradient {first:.1e}")Senza connessioni shortcut, la norma del gradiente dell'ultimo strato è 2.5e+02 e quella del primo è 4.2e-15, circa 17 ordini di grandezza inferiore: di fatto, i pesi del primo strato non cambiano mai. Con le connessioni shortcut residuali, il gradiente del primo strato è 5.6e+01, circa 38 volte inferiore a quello dell'ultimo strato, pari a 2.1e+03.
Gradienti evanescenti e gradienti esplosivi#
Entrambi i problemi derivano dalla stessa moltiplicazione ripetuta. I gradienti evanescenti bloccano silenziosamente l'apprendimento: la loss continua a diminuire, grazie agli ultimi strati, mentre quelli iniziali restano vicini all'inizializzazione casuale. I gradienti esplosivi, invece, crescono geometricamente e si manifestano in modo evidente con picchi della loss e valori NaN. Il gradient clipping limita la norma di un gradiente esplosivo prima di ogni aggiornamento e non ha alcun effetto su un gradiente già svanito. Il problema delle ReLU morenti è un fenomeno correlato: l'input di un'unità ReLU rimane negativo, quindi il suo gradiente è esattamente 0 e l'unità smette di apprendere.
Come prevenire i gradienti evanescenti#
La soluzione più diffusa è la connessione residua, la scorciatoia identità alla base delle reti residue (ResNet). Un blocco residuo restituisce x + F(x); il suo gradiente rispetto a x è quindi 1 più la derivata di F e il percorso di scorciatoia trasmette inalterato il gradiente proveniente dai livelli precedenti.
Le connessioni shortcut residuali permettono di addestrare ResNet con più di 100 strati e compaiono in quasi tutte le architetture profonde moderne, dai transformer a YOLO26, i cui blocchi C3k2 racchiudono colli di bottiglia residuali e i cui normali blocchi convoluzionali abbinano la normalizzazione del batch alle attivazioni SiLU.
Altre soluzioni affiancano le connessioni residuali:
- Funzioni di attivazione non saturanti: ReLU ha una derivata esattamente pari a 1 per gli input positivi, mentre Leaky ReLU e SiLU mantengono un gradiente diverso da zero anche per gli input negativi.
- Inizializzazione scalata: l'inizializzazione Xavier (Glorot) è adatta agli strati tanh e sigmoide, mentre l'inizializzazione He raddoppia la varianza dei pesi per compensare l'azzeramento di metà degli input causato da ReLU.
- Strati di normalizzazione: la normalizzazione del batch e la normalizzazione degli strati mantengono le pre-attivazioni vicine a una media pari a zero e a una varianza unitaria, lontano dalle regioni piatte delle funzioni di attivazione saturanti.
- Architetture ricorrenti con gate: le reti Long short-term memory (LSTM) e le unità ricorrenti con gate (GRU) trasmettono lo stato usando aggiornamenti additivi controllati da gate, invece di moltiplicazioni ripetute; ciò ha permesso alla LSTM originale di gestire intervalli temporali di oltre 1.000 passaggi.










