Глава 10. Трагедия рекуррентности (RNN / LSTM)
Последовательная обработка — удобная модель мышления.
Для GPU она часто оказывается архитектурным тупиком.
До сих пор полигоном была картинка: пространство, локальность, масштаб.
Теперь другой носитель информации — последовательность: слова, токены, кадры, сигналы.
Кажется естественным читать её слева направо, шаг за шагом, помня прошлое.
Именно так долго строили языковые модели. И именно здесь инженерия снова упёрлась в железо.
10.1. Идея RNN: состояние как память
Рекуррентная сеть держит скрытое состояние h.
На каждом шаге:
h_t = f(h_{t-1}, x_t)
y_t = g(h_t)
Красиво совпадает с интуицией «читаю текст по порядку».
Параметры одни и те же на каждом шаге — как weight sharing, только во времени.
Проблемы всплывают быстро.
10.2. Долгая память и снова глухой телефон
Если зависимость между x_1 и y_100 важна, градиенту снова нужно пройти через длинную цепь умножений.
Знакомый сюжет главы 4 — только ось теперь временная.
LSTM/GRU добавили вентили: что записать, что забыть, что отдать наружу.
Это сильно улучшило практическую память. Не отменило главный структурный приговор.
RNN/LSTM чинят «память» вентилями,
но оставляют правило: шаг t ждёт шаг t−1.
10.3. Настоящий приговор: плохой параллелизм
Современное обучение живёт батчами на GPU/TPU.
Железо любит большие матрицы и одновременные операции.
RNN говорит:
Токен 17 нельзя посчитать, пока не готов токен 16.
Даже если внутри шага всё векторизовано, длина последовательности становится глубиной последовательных зависимостей.
Параллельно по батчу? Да
Параллельно по длине? Почти нет
Масштаб к длинному контексту? Боль → дороже почти линейно по wall-clock цепочке
Для коротких фраз терпимо.
Для корпусов, длинных документов и желания масштабировать модель — всё больнее.
Инженерная переформулировка кризиса:
Мы купили естественную модель времени
ценой запрета на параллельный проход по времени.
10.4. Костыли, которые почти спасли парадигму
До трансформеров поле не стояло на месте:
- двунаправленные LSTM (смотреть контекст с двух сторон на этапе кодирования);
- deeper stacks, residual вокруг рекуррентных блоков;
- Truncated BPTT, gradient clipping;
- CNN по времени / dilated conv как альтернатива «почти рекуррентности»;
- attention поверх RNN (ещё не «attention is all you need»).
Каждый костыль закрывал симптом.
Ни один не отменял необходимость последовательного ядра в самом сердце модели.
flowchart TD
A[Последовательность] --> B[RNN/LSTM]
B --> C[Лучше память: вентили]
B --> D[Плохой параллелизм по длине]
D --> E[Обучение длинных контекстов дорого]
E --> F[Нужен другой обмен]
10.5. Какой обмен мы захотим в следующей главе
Чтобы выйти из тупика, придётся заплатить чем-то другим.
Желаемый контракт:
- каждый токен может смотреть на широкий контекст;
- вычисление по длине можно параллелить на обучении;
- глубина модели не равна длине текста.
Цена, которую рынок в итоге принял:
Квадратичная сложность внимания по длине последовательности
(и тяжёлая работа с памятью активаций)
взамен на параллелизм и масштабируемость обучения.
Это не «RNN плохие навсегда».
Для стриминга, крошечных контроллеров и некоторых online-сценариев рекуррентность всё ещё жива — и даже возвращается в новых формах (SSM/Mamba — в послесловии).
Но для большого NLP-взрыва 2017+ решающим оказался отказ от обязательного t-1 → t в ядре архитектуры.
Если бы вы были автором статьи…
-
Где RNN всё ещё бьёт трансформер по latency/памяти на вашем железе? Сформулируйте бенчмарк честно.
-
Можно ли сохранить последовательный инференс, но убрать последовательное обучение?
Какие ограничения это наложит на алгоритм? -
Если главная боль — параллелизм, почему недостаточно одномерных свёрток по токенам?
Чего им не хватает для дальних зависимостей?
Дальше — механизм, который позволил модели самой выбирать, на какие позиции смотреть, без обязательного прохода по цепочке времени.