Рекуррентные сети (RNN и LSTM)
Урок объясняет, как сети помнят прошлое при обработке последовательностей.
Рекуррентная сеть (RNN) обрабатывает последовательность по одному элементу, перенося из шага в шаг скрытое состояние — свою «память» о прошлом.
Зачем особая архитектура для последовательностей
Текст, речь, временные ряды — это последовательности, где важен порядок и контекст. Полносвязная сеть берёт фиксированный вход и не помнит, что было раньше. RNN устроена иначе: она читает элементы один за другим и на каждом шаге обновляет скрытое состояние h, в котором копится информация о предыдущих элементах.
Формула одного шага словами
На каждом шаге t: h_t = активация(Wx · x_t + Wh · h_{t-1} + b). Новое состояние зависит и от текущего входа x_t, и от прошлого состояния h_{t-1}. Те же веса Wx, Wh используются на всех шагах — сеть «прокручивается» по последовательности.
Игрушечная RNN: память в действии
import math
def tanh(x): return math.tanh(x)
Wx, Wh, b = 0.8, 0.9, 0.0
h = 0.0 # начальное состояние
sequence = [1, 0, 0, 1, 0]
print("шаг вход состояние h")
for t, x in enumerate(sequence):
h = tanh(Wx * x + Wh * h + b)
print(f"{t:>3} {x:>4} {h:>8.4f}")
print("Итоговое h помнит о прошлых входах:", round(h, 4))
Вывод:
шаг вход состояние h 0 1 0.6640 1 0 0.5354 2 0 0.4477 3 1 0.8345 4 0 0.6358 Итоговое h помнит о прошлых входах: 0.6358
Смотрите: на шагах 1 и 2 вход равен 0, но состояние h не падает в ноль — оно помнит про единицу на шаге 0 и плавно затухает. А когда на шаге 3 снова приходит 1, состояние подскакивает. Это и есть память: выход зависит не только от текущего входа, но и от истории.
Проблема короткой памяти и решение — LSTM
У простой RNN память «дырявая»: из-за затухания градиента (раздел 4) она быстро забывает давние элементы и плохо ловит длинные зависимости. LSTM (Long Short-Term Memory) решает это специальными воротами (gates) — обучаемыми вентилями, которые решают, что в памяти сохранить, что забыть, а что выдать наружу. Благодаря воротам LSTM держит важную информацию на сотни шагов. Похожая, но более простая идея — GRU.
| Архитектура | Особенность |
| RNN | простое состояние, короткая память |
| LSTM | ворота сохраняют долгую память |
| GRU | упрощённый вариант LSTM |
Как RNN обучают
Обучение рекуррентной сети — это всё тот же backprop, но применённый к «развёрнутой» во времени сети: каждый шаг последовательности рассматривают как отдельный слой с общими весами, и градиент течёт назад через все шаги. Этот приём называют backpropagation through time (BPTT). Отсюда и беда простой RNN: чем длиннее последовательность, тем больше слоёв проходит градиент, тем сильнее он затухает или взрывается — ровно проблема из четвёртого раздела, только вдоль времени. Ворота LSTM как раз дают градиенту «гладкий коридор» сквозь шаги, поэтому память держится дольше.
Где это применяют: распознавание речи, машинный перевод (до эпохи трансформеров), анализ временных рядов, генерация текста по буквам. Сегодня в обработке языка RNN и LSTM во многом потеснены трансформерами — к ним и перейдём в следующем уроке, — но идея переноса состояния-памяти из шага в шаг остаётся фундаментальной и встречается во многих гибридных архитектурах.
Итог
- RNN читает последовательность по элементам, перенося скрытое состояние-память.
- Те же веса применяются на каждом шаге; выход зависит от истории.
- Простая RNN быстро забывает; LSTM с воротами держит долгие зависимости.