Track
Ile razy podczas trenowania głębokiej sieci neuronowej widziałeś wartość straty równą NaN?
Po godzinach trenowania krzywa straty wygląda zdrowo, a potem nagle wystrzeliwuje do nieskończoności. Zwykle winne są eksplodujące gradienty — wartości gradientu rosną tak bardzo podczas propagacji wstecznej, że aktualizacje parametrów stają się niestabilne i model się psuje. Problem najmocniej dotyka sieci rekurencyjne, ale pojawia się też w transformerach i głębokich sieciach feedforward.
Gradient clipping naprawia to, ograniczając rozmiar gradientów zanim trafią do optymalizatora. To jednolinijkowy dodatek do pętli trenowania, który utrzymuje aktualizacje w ryzach bez zmian w modelu.
W tym artykule omówię intuicję stojącą za gradient clippingiem, dwa główne podejścia, jak dobrać próg oraz jak zaimplementować je w PyTorch i TensorFlow.
Ale czym właściwie jest strata w data science? Przeczytaj nasz wpis Loss Function in Machine Learning, aby się dowiedzieć.
Czym jest gradient clipping?
Gradient clipping to technika ograniczająca wielkość gradientów podczas trenowania, aby zapobiec niestabilnym aktualizacjom parametrów.
Gdy gradient staje się zbyt duży, optymalizator wykonuje ogromny krok w przestrzeni parametrów i wypycha wagi w obszar, w którym strata eksploduje. Clipping pomaga, ograniczając rozmiar tego kroku, zanim zdąży wyrządzić szkody.
Ważne: gradient clipping nie wpływa na architekturę modelu. Nie dodajesz warstw ani nie zmieniasz funkcji aktywacji. Modyfikuje wyłącznie proces trenowania, przechwytując gradienty między backpropagacją a krokiem optymalizatora.
Dzięki temu łatwo go wypróbować i usunąć. Jak zobaczysz, to dosłownie jedna linijka kodu.
Jak działa gradient clipping
Mechanika jest prosta. Operacja clippingu jest umieszczona między przebiegiem wstecznym a krokiem optymalizatora i co iterację podąża za tymi czterema krokami.
- Oblicz gradienty: Uruchom przebieg w przód, policz stratę i wykonaj propagację wsteczną. Tu nic się nie zmienia — gradienty płyną przez sieć tak jak zawsze.
- Sprawdź wielkość gradientu: Zmierz, jak duże są gradienty. W zależności od metody może to oznaczać spojrzenie na poszczególne wartości lub obliczenie normy łącznej dla wszystkich parametrów.
- Zredukuj gradienty, jeśli przekraczają próg: Jeśli wielkość przekracza ustalony limit, przeskaluj gradienty w dół. Jeśli nie, pozostaw je bez zmian.
- Zaktualizuj parametry modelu: Przekaż przycięte gradienty do optymalizatora i zastosuj aktualizację wag.
Najczęściej gradienty pozostają poniżej progu i trening przebiega tak, jak bez clippingu. Gdy pojawi się skok, clipping wyłapuje go, zanim zareaguje optymalizator.
I to wszystko.
Popularne metody gradient clippingu
Gradienty można przycinać na dwa sposoby, a różnica sprowadza się do tego, co mierzysz i co skalujesz.
Clip by value
Clip by value indywidualnie ogranicza każdy element gradientu.
Wybierasz zakres, np. [-1.0, 1.0], i każda wartość gradientu spoza tego zakresu zostaje zaokrąglona do najbliższej granicy. Gradient 2.5 staje się 1.0. Gradient -2.5 staje się -1.0. Wartości już mieszczące się w zakresie pozostają bez zmian.

Przykład clip by value
Zaletą jest prostota. Poza operacją min/max nie ma tu matematyki, a wykonanie jest szybkie.
Podejście ma jednak wadę. Przycinanie poszczególnych wartości zmienia kierunek wektora gradientu. Jeśli jeden składnik zostanie przycięty, a inne nie, zaktualizowany wektor nie wskazuje już dokładnie tam, gdzie „kazała” propagacja wsteczna. Optymalizator wykona więc krok w nieco złym kierunku.
Dlatego clip by value jest w praktyce rzadszy.
Clip by norm
Clip by norm skaluje cały wektor gradientu, gdy jego ogólna wielkość przekracza próg.
Zamiast patrzeć na poszczególne wartości, liczy normę wszystkich gradientów razem (zwykle normę L2) i porównuje ją z maksymalną wartością. Jeśli norma jest poniżej progu, nic się nie dzieje. Jeśli powyżej, każdy gradient zostaje pomnożony przez ten sam współczynnik skalujący, aby sprowadzić normę do limitu.

Przykład clip by norm
Zaletą jest zachowanie kierunku. Ponieważ każdy składnik kurczy się o ten sam współczynnik, wektor gradientu wciąż wskazuje pierwotny kierunek. Skracasz tylko krok, nie zmieniasz, dokąd zmierza.
Dlatego clip by norm stał się standardem. PyTorchowe clip_grad_norm_ i tensorflowowe clipnorm implementują tę metodę i większość nowoczesnych pipeline’ów szkoleniowych używa jej domyślnie.
Eksplodujące gradienty vs. zanikające gradienty
Eksplodujące i zanikające gradienty to częste problemy w deep learningu, ale tylko jeden z nich rozwiązuje gradient clipping.
Eksplodujące gradienty
Eksplodujące gradienty pojawiają się, gdy wartości gradientu rosną zbyt mocno podczas propagacji wstecznej.
Zwykle widać to w głębokich sieciach lub architekturach rekurencyjnych, gdzie gradienty są mnożone przez wiele warstw lub kroków w czasie. Jeśli te mnożenia kumulują się w „złą stronę”, wielkość gradientu wybucha. Optymalizator wykonuje wtedy ogromną aktualizację, wagi skaczą do skrajnych wartości, a strata często staje się NaN albo Inf.
Zobaczysz to jako nagłe skoki straty lub model, który znikąd zaczyna się rozjeżdżać.
Zanikające gradienty
Zanikające gradienty to problem odwrotny. Wartości gradientu kurczą się do zera, gdy propagują się wstecz przez sieć.
Gdy gradienty są zbyt małe, aktualizacje wag stają się minimalne. Wczesne warstwy przestają się uczyć, głębsze uczą się wolno i trening praktycznie staje. Krzywa straty się spłaszcza i nie poprawia, nawet po wielu epokach.
To był główny powód, dla którego RNN-y miały kłopot z długimi sekwencjami przed pojawieniem się LSTM i GRU.
Gdzie pasuje gradient clipping
Gradient clipping rozwiązuje eksplodujące gradienty, a nie zanikające gradienty.
Clipping zmniejsza gradienty, które są zbyt duże, ale nic nie robi, gdy są zbyt małe. Na zanikające gradienty potrzebujesz lepszej inicjalizacji wag, połączeń resztowych, normalizacji w partiach lub architektur zaprojektowanych do zachowania przepływu gradientu.
Gradient clipping by norm — wyjaśnienie
Clipping by norm to metoda, której większość osób faktycznie szuka, gdy szuka informacji o gradient clippingu.
Proces ma trzy kroki. Po pierwsze, policz normę wszystkich gradientów razem. Po drugie, porównaj tę normę z wybranym progiem. Po trzecie, przeskaluj gradienty, jeśli norma jest zbyt duża.
Normą jest zwykle L2, co oznacza, że podnosisz do kwadratu każdą wartość gradientu, sumujesz je i wyciągasz pierwiastek. Jeśli masz gradienty g_1, g_2, ..., g_n dla wszystkich parametrów modelu, norma L2 to:

Wzór dla clippingu by norm
Gdy masz normę, porównujesz ją z progiem c. Jeśli ||g|| <= c, gradienty przechodzą bez zmian. Jeśli ||g|| > c, każdy gradient jest mnożony przez współczynnik skalujący c / ||g||. To sprowadza nową normę dokładnie do c.
To istotne, bo każdy składnik kurczy się o ten sam współczynnik. Względne proporcje między wartościami gradientów pozostają niezmienione, więc wektor wciąż wskazuje pierwotny kierunek. Skracasz krok optymalizatora, a nie zmieniasz kierunku ruchu.
Ta właściwość zachowania kierunku sprawia, że clipping normy jest wyborem domyślnym. Clip by value może skręcić wektor gradientu w nowy kierunek. Clip by norm zmienia tylko jego długość.
PyTorchowe clip_grad_norm_ i tensorflowowe clipnorm robią dokładnie to. Gdy ktoś mówi „używam gradient clippingu”, zwykle ma na myśli clipping by norm.
Dobór progu gradient clippingu
Próg to hiperparametr, więc nie ma jednej uniwersalnej wartości dobra dla każdego modelu.
Jeśli ustawisz go zbyt wysoko, clipping prawie nigdy się nie uaktywni. Gradienty niemal zawsze pozostaną poniżej limitu, więc siatka bezpieczeństwa niczego nie wychwyci. Trening przebiega jakby clippingu nie było, a przy eksplozji gradientów nadal zobaczysz skoki straty.
Jeśli ustawisz go zbyt nisko, przycinasz zbyt agresywnie. Każda partia ma zmniejszane gradienty, co sprawia, że aktualizacje wag są mniejsze niż powinny. Uczenie zwalnia, a model dłużej się zbiega — czasem znacznie dłużej.
Częsty punkt startowy to 1.0, który sprawdza się w wielu architekturach. Wartości między 0.5 a 5.0 pokrywają większość praktycznych przypadków.
Lepsze podejście to monitorowanie norm gradientów podczas treningu. Loguj nieprzyciętą normę na każdym kroku i spójrz na rozkład. Jeśli większość norm oscyluje wokół 0.3 z okazjonalnymi skokami do 50, ustaw próg powyżej typowego zakresu, ale sporo poniżej skoków — 2.0 lub 3.0 byłyby tu rozsądne.
Traktuj to jak każdy inny hiperparametr. Zacznij od 1.0, obserwuj efekty i dostosuj na podstawie zachowania treningu.
Gradient clipping w rekurencyjnych sieciach neuronowych
RNN-y to miejsce, gdzie gradient clipping stał się standardową techniką.
Powód tkwi w tym, jak RNN-y propagują gradienty w czasie. Backpropagation through time mnoży te same macierze wag przez wiele kroków czasowych, a te powtarzające się mnożenia mogą się skumulować do ogromnych wartości. Długie sekwencje pogarszają problem.
LSTM i GRU ograniczyły ten problem dzięki mechanizmom bramek, ale go nie wyeliminowały. Obie architektury nadal zyskują na clippingu, zwłaszcza przy długich sekwencjach lub wysokich learning rate’ach.
W trenowaniu RNN typowym domyślnym ustawieniem jest clip by norm z progiem między 1.0 a 5.0. Jeśli używasz PyTorchowego nn.LSTM lub nn.GRU i podczas trenowania strata eksploduje, dodanie clip_grad_norm_ to zwykle pierwszy krok do wypróbowania.
Gradient clipping we współczesnym deep learningu
Gradient clipping nie zniknął, gdy transformatory zastąpiły RNN-y.
Duże modele językowe, takie jak GPT i BERT, używają clippingu podczas pretrenowania i strojenia. To samo dotyczy transformerów wizyjnych, modeli dyfuzyjnych i większości głębokich architektur liczących setki warstw. Optymalizatory Adam i AdamW, dominujące we współczesnym trenowaniu, często łączy się z clip by norm przy progach około 1.0.
Powód jest ten sam, co w RNN-ach. Głębokie sieci mnożą gradienty przez wiele warstw, a duże batch size’y w połączeniu z wysokimi learning rate’ami mogą powodować okazjonalne skoki gradientów. Clipping radzi sobie z tymi skokami bez wpływu na normalne kroki treningowe.
Większość implementacji referencyjnych ma clipping domyślnie. Hugging Face Trainer, PyTorch Lightning i DeepSpeed udostępniają clipping jako standardową opcję konfiguracyjną. Jeśli trenujesz coś większego niż mały model-zabawka, clipping niemal na pewno jest częścią pipeline’u.
To jedna linijka, która prawie nic nie kosztuje, a chroni przed zawieszeniem treningu po godzinach liczenia. Dlatego przetrwał.
Gradient clipping w PyTorch
PyTorch obsługuje gradient clipping jedną funkcją pomocniczą: torch.nn.utils.clip_grad_norm_.
Wywołanie clippingu trafia między loss.backward() a optimizer.step(). Backpropagacja musi najpierw wypełnić gradienty, potem clipping je ewentualnie zmniejsza, a na końcu optymalizator stosuje aktualizację. Umieszczenie wywołania gdzie indziej nie zadziała.
Oto kompletny, uruchamialny skrypt treningowy, który trenuje mały MLP na syntetycznych danych regresyjnych z włączonym gradient clippingiem:
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}")

Wynik PyTorch
Funkcja clip_grad_norm_ przyjmuje dwa główne argumenty:
-
parameters: parametry modelu, których gradienty chcesz przycinać. Przekażmodel.parameters(), aby objąć cały model. -
max_norm: próg dla normy gradientu. Wartość1.0to popularny punkt startowy.
Jest też opcjonalny argument norm_type, który domyślnie wynosi 2.0 dla normy L2. Rzadko będziesz musiał go zmieniać.
Podkreślenie na końcu clip_grad_norm_ oznacza operację in-place. Funkcja modyfikuje gradienty bezpośrednio w atrybucie .grad każdego parametru, więc nie musisz śledzić wartości zwrotnej. Zwraca jednak całkowitą normę gradientów przed clippingiem — przydatne, jeśli chcesz ją logować.
Dla clip-by-value zamiast clip-by-norm PyTorch ma torch.nn.utils.clip_grad_value_:
torch.nn.utils.clip_grad_value_(model.parameters(), clip_value=0.5)
Ale jak wspomniano, rzadko (o ile w ogóle) będziesz z tego korzystać.
I to cały setup. Dwie linijki dodane do pętli trenowania.
Gradient clipping w TensorFlow
TensorFlow obsługuje clipping na poziomie optymalizatora, a nie jako osobne wywołanie funkcji.
Tworząc optymalizator, przekazujesz argument clipnorm lub clipvalue. Optymalizator stosuje clipping wewnętrznie na każdym kroku, więc nie musisz modyfikować pętli trenowania.
Oto pełny działający przykład z API Keras na syntetycznych danych regresyjnych:
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)

Wynik TensorFlow
Te dwa argumenty robią różne rzeczy:
-
clipnormprzycina względem normy L2 każdego tensora gradientu. Jeśli norma przekracza próg, tensor jest proporcjonalnie skalowany w dół. -
clipvalueindywidualnie przycina każdy element gradientu. Dowolna wartość powyżej progu jest ograniczana do progu, a poniżej ujemnego progu — do ujemnego progu.
Aby przełączyć się z norm clipping na value clipping, po prostu podmień argument:
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3, clipvalue=0.5)
Oba argumenty działają z każdym optymalizatorem Keras: Adam, SGD, RMSprop, AdamW i pozostałymi. Jest też argument global_clipnorm, który przycina względem normy liczonej łącznie dla wszystkich gradientów, a nie per tensor. To bliżej domyślnego zachowania PyTorcha.
Jeśli piszesz własną pętlę trenowania z tf.GradientTape, optymalizator nadal obsługuje clipping przy wywołaniu 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))
Tym różnią się oba frameworki. PyTorch oddaje clipping w twoje ręce, wewnątrz pętli. TensorFlow przenosi go do samego optymalizatora. Logika w tle jest identyczna.
Gradient clipping vs. inne techniki stabilizacji
Gradient clipping nie jest jedynym sposobem stabilizacji treningu i nie zawsze jest właściwym narzędziem.
Inne techniki rozwiązują pokrewne, ale różne problemy. Jedne zapobiegają nadmiernemu wzrostowi gradientów, inne chronią przed ich zanikiem, a niektóre po prostu wygładzają powierzchnię straty. Oto kilka z nich.
Batch normalization
Batch normalization normalizuje aktywacje w każdej mini-partii podczas trenowania.
Utrzymuje wyjścia warstw w stabilnym zakresie, co czyni wielkości gradientów bardziej przewidywalnymi. Sieci trenowane z batch norm lepiej tolerują wyższe learning rate’y i szybciej się zbiegają, a także są mniej wrażliwe na wybór inicjalizacji wag.
Jednak batch norm nie zatrzymuje wprost eksplozji gradientów. Ogranicza, jak często do nich dochodzi, ale nie mówi, co zrobić, gdy już się pojawią. Dlatego wiele modeli łączy batch norm z gradient clippingiem.
Połączenia resztowe (residual)
Połączenia resztowe dodają skróty omijające jedną lub więcej warstw, pozwalając gradientom płynąć bezpośrednio z późniejszych do wcześniejszych warstw.
To rozwiązuje problem zanikających gradientów w głębokich sieciach. Bez połączeń resztowych trenowanie sieci z ponad 20–30 warstwami jest trudne, bo gradienty kurczą się do zera, propagując się wstecz. Dzięki nim sieci liczące setki warstw trenują bez problemu.
Połączenia resztowe celują w przeciwległy biegun problemu gradientów względem clippingu. Clipping radzi sobie z gradientami zbyt dużymi. Resztowe — z gradientami zbyt małymi.
Uważna inicjalizacja wag
Początkowe wartości wag ustawiają startową wielkość aktywacji i gradientów. Zła inicjalizacja może powodować eksplozje lub zanik gradientów już od pierwszego kroku.
Metody takie jak inicjalizacja Xaviera i He skalują wagi na starcie w zależności od rozmiaru warstwy. Stabilizuje to wariancje aktywacji w warstwach na początku treningu, co zapobiega wielu problemom z gradientami, zanim wystąpią.
Dobra inicjalizacja zmniejsza szansę, że będziesz potrzebować clippingu, ale jej nie eliminuje. Skoki gradientów mogą pojawić się później w trenowaniu, zwłaszcza przy wysokich learning rate’ach lub nietypowych batchach.
Jak to się uzupełnia
Te techniki nie są alternatywami. To komplementarne narzędzia rozwiązujące różne części tego samego problemu.
Typowy nowoczesny setup treningowy używa na starcie uważnej inicjalizacji, połączeń resztowych w architekturze, batch normalization (lub layer normalization) wewnątrz sieci oraz gradient clippingu jako siatki bezpieczeństwa podczas optymalizacji. Każdy element adresuje konkretny tryb awarii, a razem sprawiają, że głębokie sieci da się efektywnie trenować.
Wnioski
Gradient clipping to jedno z najprostszych rozwiązań w deep learningu, a rozwiązuje problem, który potrafi w jednej chwili zaprzepaścić godziny trenowania.
Dobra wiadomość jest taka, że nie musisz zmieniać architektury modelu ani przepisywać kodu treningowego. Jedna linijka w PyTorch lub jeden argument w TensorFlow wystarczy, by wdrożyć gradient clipping.
Najlepiej działa jako część większego zestawu. Połącz go z uważną inicjalizacją wag, połączeniami resztowymi oraz batch lub layer normalization, a zbudujesz pipeline treningowy odporny na niestabilność z wielu stron.
Jeśli twoja strata eksploduje, zacznij od clippingu. Jeśli zanika — szukaj gdzie indziej. A jeśli trenujesz coś większego niż mały model, dodaj clipping do pipeline’u domyślnie i zapomnij o nim.
Gradient clipping to tylko jeden z wielu terminów, które każdy inżynier uczenia maszynowego musi znać. Jeśli chcesz poznać pozostałe i być gotowy do pracy w 2026 roku, zapisz się na nasz kierunek Machine Learning Engineer już dziś.
FAQ: Gradient clipping
Czym jest gradient clipping w deep learningu?
Gradient clipping to technika ograniczająca rozmiar gradientów podczas trenowania sieci neuronowej, aby zapobiec niestabilnym aktualizacjom parametrów. Gdy gradienty rosną zbyt mocno w trakcie propagacji wstecznej, optymalizator wykonuje ogromne kroki, które wypychają wagi w złe rejony i powodują eksplozję straty. Clipping ogranicza wielkość gradientu przed krokiem optymalizatora, dzięki czemu aktualizacje pozostają ograniczone nawet wtedy, gdy surowe gradienty skaczą.
Kiedy powinienem używać gradient clippingu?
Używaj gradient clippingu zawsze, gdy trenowanie jest niestabilne — zwłaszcza gdy widzisz nagłe skoki straty, wartości NaN lub rozbieżność po godzinach treningu. To standard w sieciach rekurencyjnych jak LSTM i GRU oraz w każdej głębokiej architekturze trenowanej z wysokim learning rate’em. Jeśli krzywa straty wygląda zdrowo, możesz go pominąć, ale dodanie go jako siatki bezpieczeństwa nie zaszkodzi.
Jaka jest różnica między clip by value a clip by norm?
Clip by value indywidualnie ogranicza każdy element gradientu, co może zmienić kierunek wektora gradientu. Clip by norm skaluje cały wektor, gdy jego ogólna wielkość przekracza próg, zachowując pierwotny kierunek i jedynie skracając krok. Clip by norm jest standardowym wyborem we współczesnym deep learningu, ponieważ nie zniekształca kierunku aktualizacji.
Jak wybrać dobry próg gradient clippingu?
Zacznij od 1.0 i dostosuj na podstawie obserwacji podczas trenowania. Loguj nieprzycięte normy gradientów w partiach i spójrz na rozkład. Ustaw próg powyżej typowego zakresu norm, ale wyraźnie poniżej skoków, które chcesz wyłapać. Zbyt wysoki próg sprawi, że clipping się nie uaktywni; zbyt niski — niepotrzebnie spowolni uczenie.
Czy gradient clipping naprawia także zanikające gradienty?
Nie. Gradient clipping rozwiązuje tylko eksplodujące gradienty, gdzie wartości rosną zbyt duże. Zanikające gradienty to problem odwrotny — wartości kurczą się do zera i uczenie praktycznie ustaje. Na zanikające gradienty zastosuj lepszą inicjalizację wag, połączenia resztowe, batch normalization lub architektury takie jak LSTM i GRU.