Как устроены RNN, LSTM и GRU? В чём между ними разница?
RNN (Recurrent Neural Networks), LSTM (Long Short-Term Memory) и GRU (Gated Recurrent Unit) — это типы рекуррентных нейронных сетей, предназначенных для обработки последовательностей, таких как текст, аудио или временные ряды. Все они используют скрытое состояние, передаваемое во времени от одного шага к другому, но различаются архитектурно и функционально, особенно в умении запоминать долгосрочные зависимости и избегать затухающего градиента.
RNN — Recurrent Neural Network
Принцип работы:
Обычная нейросеть (MLP) не может обрабатывать последовательные данные напрямую, т.к. не сохраняет контекст. RNN же имеет обратную связь во времени — каждый элемент последовательности обрабатывается шаг за шагом, передавая скрытое состояние от предыдущего шага к текущему.
На каждом временном шаге tt:
-
Вход: xtx_t
-
Скрытое состояние: hth_t
-
Обновление:
ht=tanh(Wxhxt+Whhht−1+b)h_t = \tanh(W_{xh} x_t + W_{hh} h_{t-1} + b) - Выход (опционально): yt=Whyhty_t = W_{hy} h_t
RNN позволяет моделировать зависимость между элементами последовательности. Однако простая RNN страдает от проблемы исчезающего/взрывающегося градиента при обучении на длинных последовательностях, что делает невозможным запоминание информации, находящейся далеко в прошлом.
LSTM — Long Short-Term Memory
LSTM — это разновидность RNN, предложенная для борьбы с исчезающим градиентом. Она содержит механизмы управления потоком информации с помощью гейтов (вентилей).
Основные компоненты:
Каждый LSTM-узел содержит:
-
ячейку памяти CtC_t
-
входной гейт iti_t
-
забывающий гейт ftf_t
-
гейт обновления (кандидатное состояние) C~t\tilde{C}_t
-
выходной гейт oto_t
Формулы:
ft=σ(Wf⋅[ht−1,xt]+bf)it=σ(Wi⋅[ht−1,xt]+bi)C~t=tanh(WC⋅[ht−1,xt]+bC)Ct=ft∗Ct−1+it∗C~tot=σ(Wo⋅[ht−1,xt]+bo)ht=ot∗tanh(Ct)\begin{align*} f_t &= \sigma(W_f \cdot [h_{t-1}, x_t] + b_f) \\ i_t &= \sigma(W_i \cdot [h_{t-1}, x_t] + b_i) \\ \tilde{C}_t &= \tanh(W_C \cdot [h_{t-1}, x_t] + b_C) \\ C_t &= f_t * C_{t-1} + i_t * \tilde{C}_t \\ o_t &= \sigma(W_o \cdot [h_{t-1}, x_t] + b_o) \\ h_t &= o_t * \tanh(C_t) \end{align*}
-
σ\sigma — сигмоида
-
∗* — поэлементное умножение
Интерпретация:
-
ftf_t решает, какую часть старой памяти Ct−1C_{t-1} забыть.
-
iti_t контролирует, сколько новой информации добавить.
-
oto_t управляет, что из памяти выдать как выход.
-
Это позволяет LSTM долго сохранять релевантную информацию и игнорировать нерелевантную.
GRU — Gated Recurrent Unit
GRU — упрощённая версия LSTM, предложенная для снижения вычислительной нагрузки при сохранении эффективности.
Основные гейты:
-
гейт обновления ztz_t — как в LSTM: насколько обновлять скрытое состояние.
-
гейт сброса rtr_t — управляет забыванием предыдущего состояния.
Формулы:
zt=σ(Wz⋅[ht−1,xt])rt=σ(Wr⋅[ht−1,xt])h~t=tanh(W⋅[rt∗ht−1,xt])ht=(1−zt)∗ht−1+zt∗h~t\begin{align*} z_t &= \sigma(W_z \cdot [h_{t-1}, x_t]) \\ r_t &= \sigma(W_r \cdot [h_{t-1}, x_t]) \\ \tilde{h}_t &= \tanh(W \cdot [r_t * h_{t-1}, x_t]) \\ h_t &= (1 - z_t) * h_{t-1} + z_t * \tilde{h}_t \end{align*}
Интерпретация:
-
GRU объединяет память и скрытое состояние (в отличие от LSTM, где они разделены).
-
Обновление производится по принципу: либо оставить старое, либо заменить новым.
-
Меньше параметров, быстрее обучение, подходит для задач с ограниченными ресурсами.
Сравнение RNN, LSTM и GRU
Характеристика | RNN | LSTM | GRU |
---|---|---|---|
Количество гейтов | 0 | 3 (forget, input, output) | 2 (reset, update) |
--- | --- | --- | --- |
Управление памятью | Нет | Да | Да |
--- | --- | --- | --- |
Проблема исчезающего градиента | Да | Частично решена | Частично решена |
--- | --- | --- | --- |
Долгосрочная память | Плохо | Хорошо | Хорошо (но чуть хуже LSTM) |
--- | --- | --- | --- |
Скорость обучения | Быстрее (но хуже качество) | Медленнее | Быстрее, чем LSTM |
--- | --- | --- | --- |
Количество параметров | Меньше | Больше | Меньше, чем у LSTM |
--- | --- | --- | --- |
Подходит для длинных последовательностей | Плохо | Лучше всего | Хорошо, но зависит от задачи |
--- | --- | --- | --- |
Интерпретируемость | Простая | Сложная, но гибкая | Средняя |
--- | --- | --- | --- |
Примеры в фреймворках
TensorFlow/Keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import SimpleRNN, LSTM, GRU
model = Sequential()
model.add(SimpleRNN(128, input_shape=(max_len, embedding_dim))) # RNN
\# model.add(LSTM(128)) # LSTM
\# model.add(GRU(128)) # GRU
PyTorch
import torch.nn as nn
rnn = nn.RNN(input_size=300, hidden_size=128)
lstm = nn.LSTM(input_size=300, hidden_size=128)
gru = nn.GRU(input_size=300, hidden_size=128)
Где применяются:
-
RNN:
-
Базовые задачи, короткие тексты, простые модели.
-
В наши дни почти не используется напрямую из-за ограничений.
-
-
LSTM:
-
Задачи с длинной памятью: перевод, генерация текста, временные ряды, биоинформатика.
-
Более стабильны при обучении на длинных последовательностях.
-
-
GRU:
-
Популярен в задачах, где важна производительность (мобильные устройства, большие корпуса).
-
Часто дает сравнимую точность с LSTM при меньших затратах.
-
Влияние длины последовательности
-
При коротких последовательностях различие между LSTM и GRU может быть несущественным.
-
При длинных — LSTM устойчивее, лучше передаёт информацию на десятки и сотни шагов назад.
-
GRU склонен быстрее «забывать», но делает это экономнее.
Важно понимать
-
LSTM и GRU — это решения для моделирования зависимостей во времени.
-
Они не параллелизуются по временной оси, как трансформеры (BERT, GPT), поэтому в современных NLP задачах часто заменяются на attention-based модели.
-
Тем не менее, в задачах временных рядов, аудио, IoT, сигналов — RNN и производные всё ещё активно применяются.