track
Hur många gånger har du sett ett NaN-värde för förlusten när du tränar ett djupt neuralt nätverk?
Efter timtal av träning ser förlustkurvan frisk ut, och sedan sticker den plötsligt iväg mot oändligheten. Orsaken är oftast exploderande gradienter – gradientvärden som blir så stora under backpropagering att parameteruppdateringarna blir instabila och modellen havererar. Problemet drabbar återkommande nätverk hårdast, men dyker även upp i transformers och djupa feedforward-nätverk.
Gradient clipping löser detta genom att begränsa gradienternas storlek innan de når optimeraren. Det är ett tillskott på en enda rad i din träningsslinga som håller uppdateringarna begränsade utan att du behöver ändra modellen.
I den här artikeln går jag igenom intuitionen bakom gradient clipping, de två huvudsakliga metoderna, hur du väljer en tröskel och hur du implementerar det i PyTorch och TensorFlow.
Men vad exakt är förlust inom data science? Läs vårt Loss Function in Machine Learning-inlägg för att ta reda på det.
Vad är Gradient Clipping?
Gradient clipping är en teknik som begränsar gradienternas magnitud under träning för att förhindra instabila parameteruppdateringar.
När en gradient blir för stor tar optimeraren ett enormt steg i parameterutrymmet och skjuter vikterna in i en region där förlusten exploderar. Clipping hjälper till genom att sätta ett tak på steglängden innan den kan orsaka skada.
Det är viktigt att notera att gradient clipping inte påverkar modellarkitekturen. Du lägger inte till lager eller byter aktiveringsfunktioner. Det modifierar bara träningsprocessen genom att fånga upp gradienter mellan backpropagering och optimerarsteg.
Det gör det billigt att prova och enkelt att ta bort. Som du kommer att se senare, det kräver bara en rad kod.
Hur Gradient Clipping fungerar
Mekaniken är enkel. Clipping-operationen placeras mellan din bakåtpassage och ditt optimerarsteg och följer samma fyra steg i varje iteration.
- Beräkna gradienter: Kör framåtpassagen, beräkna förlusten och kör backpropagering. Inget förändras här – gradienterna flödar genom nätverket som vanligt.
- Kontrollera gradienternas storlek: Mät hur stora gradienterna är. Beroende på metod innebär det att titta på individuella värden eller beräkna den övergripande normen över alla parametrar.
- Minska gradienter om de överskrider en tröskel: Om magnituden passerar gränsen du satt, skala ned gradienterna. Om inte, lämna dem oförändrade.
- Uppdatera modellparametrar: Skicka de klippta gradienterna till optimeraren och applicera viktuppdateringen.
För det mesta håller sig gradienterna under tröskeln och träningen fortskrider som utan gradient clipping. När en spike inträffar fångar clipping den innan optimeraren hinner reagera.
Det är allt.
Vanliga metoder för Gradient Clipping
Det finns två sätt att klippa gradienter, och skillnaden handlar om vad du mäter och vad du skalar.
Clip by value
Clip by value sätter ett individuellt tak för varje enskilt gradientelement.
Du väljer ett intervall, säg [-1.0, 1.0], och alla gradientvärden utanför intervallet avrundas till närmaste gräns. En gradient på 2.5 blir 1.0. En gradient på -2.5 blir -1.0. Värden som redan ligger inom intervallet förblir oförändrade.

Exempel på clip by value
Styrkan är enkelheten. Det krävs ingen matematik bortom en min-/max-operation, och det går snabbt att köra.
Men den här metoden har en nackdel. Att klippa individuella värden ändrar riktningen på gradientvektorn. Om en komponent klipps och de andra inte, pekar den uppdaterade vektorn inte längre dit backpropageringen angav. Din optimerare tar då ett steg i en något felaktig riktning.
Därför är clip by value mindre vanligt i praktiken.
Clip by norm
Clip by norm skalar hela gradientvektorn när dess totala magnitud överskrider en tröskel.
I stället för att titta på individuella värden beräknar den normen för alla gradienter tillsammans (vanligen L2-normen) och jämför den med ett maxvärde. Om normen ligger under tröskeln händer inget. Om den ligger över multipliceras varje gradient med samma skalfaktor för att få tillbaka normen till gränsvärdet.

Exempel på clip by norm
Fördelen är att riktningen bevaras. Eftersom varje komponent krymper med samma faktor pekar gradientvektorn fortfarande i ursprungsriktningen. Du förkortar bara steget, du ändrar inte riktningen.
Det är därför clip by norm har blivit standard. PyTorchs clip_grad_norm_ och TensorFlows clipnorm implementerar båda denna metod, och de flesta moderna träningspipelines använder den som standard.
Exploderande gradienter vs försvinnande gradienter
Exploderande och försvinnande gradienter är båda vanliga problem inom deep learning, men bara det ena löses med gradient clipping.
Exploderande gradienter
Exploderande gradienter uppstår när gradientvärden blir för stora under backpropagering.
Detta visar sig vanligtvis i djupa nätverk eller återkommande arkitekturer, där gradienter multipliceras över många lager eller tidssteg. Om de multiplikationerna samverkar åt fel håll blåser gradientmagnituden upp. Optimeraren gör då en enorm parameteruppdatering, vikter hoppar till extrema värden och förlusten blir ofta NaN eller Inf.
Du ser det som plötsliga spikar i förlusten eller en modell som divergerar utan förvarning.
Försvinnande gradienter
Försvinnande gradienter är motsatt problem. Gradientvärdena krymper mot noll när de propageras bakåt genom nätverket.
När gradienterna blir för små blir viktuppdateringarna minimala. Tidiga lager slutar lära sig, djupare lager lär långsamt och träningen stannar i praktiken. Förlustkurvan planar ut och förbättras inte, även efter många epoker.
Detta var huvudskälet till att RNN:er hade svårt med långa sekvenser innan LSTM:er och GRU:er kom.
Var gradient clipping passar in
Gradient clipping adresserar exploderande gradienter, inte försvinnande gradienter.
Clipping krymper gradienter som är för stora, men gör inget när gradienterna är för små. För försvinnande gradienter behöver du bättre viktinitialisering, residualkopplingar, batchnormalisering eller arkitekturer som bevarar gradientflödet.
Gradient Clipping by Norm förklarat
Clipping by norm är den metod de flesta egentligen söker efter när de letar efter gradient clipping.
Processen har tre steg. Först beräknar du normen för alla gradienter tillsammans. Sedan jämför du den normen med din valda tröskel. Slutligen, om normen är för stor, skalas gradienterna om.
Normen är vanligtvis L2-normen, vilket innebär att du kvadrerar varje gradientvärde, summerar dem och tar kvadratroten. Om du har gradienter g_1, g_2, ..., g_n över alla modellparametrar är L2-normen:

Formel för clipping by norm
När du har normen jämför du den med din tröskel c. Om ||g|| <= c passerar gradienterna oförändrade. Om ||g|| > c multipliceras varje gradient med skalfaktorn c / ||g||. Detta sänker den nya normen till exakt c.
Detta är viktigt eftersom varje komponent krymper med samma faktor. De relativa proportionerna mellan gradientvärdena förblir oförändrade, vilket betyder att vektorn fortfarande pekar i ursprungsriktningen. Du förkortar steget optimeraren tar, inte ändrar vart det går.
Denna egenskap att bevara riktningen är det som gör normklippning till förstahandsvalet. Clip by value kan vrida gradientvektorn i en ny riktning. Clip by norm ändrar bara dess längd.
PyTorchs clip_grad_norm_ och TensorFlows clipnorm gör exakt detta. När någon säger "jag använder gradient clipping" menar de nästan alltid klippning efter norm.
Att välja en tröskel för Gradient Clipping
Tröskeln är en hyperparameter, vilket betyder att det inte finns något universellt värde som fungerar för varje modell.
Om du sätter den för högt aktiveras klippningen nästan aldrig. Dina gradienter ligger nästan alltid under gränsen, så skyddsnätet fångar inget. Träningen fortgår som om klippning inte fanns, och du ser fortfarande spikar i förlusten när gradienter exploderar.
Om du sätter den för lågt klipper du för aggressivt. Varje batch får sina gradienter krympta, vilket gör viktuppdateringarna mindre än de borde vara. Inlärningen saktar ned och din modell tar längre tid att konvergera, ibland mycket längre.
En vanlig startpunkt är 1.0, vilket fungerar bra för många arkitekturer. Värden mellan 0.5 och 5.0 täcker de flesta praktiska användningsfall.
Det bättre tillvägagångssättet är att övervaka dina gradientnormer under träningen. Logga den oklippta normen vid varje steg och titta på fördelningen. Om de flesta normer ligger runt 0.3 med enstaka spikar upp till 50, sätt tröskeln någonstans över det typiska intervallet men långt under spikarna – 2.0 eller 3.0 vore rimligt här.
Behandla den som vilken hyperparameter som helst. Börja med 1.0, se vad som händer och justera baserat på träningsbeteendet.
Gradient Clipping i återkommande neurala nätverk
RNN:er är där gradient clipping först blev en standardteknik.
Anledningen är hur RNN:er propagerar gradienter genom tiden. Backpropagation through time multiplicerar samma viktmatriser över många tidssteg, och dessa upprepade multiplikationer kan samverka till enorma värden. Långa sekvenser förvärrar problemet.
LSTM:er och GRU:er minskade problemet med sina grindmekanismer, men de eliminerade det inte. Båda arkitekturerna gynnas fortfarande av klippning, särskilt vid träning på långa sekvenser eller med höga inlärningstakter.
För RNN-träning är clip by norm med en tröskel mellan 1.0 och 5.0 det typiska standardvalet. Om du använder PyTorchs nn.LSTM eller nn.GRU och din förlust exploderar under träning, är det oftast första steget att lägga till clip_grad_norm_.
Gradient Clipping i modern deep learning
Gradient clipping försvann aldrig när transformers ersatte RNN:er.
Stora språkmodeller som GPT och BERT använder klippning under förträning och finjustering. Detsamma gäller vision transformers, diffusionsmodeller och de flesta djupa arkitekturer med hundratals lager. Optimerarna Adam och AdamW, som dominerar modern träning, paras ofta med normklippning vid trösklar runt 1.0.
Anledningen är densamma som för RNN:er. Djupa nätverk multiplicerar gradienter över många lager, och stora batchstorlekar i kombination med höga inlärningstakter kan ge upphov till enstaka gradientspikar. Klippning hanterar dessa spikar utan att påverka normala träningssteg.
De flesta referensimplementationer inkluderar klippning som standard. Hugging Faces Trainer, PyTorch Lightning och DeepSpeed exponerar alla klippning som en standardkonfigurationsinställning. Om du tränar något större än en liten leksaksmodell är klippning nästan säkert en del av pipelinen.
Det är ett tillägg på en rad som kostar nästan inget och förhindrar att träningskörningar kraschar efter timtal av beräkningar. Det är därför det har stannat kvar.
Gradient Clipping i PyTorch
PyTorch hanterar gradient clipping med en enda hjälpfunktion: torch.nn.utils.clip_grad_norm_.
Klippningsanropet kommer mellan loss.backward() och optimizer.step(). Backpropageringen måste fylla i gradienterna först, sedan krymper klippningen dem vid behov och därefter applicerar optimeraren uppdateringen. Att lägga anropet någon annanstans fungerar inte.
Här är ett komplett, körbart träningsskript som tränar ett litet MLP på syntetiska regressionsdata med gradient clipping aktiverat:
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}")

PyTorch-utdata
Funktionen clip_grad_norm_ tar två huvudargument:
-
parameters: de modellparametrar vars gradienter du vill klippa. Skicka inmodel.parameters()för att täcka hela modellen. -
max_norm: tröskeln för gradientnormen. Ett värde på1.0är en vanlig startpunkt.
Det finns ett valfritt argument norm_type som är 2.0 som standard för L2-norm. Du behöver sällan ändra det.
Understrecket i clip_grad_norm_ signalerar en in-place-operation. Funktionen modifierar gradienterna direkt i attributet .grad för varje parameter, så du behöver inte hålla reda på returvärdet. Den returnerar den totala normen för gradienterna före klippning, vilket är praktiskt om du vill logga den.
För clip-by-value i stället för clip-by-norm har PyTorch torch.nn.utils.clip_grad_value_:
torch.nn.utils.clip_grad_value_(model.parameters(), clip_value=0.5)
Men som nämnts tidigare kommer du sällan (om någonsin) att använda denna implementation.
Det är hela upplägget. Två rader tillagda i din träningsslinga.
Gradient Clipping i TensorFlow
TensorFlow hanterar klippning på optimerarnivå snarare än som ett separat funktionsanrop.
När du skapar en optimerare skickar du clipnorm eller clipvalue som argument. Optimeraren applicerar klippning internt vid varje steg, så du behöver inte ändra din träningsslinga alls.
Här är ett komplett fungerande exempel med Keras-API:t på syntetiska regressionsdata:
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)

TensorFlow-utdata
De två argumenten gör olika saker:
-
clipnormklipper efter L2-normen för varje gradienttensor. Om normen överskrider tröskeln skalas tensorn ned proportionellt. -
clipvalueklipper varje gradientelement individuellt. Alla värden över tröskeln kläms till tröskeln, och alla värden under den negativa tröskeln kläms till den negativa tröskeln.
För att byta från normklippning till värdesklippning byter du bara argument:
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3, clipvalue=0.5)
Båda argumenten fungerar med varje Keras-optimerare: Adam, SGD, RMSprop, AdamW och resten. Det finns också ett global_clipnorm-argument som klipper baserat på normen beräknad över alla gradienter tillsammans, snarare än per tensor. Detta matchar PyTorchs standardbeteende bättre.
Om du skriver en anpassad träningsslinga med tf.GradientTape hanterar optimeraren fortfarande klippning när du anropar 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))
Det är skillnaden mellan de två ramverken. PyTorch lägger klippningen i dina händer inuti loopen. TensorFlow flyttar in den i själva optimeraren. Den underliggande logiken är identisk.
Gradient Clipping vs andra stabiliseringstekniker
Gradient clipping är inte det enda sättet att stabilisera träningen, och det är inte alltid rätt verktyg för uppgiften.
Andra tekniker hanterar relaterade men olika problem. Vissa förhindrar att gradienter blir för stora från början, andra hindrar dem från att försvinna, och vissa gör helt enkelt förlustytan lättare att optimera. Låt mig visa ett par olika tekniker.
Batchnormalisering
Batchnormalisering normaliserar aktiveringar inom varje minibatch under träning.
Den håller lagerutgångar inom ett stabilt intervall, vilket gör gradientmagnituder mer förutsägbara. Nätverk som tränas med batchnorm tål högre inlärningstakter och konvergerar snabbare, och de är mindre känsliga för val av viktinitialisering.
Men batchnorm stoppar inte direkt gradientexplosioner. Den minskar hur ofta de uppstår, inte vad man gör när de sker. Många modeller kombinerar därför batchnorm med gradient clipping.
Residualkopplingar
Residualkopplingar lägger till genvägar som hoppar över ett eller flera lager och låter gradienter flöda direkt från senare lager till tidigare.
Det löser problemet med försvinnande gradienter i djupa nätverk. Utan residualkopplingar blir det svårt att träna nätverk med mer än 20–30 lager eftersom gradienterna krymper mot noll när de propageras bakåt. Med dem kan nätverk med hundratals lager tränas utan problem.
Residualkopplingar riktar in sig på motsatt ände av gradientproblemet jämfört med klippning. Klippning hanterar gradienter som är för stora. Residualer hanterar gradienter som blir för små.
Omsorgsfull viktinitialisering
Dina vikters startvärden sätter den initiala magnituden på aktiveringar och gradienter. Dålig initialisering kan orsaka att gradienter exploderar eller försvinner redan från första steget.
Metoder som Xavier- och He-initialisering skalar initiala vikter baserat på lagerstorlek. Detta håller aktiveringsvarianser stabila över lager i början av träningen, vilket förebygger många gradientproblem innan de uppstår.
Bra initialisering minskar chansen att du behöver klippning, men eliminerar den inte. Gradientspikar kan fortfarande dyka upp senare i träningen, särskilt med höga inlärningstakter eller ovanliga batchar.
Hur de passar ihop
Dessa tekniker jag listade är inte alternativ. De är kompletterande verktyg som löser olika delar av samma övergripande problem.
Ett typiskt modernt träningsupplägg använder omsorgsfull initialisering från start, residualkopplingar i arkitekturen, batchnormalisering (eller layer normalization) i nätverket och gradient clipping som ett skyddsnät under optimeringen. Var och en hanterar ett specifikt felbeteende, och tillsammans gör de djupa nätverk träningsbara.
Slutsats
Gradient clipping är en av de enklaste åtgärderna inom deep learning, och den löser ett problem som kan förstöra timmar av träning på ett enda steg.
Det fina är att du inte behöver ändra din modellarkitektur eller skriva om din träningskod. En rad i PyTorch eller ett argument i TensorFlow räcker för att implementera gradient clipping.
Det fungerar bäst som en del av ett större upplägg. Kombinera det med omsorgsfull viktinitialisering, residualkopplingar och batch- eller layer-normalisering, så får du en träningspipeline som hanterar instabilitet från flera håll.
Om din förlust exploderar, börja med klippning. Om den försvinner, titta någon annanstans. Och om du tränar något större än en liten modell, lägg till klippning i din pipeline som standard och glöm den sedan.
Gradient clipping är bara ett av många begrepp som varje machine learning-ingenjör måste kunna. Om du vill lära dig de andra och bli jobbklar 2026, anmäl dig till vårt Machine Learning Engineer-spår redan idag.
Gradient Clipping – vanliga frågor
Vad är gradient clipping inom deep learning?
Gradient clipping är en teknik som begränsar gradienternas storlek under träning av neurala nätverk för att förhindra instabila parameteruppdateringar. När gradienter blir för stora under backpropagering tar optimeraren enorma steg som skjuter vikter in i dåliga regioner och får förlusten att explodera. Klippning sätter ett tak på gradientmagnituden före optimerarsteget, så uppdateringarna förblir begränsade även när de råa gradienterna spikar.
När ska jag använda gradient clipping?
Använd gradient clipping när din träning är instabil, särskilt om du ser plötsliga spikar i förlusten, NaN-värden eller divergens efter timtal av träning. Det är standardpraxis för återkommande nätverk som LSTM:er och GRU:er och alla djupa arkitekturer som tränas med höga inlärningstakter. Om din förlustkurva ser frisk ut kan du hoppa över det, men att lägga till det som ett skyddsnät skadar inte.
Vad är skillnaden mellan clip by value och clip by norm?
Clip by value sätter ett individuellt tak för varje gradientelement, vilket kan ändra riktningen på gradientvektorn. Clip by norm skalar hela vektorn när dess totala magnitud överskrider en tröskel, vilket bevarar den ursprungliga riktningen samtidigt som steget förkortas. Clip by norm är standardvalet i modern deep learning eftersom det inte snedvrider uppdateringsriktningen.
Hur väljer jag en bra tröskel för gradient clipping?
Börja med 1.0 och justera baserat på vad du ser under träningen. Logga dina oklippta gradientnormer över batchar och titta på fördelningen. Sätt tröskeln över det typiska normintervallet men långt under de spikar du vill fånga. När den sätts för högt aktiveras klippningen aldrig, och när den sätts för lågt saktar du i onödan ned inlärningen.
Löser gradient clipping även försvinnande gradienter?
Nej. Gradient clipping adresserar bara exploderande gradienter, där värden blir för stora. Försvinnande gradienter är det motsatta problemet, där värden krymper mot noll och inlärningen i praktiken upphör. För försvinnande gradienter använd bättre viktinitialisering, residualkopplingar, batchnormalisering eller arkitekturer som LSTM och GRU.