Что такое проблемы взрывающегося и затухающего градиента?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Взрывающийся и затухающий градиент (Exploding & Vanishing Gradients)
Это две критические проблемы при обучении глубоких нейронных сетей (RNN, LSTM), особенно на последовательностях. Они приводят к неустойчивому обучению и плохой способности модели учить долгосрочные зависимости.
Суть проблемы
При обучении используется backpropagation — распространение ошибки назад через сеть:
Ошибка propagates: Output → Hidden → Input
dL/dW = dL/dH * dH/dW
Когда градиенты перемножаются много раз (в глубокой сети), они могут либо взорваться (бесконечно вырасти), либо затухнуть (стать близкими к нулю).
Затухающий градиент (Vanishing Gradient)
Проблема: Градиенты становятся меньше и меньше при распространении назад, близко к нулю.
Симптомы:
- Первые слои сети практически не обновляются
- Модель не учит долгосрочные зависимости
- Loss плато на начальном уровне
Пример с RNN:
# Обновление весов в RNN:
# dW_hidden = dL/dH_t * dH_t/dW_hidden
# = dL/dH_t * dH_t/dH_{t-1} * dH_{t-1}/dH_{t-2} * ... * dH_1/dW_hidden
#
# Если |dH_t/dH_{t-1}| < 0.1, то при 100 временных шагов:
# 0.1^100 ≈ 10^(-100) <- градиент исчезает!
Где чаще всего:
- RNN с функцией активации tanh или sigmoid
- Глубокие сети без batch normalization
- Долгие последовательности
Взрывающийся градиент (Exploding Gradient)
Проблема: Градиенты становятся огромными, обновления весов неконтролируемо большие.
Симптомы:
- Веса становятся NaN (not a number)
- Loss сразу же растёт до бесконечности
- Training crashes
Пример:
# Если |dH_t/dH_{t-1}| > 1, то при 100 шагов:
# 2^100 ≈ 10^30 <- градиент взрывается!
Решения для затухающего градиента
1. LSTM и GRU вместо RNN
Эти архитектуры специально разработаны для решения проблемы затухания:
from tensorflow.keras.layers import LSTM, GRU
import tensorflow as tf
# RNN (уязвим к затуханию)
model_rnn = tf.keras.Sequential([
tf.keras.layers.SimpleRNN(64, input_shape=(sequence_length, features))
])
# LSTM (имеет "cell state" - долговременную память)
model_lstm = tf.keras.Sequential([
tf.keras.layers.LSTM(64, input_shape=(sequence_length, features))
])
# GRU (более простой, но эффективный)
model_gru = tf.keras.Sequential([
tf.keras.layers.GRU(64, input_shape=(sequence_length, features))
])
2. ResNet - Skip Connections
Прямые связи через слои:
# В Keras используется Functional API
input_x = tf.keras.Input(shape=(100,))
x = tf.keras.layers.Dense(64, activation=relu)(input_x)
x = tf.keras.layers.Dense(64, activation=relu)(x)
x = tf.keras.layers.Add()([x, input_x]) # Skip connection
output = tf.keras.layers.Dense(10)(x)
model = tf.keras.Model(inputs=input_x, outputs=output)
3. Batch Normalization
Нормализует входы каждого слоя, стабилизирует градиенты:
model = tf.keras.Sequential([
tf.keras.layers.Dense(128),
tf.keras.layers.BatchNormalization(), # Стабилизирует
tf.keras.layers.Activation(relu),
tf.keras.layers.Dense(64),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Activation(relu),
])
4. Хорошая инициализация весов
Xavier/He инициализация:
# He инициализация для ReLU
tf.keras.layers.Dense(64,
kernel_initializer=tf.keras.initializers.HeNormal())
# Xavier для tanh/sigmoid
tf.keras.layers.Dense(64,
kernel_initializer=tf.keras.initializers.GlorotNormal())
Решения для взрывающегося градиента
1. Gradient Clipping
Обрезаем градиенты, если они превышают порог:
optimizer = tf.keras.optimizers.Adam()
# Clipping по норме
training_step = tf.keras.optimizers.Adam(
clipnorm=1.0 # Обрезаем, если норма градиента > 1.0
)
# Clipping по значению
training_step = tf.keras.optimizers.Adam(
clipvalue=0.5 # Все значения градиентов в [-0.5, 0.5]
)
2. Уменьшить learning rate
optimizer = tf.keras.optimizers.Adam(learning_rate=0.0001) # Меньше lr
3. Уменьшить размер batch
Меньше образцов → меньше градиента
Практический пример мониторинга
import tensorflow as tf
from tensorflow.keras.callbacks import TensorBoard
model = tf.keras.Sequential([
tf.keras.layers.LSTM(64, input_shape=(100, 32), return_sequences=True),
tf.keras.layers.LSTM(32),
tf.keras.layers.Dense(10, activation=softmax)
])
model.compile(
optimizer=tf.keras.optimizers.Adam(clipnorm=1.0), # Gradient clipping
loss=categorical_crossentropy,
metrics=[accuracy]
)
# TensorBoard для мониторинга gradient flow
callback = TensorBoard(log_dir=/logs, histogram_freq=1)
model.fit(
X_train, y_train,
epochs=50,
batch_size=32,
validation_data=(X_val, y_val),
callbacks=[callback]
)
Чеклист при обучении глубокой сети
✅ Используй LSTM/GRU для RNN (или Transformer) ✅ Batch Normalization между слоями ✅ He/Xavier инициализация ✅ Gradient clipping если видишь NaN ✅ Skip connections в очень глубоких сетях ✅ Мониторь gradient flow в TensorBoard ✅ Начни с маленького learning rate ✅ Тестируй на коротких последовательностях сначала