Hoppa till huvudinnehållet

Gradient Clipping: Så förhindrar du exploderande gradienter

Gradient clipping är en justering på en rad i träningsslingan som förhindrar att exploderande gradienter förstör träningen av djupa neurala nätverk. Den här guiden förklarar hur det fungerar, de två huvudsakliga klippningsmetoderna, hur du väljer tröskel och implementering i PyTorch och TensorFlow.
Uppdaterad 10 juni 2026  · 13 min läsa

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.

  1. 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.
  2. 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.
  3. 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.
  4. 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å gradient clipping med clip by value

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å gradient clipping med clip by norm

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

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

PyTorch-utdata

Funktionen clip_grad_norm_ tar två huvudargument:

  • parameters: de modellparametrar vars gradienter du vill klippa. Skicka in model.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:

  • clipnorm klipper efter L2-normen för varje gradienttensor. Om normen överskrider tröskeln skalas tensorn ned proportionellt.

  • clipvalue klipper 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.

Ämnen

Lär dig med DataCamp

track

Maskininlärningsforskare i Python

85 timmar
Upptäck maskininlärning med Python och arbeta mot att bli en maskininlärningsforskare. Utforska övervakad, oövervakad och djupinlärning.
Se detaljerRight Arrow
Starta kursen
Se merRight Arrow