Vai al contenuto principale

Gradient Clipping: come prevenire gli exploding gradients

Il gradient clipping è una correzione da una riga che impedisce agli exploding gradients di rovinare l'addestramento di reti neurali profonde. Questa guida spiega come funziona, i due metodi principali di clipping, la scelta della soglia e l'implementazione in PyTorch e TensorFlow.
Aggiornato 10 giu 2026  · 13 min leggi

Esplora con l'AI

Apri in ChatGPTApri in ClaudeApri in Perplexity

Quante volte hai visto un valore di loss NaN durante l'addestramento di una rete neurale profonda?

Dopo ore di addestramento, la curva della loss sembra in salute e poi all'improvviso schizza all'infinito. La causa di solito sono gli exploding gradients: valori di gradiente che crescono così tanto durante la backpropagation da rendere instabili gli aggiornamenti dei parametri e mandare in crisi il modello. Il problema colpisce soprattutto le reti ricorrenti, ma si presenta anche nei transformer e nelle reti feedforward profonde.

Il gradient clipping risolve limitando l'ampiezza dei gradienti prima che arrivino all'ottimizzatore. È un'aggiunta di una riga al tuo training loop che mantiene gli aggiornamenti entro limiti senza modificare il modello.

In questo articolo vedremo l'intuizione dietro il gradient clipping, i due metodi principali, come scegliere una soglia e come implementarlo in PyTorch e TensorFlow.

Ma che cos'è esattamente la loss in data science? Leggi il nostro post sul blog Loss Function in Machine Learning per scoprirlo.

Cos'è il Gradient Clipping?

Il gradient clipping è una tecnica che limita l'ampiezza dei gradienti durante l'addestramento per prevenire aggiornamenti dei parametri instabili.

Quando un gradiente diventa troppo grande, l'ottimizzatore fa un passo enorme nello spazio dei parametri e spinge i pesi in una regione in cui la loss esplode. Il clipping ti aiuta limitando quella dimensione del passo prima che possa fare danni.

È importante notare che il gradient clipping non modifica l'architettura del modello. Non aggiungi layer né cambi funzioni di attivazione. Modifica solo il processo di training intercettando i gradienti tra la backpropagation e lo step dell'ottimizzatore.

Per questo è economico da provare e facile da rimuovere. Come vedrai più avanti, basta una riga di codice.

Come funziona il Gradient Clipping

La meccanica è semplice. L'operazione di clipping è posizionata tra il passaggio backward e lo step dell'ottimizzatore, e segue sempre quattro passaggi a ogni iterazione.

  1. Calcola i gradienti: esegui il forward pass, calcola la loss e avvia la backpropagation. Qui non cambia nulla: i gradienti scorrono attraverso la rete come sempre.
  2. Controlla l'ampiezza del gradiente: misura quanto sono grandi i gradienti. A seconda del metodo, significa esaminare i singoli valori o calcolare la norma complessiva su tutti i parametri.
  3. Riduci i gradienti se superano una soglia: se l'ampiezza supera il limite che hai impostato, ridimensiona i gradienti. Se non lo supera, lasciali invariati.
  4. Aggiorna i parametri del modello: passa i gradienti tagliati all'ottimizzatore e applica l'aggiornamento dei pesi.

La maggior parte del tempo i gradienti rimangono al di sotto e l'addestramento procede come se il gradient clipping non ci fosse. Quando si verifica un picco, il clipping lo intercetta prima che l'ottimizzatore reagisca.

Tutto qui.

Metodi comuni di Gradient Clipping

Ci sono due modi per fare clipping dei gradienti, e la differenza sta in cosa misuri e cosa ridimensioni.

Clip by value

Il clip by value limita individualmente ciascun elemento del gradiente.

Scegli un intervallo, ad esempio [-1.0, 1.0], e qualsiasi valore di gradiente al di fuori di quell'intervallo viene arrotondato al limite più vicino. Un gradiente di 2.5 diventa 1.0. Un gradiente di -2.5 diventa -1.0. I valori già all'interno dell'intervallo restano invariati.

esempio di gradient clipping con clip by value

Esempio di clip by value

Il punto di forza è la semplicità. Non c'è matematica oltre a un'operazione di min/max ed è veloce da eseguire.

Ma questo approccio ha un lato negativo. Tagliare i singoli valori cambia la direzione del vettore gradiente. Se una componente viene tagliata e le altre no, il vettore aggiornato non punta più dove la backpropagation indicava. L'ottimizzatore finisce per fare un passo in una direzione leggermente sbagliata.

Per questo il clip by value è meno comune nella pratica.

Clip by norm

Il clip by norm ridimensiona l'intero vettore gradiente quando la sua ampiezza complessiva supera una soglia.

Invece di guardare ai singoli valori, calcola la norma di tutti i gradienti insieme (di solito la norma L2) e la confronta con un valore massimo. Se la norma è sotto soglia, non succede nulla. Se è sopra, ogni gradiente viene moltiplicato per lo stesso fattore di scala per riportare la norma al limite.

esempio di gradient clipping con clip by norm

Esempio di clip by norm

Il vantaggio è la conservazione della direzione. Poiché ogni componente si riduce dello stesso fattore, il vettore gradiente continua a puntare nella direzione originale. Stai solo accorciando il passo, non cambiandone la direzione.

Per questo il clip by norm è diventato lo standard. clip_grad_norm_ di PyTorch e clipnorm di TensorFlow implementano entrambi questo metodo, e la maggior parte delle pipeline di training moderne lo usa di default.

Exploding Gradients vs Vanishing Gradients

Exploding e vanishing gradients sono problemi comuni nel deep learning, ma solo uno dei due è risolto dal gradient clipping.

Exploding gradients

Gli exploding gradients si verificano quando i valori dei gradienti crescono troppo durante la backpropagation.

Di solito compaiono in reti profonde o architetture ricorrenti, dove i gradienti vengono moltiplicati su molti layer o passi temporali. Se quelle moltiplicazioni si accumulano nella direzione sbagliata, l'ampiezza del gradiente esplode. L'ottimizzatore quindi effettua un aggiornamento enorme dei parametri, i pesi saltano a valori estremi e la loss spesso diventa NaN o Inf.

Lo noterai come picchi improvvisi della loss o un modello che diverge dal nulla.

Vanishing gradients

I vanishing gradients sono il problema opposto. I valori dei gradienti si riducono verso zero mentre si propagano all'indietro nella rete.

Quando i gradienti diventano troppo piccoli, gli aggiornamenti dei pesi sono minuscoli. I layer iniziali smettono di imparare, quelli profondi imparano lentamente e l'addestramento praticamente si ferma. La curva della loss si appiattisce e non migliora, anche dopo molte epoche.

Questa era la ragione principale per cui gli RNN faticavano con sequenze lunghe prima dell'arrivo di LSTM e GRU.

Dove si inserisce il gradient clipping

Il gradient clipping affronta gli exploding gradients, non i vanishing gradients.

Il clipping riduce i gradienti troppo grandi, ma non fa nulla quando i gradienti sono troppo piccoli. Per i vanishing gradients servono una migliore inizializzazione dei pesi, connessioni residuali, batch normalization o architetture pensate per preservare il flusso del gradiente.

Gradient Clipping by Norm spiegato

Il clipping per norma è il metodo che la maggior parte dei lettori cerca davvero quando cerca gradient clipping.

Il processo ha tre passaggi. Primo, calcola la norma di tutti i gradienti combinati. Secondo, confronta quella norma con la soglia scelta. Terzo, ridimensiona i gradienti se la norma è troppo grande.

La norma è di solito la L2, cioè elevi al quadrato ogni valore di gradiente, li sommi e ne prendi la radice quadrata. Se hai gradienti g_1, g_2, ..., g_n su tutti i parametri del modello, la norma L2 è:

formula del clipping by norm

Formula del clipping by norm

Una volta ottenuta la norma, la confronti con la tua soglia c. Se ||g|| <= c, i gradienti passano invariati. Se ||g|| > c, ogni gradiente viene moltiplicato per il fattore di scala c / ||g||. Questo porta la nuova norma esattamente a c.

Conta perché ogni componente si riduce dello stesso fattore. Le proporzioni relative tra i valori dei gradienti restano invariate, quindi il vettore continua a puntare nella direzione originale. Stai accorciando il passo dell'ottimizzatore, non cambiando la destinazione.

Questa proprietà di conservazione della direzione rende il norm clipping la scelta predefinita. Il clip by value può torcere il vettore gradiente in una nuova direzione. Il clip by norm ne cambia solo la lunghezza.

clip_grad_norm_ di PyTorch e clipnorm di TensorFlow fanno esattamente questo. Quando qualcuno dice "sto usando il gradient clipping", quasi sempre intende il clipping by norm.

Scegliere una soglia per il Gradient Clipping

La soglia è un iperparametro, quindi non esiste un valore universale valido per ogni modello.

Se la imposti troppo in alto, il clipping quasi non si attiva mai. I gradienti restano quasi sempre sotto il limite, quindi la rete di sicurezza non cattura nulla. L'addestramento procede come se il clipping non ci fosse e vedrai comunque picchi della loss quando i gradienti esplodono.

Se la imposti troppo in basso, fai clipping troppo aggressivo. Ogni batch subisce una riduzione dei gradienti, rendendo gli aggiornamenti dei pesi più piccoli del dovuto. L'apprendimento rallenta e il modello impiega più tempo a convergere, a volte molto di più.

Un punto di partenza comune è 1.0, che funziona bene per molte architetture. Valori tra 0.5 e 5.0 coprono la maggior parte dei casi pratici.

L'approccio migliore è monitorare le norme dei gradienti durante l'addestramento. Registra la norma non tagliata a ogni step e osserva la distribuzione. Se la maggior parte delle norme è intorno a 0.3 con picchi occasionali a 50, imposta la soglia sopra l'intervallo tipico ma ben sotto i picchi: 2.0 o 3.0 sarebbero ragionevoli qui.

Trattala come qualsiasi altro iperparametro. Parti da 1.0, osserva cosa succede e aggiusta in base al comportamento del training.

Gradient Clipping nelle reti neurali ricorrenti

Gli RNN sono il contesto in cui il gradient clipping è diventato una tecnica standard.

Il motivo è come gli RNN propagano i gradienti nel tempo. La backpropagation through time moltiplica le stesse matrici di pesi su molti passi temporali, e queste moltiplicazioni ripetute possono accumularsi in valori enormi. Sequenze lunghe peggiorano il problema.

LSTM e GRU hanno ridotto il problema con i loro meccanismi di gating, ma non lo hanno eliminato. Entrambe le architetture traggono ancora beneficio dal clipping, soprattutto con sequenze lunghe o learning rate elevati.

Per l'addestramento RNN, il clip by norm con una soglia tra 1.0 e 5.0 è l'impostazione tipica. Se usi nn.LSTM o nn.GRU di PyTorch e la tua loss esplode durante l'addestramento, aggiungere clip_grad_norm_ è di solito la prima cosa da provare.

Gradient Clipping nel deep learning moderno

Il gradient clipping non è scomparso quando i transformer hanno sostituito gli RNN.

Grandi modelli linguistici come GPT e BERT usano il clipping durante il pretraining e il fine-tuning. Lo stesso vale per i vision transformer, i modelli di diffusione e la maggior parte delle architetture profonde con centinaia di layer. Gli ottimizzatori Adam e AdamW, che dominano il training moderno, sono spesso abbinati al norm clipping con soglie intorno a 1.0.

Il motivo è lo stesso degli RNN. Le reti profonde moltiplicano i gradienti su molti layer, e batch di grandi dimensioni combinati con learning rate alti possono produrre picchi occasionali dei gradienti. Il clipping gestisce quei picchi senza influenzare i normali step di training.

La maggior parte delle implementazioni di riferimento include il clipping di default. Il Trainer di Hugging Face, PyTorch Lightning e DeepSpeed espongono tutti il clipping come opzione standard di configurazione. Se stai addestrando qualcosa di più grande di un piccolo modello di prova, il clipping fa quasi certamente parte della pipeline.

È un'aggiunta di una riga che costa quasi nulla e impedisce che le esecuzioni di training vadano in crash dopo ore di calcolo. Ecco perché è rimasto.

Gradient Clipping in PyTorch

PyTorch gestisce il gradient clipping con un'unica funzione di utilità: torch.nn.utils.clip_grad_norm_.

La chiamata al clipping va tra loss.backward() e optimizer.step(). Prima la backpropagation deve riempire i gradienti, poi il clipping li riduce se necessario, quindi l'ottimizzatore applica l'aggiornamento. Mettere la chiamata altrove non funziona.

Ecco uno script di training completo ed eseguibile che addestra una piccola MLP su dati sintetici di regressione con gradient clipping attivo:

import torch
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset

torch.manual_seed(42)

# Synthetic regression data
n_samples = 1000
n_features = 20
inputs = torch.randn(n_samples, n_features)
targets = (inputs.sum(dim=1, keepdim=True) * 2.0 + torch.randn(n_samples, 1) * 0.1)

dataset = TensorDataset(inputs, targets)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)

# Small feedforward network
model = nn.Sequential(
    nn.Linear(n_features, 64),
    nn.ReLU(),
    nn.Linear(64, 64),
    nn.ReLU(),
    nn.Linear(64, 1),
)

optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
loss_fn = nn.MSELoss()

# Training loop with gradient clipping
n_epochs = 5
max_grad_norm = 1.0

for epoch in range(n_epochs):
    epoch_loss = 0.0
    for batch_inputs, batch_targets in dataloader:
        optimizer.zero_grad()

        predictions = model(batch_inputs)
        loss = loss_fn(predictions, batch_targets)
        loss.backward()

        # Gradient clipping
        torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=max_grad_norm)

        optimizer.step()
        epoch_loss += loss.item()

    print(f"Epoch {epoch + 1}: loss = {epoch_loss / len(dataloader):.4f}")

Output PyTorch

Output PyTorch

La funzione clip_grad_norm_ accetta due argomenti principali:

  • parameters: i parametri del modello i cui gradienti vuoi tagliare. Passa model.parameters() per coprire l'intero modello.

  • max_norm: la soglia per la norma del gradiente. Un valore di 1.0 è un punto di partenza comune.

C'è un argomento opzionale norm_type che di default è 2.0 per la norma L2. Raramente avrai bisogno di cambiarlo.

L'underscore finale in clip_grad_norm_ indica un'operazione in-place. La funzione modifica direttamente i gradienti all'interno dell'attributo .grad di ciascun parametro, quindi non devi tenere traccia del valore di ritorno. Restituisce comunque la norma totale dei gradienti prima del clipping, utile se vuoi registrarla.

Per il clip-by-value invece del clip-by-norm, PyTorch offre torch.nn.utils.clip_grad_value_:

torch.nn.utils.clip_grad_value_(model.parameters(), clip_value=0.5)

Ma come detto prima, lo userai raramente (se mai).

Questo è tutto il setup. Due righe aggiunte al tuo training loop.

Gradient Clipping in TensorFlow

TensorFlow gestisce il clipping a livello di ottimizzatore anziché come chiamata separata.

Quando crei un ottimizzatore, passi clipnorm o clipvalue come argomento. L'ottimizzatore applica internamente il clipping a ogni step, quindi non devi modificare affatto il training loop.

Ecco un esempio completo funzionante con le API Keras su dati sintetici di regressione:

import numpy as np
import tensorflow as tf

tf.random.set_seed(42)
np.random.seed(42)

# Synthetic regression data
n_samples = 1000
n_features = 20
x_train = np.random.randn(n_samples, n_features).astype(np.float32)
y_train = (x_train.sum(axis=1, keepdims=True) * 2.0
           + np.random.randn(n_samples, 1).astype(np.float32) * 0.1)

# Small feedforward network
model = tf.keras.Sequential([
    tf.keras.layers.Dense(64, activation="relu", input_shape=(n_features,)),
    tf.keras.layers.Dense(64, activation="relu"),
    tf.keras.layers.Dense(1),
])

# Optimizer with gradient clipping by norm
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3, clipnorm=1.0)

model.compile(optimizer=optimizer, loss="mse")
model.fit(x_train, y_train, epochs=5, batch_size=32)

Output TensorFlow

I due argomenti fanno cose diverse:

  • clipnorm taglia in base alla norma L2 di ciascun tensore di gradiente. Se la norma supera la soglia, il tensore viene ridimensionato proporzionalmente.

  • clipvalue taglia individualmente ciascun elemento del gradiente. Qualsiasi valore sopra la soglia viene bloccato alla soglia e qualsiasi valore sotto la soglia negativa viene bloccato alla soglia negativa.

Per passare dal norm clipping al value clipping, basta sostituire l'argomento:

optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3, clipvalue=0.5)

Entrambi gli argomenti funzionano con ogni ottimizzatore Keras: Adam, SGD, RMSprop, AdamW e gli altri. C'è anche un argomento global_clipnorm che taglia in base alla norma calcolata su tutti i gradienti combinati, invece che per tensore. Questo rispecchia più da vicino il comportamento predefinito di PyTorch.

Se stai scrivendo un training loop personalizzato con tf.GradientTape, l'ottimizzatore gestisce comunque il clipping quando chiami apply_gradients:

for epoch in range(5):
    for batch_x, batch_y in zip(np.array_split(x_train, 32), np.array_split(y_train, 32)):
        with tf.GradientTape() as tape:
            predictions = model(batch_x, training=True)
            loss = tf.reduce_mean(tf.square(predictions - batch_y))

        gradients = tape.gradient(loss, model.trainable_variables)
        optimizer.apply_gradients(zip(gradients, model.trainable_variables))

Questa è la differenza tra i due framework. PyTorch mette il clipping nelle tue mani, dentro il loop. TensorFlow lo integra nell'ottimizzatore. La logica di base è identica.

Gradient Clipping vs altre tecniche di stabilizzazione

Il gradient clipping non è l'unico modo per stabilizzare l'addestramento, e non è sempre lo strumento giusto.

Altre tecniche affrontano problemi correlati ma diversi. Alcune impediscono ai gradienti di crescere troppo in partenza, altre evitano che scompaiano, e alcune rendono semplicemente la superficie di loss più facile da ottimizzare. Ecco un paio di tecniche diverse.

Batch normalization

La batch normalization normalizza le attivazioni all'interno di ogni mini-batch durante l'addestramento.

Mantiene le uscite dei layer in un intervallo stabile, rendendo le ampiezze dei gradienti più prevedibili. Le reti addestrate con batch norm tollerano learning rate più alti e convergono più velocemente, e sono meno sensibili alle scelte di inizializzazione dei pesi.

Ma la batch norm non ferma direttamente le esplosioni dei gradienti. Riduce la frequenza con cui accadono, non cosa fare quando si verificano. Per questo molti modelli abbinate la batch norm al gradient clipping.

Connessioni residuali

Le connessioni residuali aggiungono scorciatoie che saltano uno o più layer, permettendo ai gradienti di fluire direttamente dai layer successivi a quelli precedenti.

Questo risolve il problema dei vanishing gradients nelle reti profonde. Senza connessioni residuali, addestrare reti con più di 20-30 layer diventa difficile perché i gradienti si riducono verso zero mentre si propagano all'indietro. Con esse, reti con centinaia di layer si addestrano senza problemi.

Le connessioni residuali mirano al lato opposto del problema rispetto al clipping. Il clipping gestisce gradienti troppo grandi. Le residual gestiscono gradienti troppo piccoli.

Inizializzazione attenta dei pesi

I valori iniziali dei pesi determinano l'ampiezza iniziale di attivazioni e gradienti. Una cattiva inizializzazione può causare exploding o vanishing gradients fin dal primo step.

Metodi come l'inizializzazione di Xavier e di He scalano i pesi iniziali in base alla dimensione del layer. Questo mantiene stabili le varianze delle attivazioni tra i layer all'inizio del training, prevenendo molti problemi di gradiente prima che si verifichino.

Una buona inizializzazione riduce la probabilità che ti serva il clipping, ma non la elimina. Picchi di gradiente possono comunque comparire più avanti nell'addestramento, soprattutto con learning rate alti o batch insoliti.

Come si combinano

Queste tecniche non sono alternative. Sono strumenti complementari che risolvono parti diverse dello stesso problema generale.

Un setup di training moderno tipico usa un'attenta inizializzazione all'avvio, connessioni residuali nell'architettura, batch normalization (o layer normalization) all'interno della rete e gradient clipping come rete di sicurezza durante l'ottimizzazione. Ognuna gestisce una specifica modalità di fallimento e insieme rendono addestrabili le reti profonde.

Conclusione

Il gradient clipping è una delle correzioni più semplici nel deep learning, e risolve un problema che può mandare in fumo ore di training in un solo step.

La buona notizia è che non devi cambiare l'architettura del modello né riscrivere il codice di training. Una riga in PyTorch o un argomento in TensorFlow sono sufficienti per implementare il gradient clipping.

Funziona al meglio come parte di un setup più ampio. Abbinalo a un'attenta inizializzazione dei pesi, connessioni residuali e batch o layer normalization, e avrai una pipeline di training che gestisce l'instabilità da più angolazioni.

Se la tua loss esplode, inizia dal clipping. Se scompare, cerca altrove. E se stai addestrando qualcosa di più grande di un piccolo modello, aggiungi il clipping alla pipeline di default e dimenticatene.

Il gradient clipping è solo uno dei tanti termini che ogni machine learning engineer deve conoscere. Se vuoi imparare gli altri e prepararti per il lavoro nel 2026, iscriviti oggi al nostro percorso Machine Learning Engineer.


Dario Radečić's photo
Author
Dario Radečić
LinkedIn
Senior Data Scientist con base in Croazia. Top Tech Writer con oltre 700 articoli pubblicati, per più di 10 milioni di visualizzazioni. Autore del libro Machine Learning Automation with TPOT.

Gradient Clipping: domande frequenti

Che cos'è il gradient clipping nel deep learning?

Il gradient clipping è una tecnica che limita la dimensione dei gradienti durante l'addestramento delle reti neurali per prevenire aggiornamenti dei parametri instabili. Quando i gradienti crescono troppo durante la backpropagation, l'ottimizzatore compie passi enormi che spingono i pesi in regioni problematiche e fanno esplodere la loss. Il clipping limita l'ampiezza del gradiente prima dello step dell'ottimizzatore, così gli aggiornamenti restano entro limiti anche quando i gradienti grezzi hanno picchi.

Quando dovrei usare il gradient clipping?

Usa il gradient clipping ogni volta che il training è instabile, soprattutto se vedi picchi improvvisi della loss, valori NaN o divergenza dopo ore di addestramento. È pratica standard per reti ricorrenti come LSTM e GRU, e per qualsiasi architettura profonda addestrata con learning rate elevati. Se la curva della loss è in ordine, puoi evitarlo, ma aggiungerlo come rete di sicurezza non fa male.

Qual è la differenza tra clip by value e clip by norm?

Il clip by value limita individualmente ciascun elemento del gradiente, il che può cambiare la direzione del vettore gradiente. Il clip by norm ridimensiona l'intero vettore quando la sua ampiezza complessiva supera una soglia, preservando la direzione originale mentre accorcia il passo. Il clip by norm è la scelta standard nel deep learning moderno perché non distorce la direzione dell'aggiornamento.

Come scelgo una buona soglia di gradient clipping?

Parti da 1.0 e aggiusta in base a ciò che osservi durante l'addestramento. Registra le norme dei gradienti non tagliati sui batch e osserva la distribuzione. Imposta la soglia sopra l'intervallo tipico delle norme ma ben al di sotto dei picchi che vuoi intercettare. Se la imposti troppo alta, il clipping non si attiva mai; se troppo bassa, rallenterai inutilmente l'apprendimento.

Il gradient clipping risolve anche i vanishing gradients?

No. Il gradient clipping affronta solo gli exploding gradients, quando i valori crescono troppo. I vanishing gradients sono il problema opposto, quando i valori si riducono verso zero e l'apprendimento si blocca. Per i vanishing gradients usa una migliore inizializzazione dei pesi, connessioni residuali, batch normalization o architetture come LSTM e GRU.

Argomenti

Impara con DataCamp

Programma

Scienziato specializzato in apprendimento automatico in Python

85 h
Scopri il machine learning con Python e prova a diventare uno scienziato del machine learning. Scopri l'apprendimento supervisionato, non supervisionato e profondo.
Vedi dettagliRight Arrow
Inizia Il Corso
Mostra altroRight Arrow