Диагностика Mock-интервью
Главная · Нейронные сети

Рекуррентные сети (RNN, LSTM)

До эпохи трансформеров последовательности — текст, речь, временные ряды — обрабатывали рекуррентные сети (recurrent neural networks, RNN). Их главная идея, «память в скрытом состоянии», жива до сих пор: без неё не понять ни LSTM на легаси-проде, ни современные state space models.

Интуиция

Обычная сеть видит вход целиком и сразу. Но текст приходит по одному токену, и его длина заранее неизвестна. RNN читает последовательность как человек — слева направо, элемент за элементом, — и ведёт «конспект» прочитанного: вектор скрытого состояния (hidden state) h. На каждом шаге сеть смешивает новый вход со старым конспектом и записывает обновлённый конспект:

ht = tanh(W·xt + U·ht−1 + b)

Здесь xt — текущий вход (например, one-hot вектор символа), ht−1 — память с прошлого шага, а матрицы W, U и смещение bодни и те же на всех шагах. Предсказание (скажем, следующего символа) делается ещё одним линейным слоем поверх ht с softmax.

Важно: размер h фиксирован. Вся история, сколь угодно длинная, ужимается в один вектор — это и сила (константная память), и слабость (бутылочное горлышко: детали далёкого прошлого затираются).

Как RNN обучается: развёртка во времени

Чтобы применить обратное распространение, RNN «разворачивают» во времени (unrolling): цепочка из T шагов превращается в глубокую сеть из T одинаковых слоёв с общими весами, и градиент течёт по ней назад — от последнего шага к первому. Это называется backpropagation through time (BPTT). Градиент по U суммируется по всем шагам — ведь матрица одна.

Тут же прячется главная беда: пробираясь через T шагов, градиент T раз умножается на якобиан перехода (по сути на U и производные tanh, которые ≤ 1). Если множители в среднем меньше единицы — градиент затухает (vanishing gradients), и сеть не может выучить зависимости длиной в десятки шагов. Если больше — взрывается (exploding gradients); от взрыва спасает gradient clipping, от затухания — архитектурные костыли посерьёзнее.

💡 Ключевая мысль RNN — это один и тот же слой, применяемый по кругу: новый вход + старая память → новая память. Все проблемы (затухающие градиенты, последовательность вычислений) растут из этого же цикла.

Обрати внимание: паттерн «аабб» нельзя предсказать по одному текущему символу — после «а» идёт то «а», то «б» в зависимости от того, что было раньше. Именно поэтому сети нужна память h: она должна закодировать «это первая „а“ или вторая». Простая биграммная модель здесь навсегда застряла бы на 50% уверенности.

LSTM и GRU: память с вентилями

LSTM (long short-term memory) чинит затухание градиентов архитектурно. К скрытому состоянию добавляется ячейка памяти (cell state) — «конвейер», по которому информация течёт сквозь шаги почти без изменений, — и три вентиля (gates), каждый из которых — маленький сигмоидный слой со значениями от 0 до 1:

Так как память обновляется аддитивно (что-то прибавили, что-то стёрли), а не через многократное умножение, градиент течёт по конвейеру на десятки и сотни шагов. GRU (gated recurrent unit) — упрощение с двумя вентилями: чуть быстрее, обычно сопоставимо по качеству.

Почему трансформеры вытеснили RNN — и где RNN живы

У RNN есть неустранимый недостаток: шаг t нельзя посчитать раньше шага t−1. Обучение принципиально последовательно и не параллелится по длине текста — GPU простаивает. Внимание (attention) в трансформерах смотрит на все позиции сразу: обучение параллелится целиком, а зависимость между токенами на расстоянии 1000 шагов — это одна операция, а не 1000 переходов через память.

Но RNN-идея не умерла: стриминговое распознавание речи и обработка сигналов на маленьких устройствах любят рекуррентность за константную память на шаг (не нужен растущий KV-cache). А state space models (SSM, например Mamba) — это, по сути, современные линейные рекуррентные сети: инференс — как у RNN (шаг за шагом, дёшево), обучение — параллельное, как у трансформера.

⚠️ Подводный камень «LSTM решает проблему затухающих градиентов» — опасное упрощение. LSTM резко смягчает её на дистанциях в сотни шагов, но не отменяет: на очень длинных последовательностях память всё равно деградирует. И от взрыва градиентов вентили не спасают — gradient clipping для рекуррентных сетей нужен почти всегда.
🎤 На собеседовании
  • «Напишите формулу шага RNN» — ht = tanh(W·xt + U·ht−1 + b); подчеркните, что W и U общие для всех шагов.
  • «Почему градиенты затухают?» — при BPTT градиент умножается на якобиан перехода T раз; произведение множителей < 1 экспоненциально гаснет.
  • «Зачем LSTM три вентиля?» — управляемые запись/стирание/чтение памяти; аддитивное обновление ячейки даёт градиенту «шоссе» сквозь время.
  • «Почему трансформер победил?» — параллельное обучение по всей длине и прямой доступ к далёкому контексту вместо T последовательных переходов.