# Архитектура RNN и LSTM: разбор лекции CS231N от Стэнфорда

Источник: https://www.youtube.com/watch?v=kG2lAPBF7zA
Канал: Stanford Online
Опубликовано: 02.09.2025

---

В рамках фундаментального курса Стэнфордского университета CS231N состоялась лекция, целиком посвященная рекуррентным нейронным сетям (RNN) и специфике обработки последовательностей переменных размеров. Преподаватель детально разобрал математический базис классических рекуррентных архитектур, наглядные примеры их ручного проектирования, а также ключевые проблемы затухания градиентов, которые подтолкнули индустрию к созданию блоков LSTM и современных моделей пространства состояний. Анализ эволюции этих подходов позволяет глубже понять устройство современных больших языковых моделей и систем компьютерного зрения.

## 🔍 Уточнения по прошлым темам: нюансы дропаута и LayerNorm
[[JUMP:0:05]]

Перед погружением в новую тему лектор счел необходимым прояснить ряд спорных вопросов, возникших у студентов на платформе Ed после предыдущего занятия. Первый нюанс коснулся математического несоответствия в слайдах, описывающих механизм работы дропаута (Dropout). В большинстве современных библиотек глубокого обучения гиперпараметр $p$ определяет именно вероятность отбрасывания нейронов. Однако базовая цель на этапе тестирования (test time) остается неизменной — ожидаемое значение выхода должно соответствовать показателям времени обучения. По словам преподавателя, если во время обучения отключается 25% активаций, то на этапе инференса значения необходимо масштабировать на коэффициент 0,75, чтобы сбалансировать общую мощность сигналов.

Второй важный аспект коснулся применения нормализации слоев (LayerNorm) для компенсации некорректной инициализации весов. В рамках симуляции двухслойной нейросети с функцией активации ReLU, решающей задачу определения квадранта для двумерных точек, исследовались разные стратегии инициализации. На графиках обучения видно, что LayerNorm действительно сглаживает негативные эффекты завышенного стандартного отклонения весов, однако между идеальной инициализацией по методу Кайминга (Kaiming initialization) и плохой инициализацией с LayerNorm все еще сохраняется разрыв в финальной точности. Лектор подчеркнул, что эффективность LayerNorm напрямую зависит от специфики конкретной задачи:

* В задачах, где точные пространственные координаты объектов не играют критической роли (как в функции квадрантов), нормализация слоев существенно ускоряет сходимость.
* В архитектурах, где нейросети жизненно необходимо знать точные координаты точек для формирования корректного ответа, LayerNorm может серьезно навредить производительности, поскольку процедура вычитания среднего значения и деления на стандартное отклонение стирает исходную пространственную информацию.

## 📊 Инструменты для трекинга гиперпараметров
[[JUMP:3:00]]

Подытоживая разбор классических полносвязных и сверточных нейросетей, оперирующих фиксированными размерами входов и выходов, лектор напомнил о важности контроля динамики обучения. Процесс настройки таких параметров, как скорость обучения (learning rate) или конфигурация трансферного обучения на базе предобученных весов ImageNet, требует постоянного наблюдения. В качестве оптимального инструмента для мониторинга экспериментов преподаватель выделил платформу Weights & Biases, отметив, что лично использует ее практически во всех своих исследовательских проектах.

Система позволяет наглядно визуализировать десятки параллельных запусков с различными значениями гиперпараметров (например, с разной силой дропаута) с помощью удобной цветовой кодировки. Графики валидационной точности наглядно демонстрируют исследователю, какие именно конфигурации ведут к переобучению, а какие обеспечивают наилучший результат. Преподаватель добавил, что при наличии достаточных вычислительных ресурсов для перебора конфигураций этот инструмент незаменим, хотя в качестве альтернативы разработчики могут использовать стандартный TensorBoard.

## 🔄 Введение в моделирование последовательностей
[[JUMP:4:45]]

Главным ограничением стандартных нейросетей является их жесткая привязка к статичным тензорам на входе и выходе. В реальном мире данные чаще представляют собой последовательности переменной длины. До наступления эпохи трансформеров основным инструментом для работы с такими структурами выступали рекуррентные нейронные сети (RNN) и их продвинутые модификации. Лектор акцентировал внимание на том, что базовые концепции RNN вовсе не ушли в прошлое: сегодня они находят свое отражение и вдохновляют разработчиков новейших архитектур, таких как модели пространства состояний (State Space Models, SSM), ярким примером которых является архитектура Mamba.

Для формализации задач моделирования последовательностей была предложена следующая классификация архитектурных паттернов:

* **Один к многим (One-to-Many):** на вход подается один объект фиксированного размера (например, статичное изображение), а на выходе генерируется последовательность переменной длины. Классическим примером здесь служит задача автоматического описания изображений (Image Captioning).
* **Многие к одному (Many-to-One):** модель принимает на вход последовательность векторов изменяемой длины и выдает одну итоговую метку класса. Типичный сценарий — классификация видео, где сеть последовательно обрабатывает цепочку видеокадров для определения выполняемого в кадре действия.
* **Многие ко многим (Many-to-Many):** гибкая схема, где длины входной и выходной последовательностей могут не совпадать (например, генерация текстового описания для видеоролика). Отдельным частным случаем является синхронное пошаговое отображение, когда каждому конкретному входному шагу соответствует свой выходной шаг — именно на этой схеме лектор сфокусировался при разборе принципов работы RNN, приведя в пример покадровую разметку видео.

## 🧠 Анатомия RNN и математика ручной сборки детектора
[[JUMP:7:22]]

Суть рекуррентной сети заключается в наличии внутреннего или скрытого состояния (hidden state), обозначаемого как $h_t$, которое непрерывно обновляется по мере продвижения по цепочке данных. Каждое новое вычисление текущего состояния опирается как на текущий входной вектор $x_t$, так и на вектор памяти из предыдущего временного шага $h_{t-1}$. На традиционных схемах этот процесс часто изображают в виде циклической стрелки, возвращающейся в функциональный блок, однако для понимания алгоритма вычисления градиентов гораздо удобнее использовать схему развернутой во времени сети (unrolled RNN).

Математически классическая формула обновления скрытого состояния выглядит следующим образом:

$$h_t = f_W(h_{t-1}, x_t)$$

Обычно она параметризуется матрицами весов и нелинейной функцией активации. Для получения итогового прогноза $y_t$ применяется отдельная функция со своим независимым набором параметров:

$$y_t = W_{hy} h_t$$

Матрица весов $W_{hy}$ выполняет две задачи: трансформирует размерность внутреннего скрытого пространства сети в целевую размерность выходного предсказания и осуществляет линейное преобразование данных. При запуске цепочки начальное скрытое состояние $h_0$ инициализируется базовым вектором, который в реальных сценариях чаще всего является обучаемым параметром. Важно понимать, что на каждом временном шаге сеть применяет абсолютно одинаковые веса для расчета скрытого состояния и строго фиксированные параметры для генерации выходов.

Чтобы продемонстрировать внутреннюю механику RNN без использования градиентного спуска, лектор представил пример ручного конструирования весовых матриц для простой игрушечной задачи. Модели на вход подается поток из нулей и единиц, а ее цель — выдать «1» в тот момент, когда в цепочке встречаются две единицы подряд, и «0» во всех остальных случаях.

Для успешного выполнения этого теста скрытое состояние сети должно аккумулировать информацию о текущем и предыдущем значениях входного потока. Преподаватель определил скрытое состояние $h_t$ как трехмерный вектор, где верхний элемент отвечает за текущий вход, средний — за предыдущий шаг, а нижний всегда равен «1» для упрощения смещения в расчетах. Начальное состояние $h_0$ инициализируется как вектор $[0, 0, 1]^T$, что эквивалентно допущению, что сеть изначально «видела» два нуля подряд. Для простоты расчетов функция активации была заменена на ReLU.

В рамках этой конфигурации были определены следующие параметры весов:

* Матрица связи со входом $W_{xh}$ задается как вектор-столбец $[1, 0, 0]^T$. При умножении на входное значение $x_t$ (0 или 1) она переносит этот сигнал строго в верхнюю ячейку скрытого состояния.
* Матрица перехода между скрытыми состояниями $W_{hh}$ имеет размерность $3 \times 3$, где верхняя строка занулена (чтобы прошлые состояния не искажали фиксацию нового входа), а во второй строке стоит значение $[1, 0, 0]$. Это позволяет при перемножении векторов скопировать «текущее» значение предыдущего шага и перенести его на позицию «прошлого» значения для нового шага. Нижняя строка матрицы просто транслирует единицу.
* Выходной вектор весов $W_{hy}$ имеет размерность $1 \times 3$ и представляет собой вектор $[1, 1, -1]$.

При итоговом вычислении скалярного произведения весов $W_{hy}$ на скрытое состояние $h_t$ внутри функции ReLU получается выражение:

$$\text{текущее} + \text{предыдущее} - 1$$

Если оба значения равны единице, результат операции равен 1, и ReLU возвращает единицу (обнаружен повтор). Если хотя бы один из элементов равен нулю, сумма уменьшается, а смещение $-1$ уводит итоговый аргумент в отрицательную зону, что на выходе ReLU дает чистый ноль.

## 📉 Обратное распространение ошибки во времени и усеченный BPTT
[[JUMP:23:55]]

В реальной практике никто не подбирает веса вручную — для этого используется градиентный спуск. В полноценном сценарии «многие ко многим» функция потерь (loss) рассчитывается для каждого индивидуального шага, после чего все промежуточные потери суммируются, формируя общий показатель ошибки для всей входной цепочки данных. Полноценный расчет градиентов для единой разделяемой матрицы весов $W$ требует независимого вычисления частных производных на каждом временном отрезке с их последующим сложением.

При работе с экстремально длинными последовательностями исследователи неизбежно сталкиваются с жестким ограничением памяти GPU, поскольку алгоритм вынужден сохранять в памяти все промежуточные активации для каждого шага. Процесс вычисления градиентов по всей длине называется обратным распространением ошибки во времени (Backpropagation Through Time, BPTT). Для преодоления дефицита памяти применяется метод усеченного обратного распространения (Truncated BPTT).

Суть метода заключается в разбиении исходной длинной цепочки на фиксированные небольшие временные окна (чанки):

1.  Сеть выполняет прямой проход (forward pass) только внутри текущего окна, рассчитывая скрытые состояния и фиксируя локальные потери.
2.  Затем выполняется стандартный обратный проход для вычисления градиентов весов исключительно в границах этого окна.
3.  При переходе к следующему чанку веса обновляются, история вычисления градиентов полностью обнуляется, однако финальное скрытое состояние предыдущего окна передается в качестве стартового вектора $h_0$ для новой сессии вычислений.

## 📝 Символьные языковые модели и их «необоснованная эффективность»
[[JUMP:36:26]]

Одной из классических демонстраций возможностей рекуррентных сетей являются языковые модели символьного уровня (character-level language models), активно развивавшиеся около 10 лет назад. Задача такой модели — по цепочке уже введенных букв предсказать следующий наиболее вероятный символ текста. Входные буквы кодируются с помощью векторов One-Hot, где единица выставляется строго на индексе конкретного символа в алфавите. На выходном слое с помощью функции Softmax формируются логиты — оценки вероятностей для каждого возможного символа. На этапе генерации текста сеть осуществляет последовательное пошаговое сэмплирование букв, подавая собственный сгенерированный символ обратно на вход для расчета следующего шага.

Преподаватель отметил, что вместо неэффективных разреженных One-Hot векторов в реальных системах всегда используется промежуточный слой эмбеддингов (embedding layer). Он представляет собой обучаемую матрицу размерности $D \times D$, из которой по индексу входного символа извлекается плотный вектор признаков, инициализированный случайными малыми значениями по методу Кайминга.

Лектор упомянул знаменитый блог-пост Андрея Карпати от 2015 года под названием *«Необоснованная эффективность рекурнентных нейронных сетей»*. Минималистичная реализация такой модели занимает всего 112 строк чистого кода на Python, но при этом способна выдавать поразительные результаты. При обучении на сонетах Уильяма Шекспира модель на ранних этапах генерирует случайный набор букв из-за случайных весов $W$, но по мере продолжения обучения текст обретает структуру: появляются реальные слова, а затем сеть полностью перенимает драматический стиль автора с именами персонажей перед репликами. При обучении на исходном коде ядра Linux символьная RNN начинает генерировать синтаксически правдоподобный код на языке C с корректными отступами и объявлением переменных.

В современных коммерческих инструментах для программирования и больших языковых моделях используется аналогичный авторегрессионный принцип, однако вместо отдельных букв сети предсказывают токены — укрупненные группы символов. При генерации критически важно избегать «жадного декодирования» (greedy decoding) — стратегии, при которой всегда выбирается символ с максимальной вероятностью, так как это ведет к зацикливанию текста. Профессиональные разработчики сэмплируют токены на основе распределения вероятностей Softmax или задействуют алгоритм лучшего лучевого поиска (Beam Search).

## 🔬 Визуализация скрытых состояний: что «видят» нейроны
[[JUMP:45:21]]

Интересной особенностью RNN является высокая интерпретируемость некоторых внутренних нейронов скрытого слоя при использовании активации $tanh$, возвращающей значения от -1 (красный цвет на визуализации) до +1 (синий цвет). Эксперименты показывают, что в процессе автономного обучения отдельные скрытые ячейки сети самостоятельно начинают выполнять специализированные функции без какого-либо ручного программирования со стороны человека:

* **Детектор кавычек:** нейрон активируется в синюю зону строго при открытии текстовой кавычки и мгновенно переходит в красную зону, как только кавычка закрывается.
* **Счетчик длины строки:** активация плавно угасает по мере продвижения по строке, фактически сигнализируя системе о необходимости скорого вывода символа переноса строки `\n`.
* **Детектор условий `if`:** в моделях, обучавшихся на коде, данная ячейка удерживает высокий уровень активации исключительно в границах условных операторов.
* **Ячейка глубины вложенности кода:** отслеживает уровни отступов и табуляции в иерархии исходного кода, усиливая сигнал по мере углубления в логические блоки.

## ⚖️ Сильные стороны архитектуры и интеграция с компьютерным зрением
[[JUMP:48:19]]

По мнению преподавателя, архитектура RNN обладает рядом фундаментальных преимуществ, которые выгодно отличают ее от классических моделей:

* Способность обрабатывать входные последовательности абсолютно любой длины, поскольку у классической RNN отсутствует жестко лимитированное окно контекста, свойственное стандартным трансформерам.
* Размер самой модели и количество ее параметров остаются неизменными и не разрастаются при увеличении длины обрабатываемой цепочки.
* Симметрия вычислений за счет применения одних и тех же весовых коэффициентов на каждом шаге.

Тем не менее, главным недостатком остается сугубо последовательная природа вычислений: для расчета текущего шага $t$ необходимо обязательно дождаться завершения вычисления состояния $t-1$, что делает невозможным параллельное обучение на GPU и сильно замедляет процесс по сравнению с трансформерами. Кроме того, фиксированный размер вектора скрытого состояния создает «бутылочное горлышко», мешая эффективно удерживать информацию за сотни шагов до текущего момента.

В сфере компьютерного зрения рекуррентные сети успешно комбинируются со сверточными архитектурами (CNN). В задаче Image Captioning изображение сначала пропускается через сверточную сеть (например, предобученную на ImageNet), откуда извлекается вектор признаков с предпоследнего полносвязного слоя. Этот визуальный вектор подмешивается во внутреннее скрытое состояние RNN, которая авторегрессионно генерирует слова описания до тех пор, пока не выдаст специальный токен окончания последовательности.

Несмотря на исторический успех, такие гибридные модели страдают от проблемы жестких статистических смещений в датасетах. Из-за высокой корреляции признаков в обучающей выборке сети склонны к сильным галлюцинациям. Например, если человек на фото держит ладони лодочкой, модель уверенно рапортует о наличии компьютерной мыши, игнорируя тот факт, что в руке находится плоский смартфон. Точно так же наличие пляжа на заднем плане заставляет сеть дорисовывать в описании доску для серфинга, даже если человек просто стоит в меховой одежде. Сеть выучивает сопутствующие признаки сцены, но не способна к их детальному смысловому распутанию (disentanglement).

Среди прочих смежных мультимодальных задач, где активно применялись рекуррентные цепочки, лектор выделил:

* **Визуальный ответ на вопросы (Visual Question Answering, VQA):** генерация текстового ответа на базе картинки и текстового вопроса, либо мультиклассовая классификация по заранее заготовленным вариантам ответов.
* **Визуальный диалог (Visual Dialogue):** ведение последовательного текстового чата вокруг содержания одного изображения.
* **Визуальная навигация (Visual Navigation):** генерация пошаговых команд перемещения агента на основе поступающих кадров интерьера.

При усложнении систем разработчики создают многослойные RNN (multi-layer RNNs), где скрытое состояние первого слоя служит входным сигналом для вышележащего рекуррентного слоя. Это формирует сложную двумерную вычислительную сетку (по времени и по глубине слоев), которая, однако, крайне неэффективна в масштабировании.

## 💥 Кризис ванильных RNN и эволюция к LSTM и моделям пространства состояний
[[JUMP:58:14]]

Главной причиной отказа от использования базовых (ванильных) рекуррентных сетей на практике стали математические проблемы при расчете градиентов по длинным цепочкам. При выполнении обратного прохода градиент функции потерь на шаге $t$ относительно скрытого состояния на предыдущем шаге $t-1$ включает в себя произведение производной функции активации (например, гиперболического тангенса) и самой матрицы скрытых весов $W_{hh}$:

$$\frac{\partial h_t}{\partial h_{t-1}} = \text{diag}(1 - \tanh^2(...)) W_{hh}^T$$

Максимальное значение производной $\tanh$ равно 1, но в большинстве точек оно значительно меньше единицы. Перемножение сотен таких локальных производных неизбежно приводит к экспоненциальному угасанию сигнала — проблеме затухающих градиентов (vanishing gradients). Ситуация с самой матрицей $W_{hh}$ еще более критична: если ее наибольшее сингулярное значение (показатель максимального растяжения векторов при трансформации) больше единицы, градиенты начинают лавинообразно взрываться (exploding gradients), уничтожая веса модели. Проблему взрыва градиентов можно купировать жестким принудительным ограничением — градиентным клиппингом (gradient clipping). Однако эффективного математического лекарства от затухания градиентов в рамках классической формулы RNN не существует, из-за чего сеть физически теряет способность обучаться на долгосрочных зависимостях.

Чтобы обойти это бутылочное горлышко, еще в 1990-х годах была предложена архитектура LSTM (Long Short-Term Memory). Вместо единственного вектора скрытого состояния в LSTM вводятся четыре независимых внутренних гейта (ворота), управляемых собственными весами:

* **Входной гейт (Input gate):** определяет, какой объем новой информации со входа будет записан в память.
* **Гейт забывания (Forget gate):** решает, какую долю накопленной старой информации из прошлых шагов необходимо стереть.
* **Выходной гейт (Output gate):** регулирует, какая часть внутреннего состояния будет передана наружу в качестве итогового скрытого вектора.
* **Блоковый гейт (Block gate):** генерирует новые кандидаты для записи.

Ключевое архитектурное новшество LSTM — это выделенная верхняя магистраль состояния ячейки (cell state), проходящая сквозь временные шаги транзитом. На этой магистрали отсутствуют нелинейные функции активации вроде $\tanh$, подавляющие градиент. Информация обновляется посредством линейного сложения, что позволяет градиентам при обратном проходе свободно течь вспять сквозь сотни шагов во времени. По мнению лектора, этот подход концептуально полностью идентичен механизму сквозных связей (skip connections) в глубоких сверточных сетях ResNet, с той лишь разницей, что ResNet спасает градиенты при увеличении глубины слоев, а LSTM — при увеличении длины временной последовательности.

В заключение лекции преподаватель отметил, что прямо сейчас индустрия переживает яркий ренессанс рекуррентных подходов в лице моделей пространства состояний (SSM), таких как Mamba или проект RWKV. Трансформеры требуют колоссальных ресурсов, так как сложность расчета внимания в них растет квадратично ($O(N^2)$) от длины текста. Новые же рекуррентные SSM-модели обеспечивают строго линейное масштабирование ($O(N)$) вычислительной сложности, предлагая исследователям лучшее из двух миров: высокое качество обобщения информации, как у трансформеров, и неограниченное окно контекста при минимальном потреблении памяти, как у классических рекуррентных сетей.