Как ворота помогают градиенту пройти через много шагов?
LSTM прокладывает через время почти линейный путь состояния. Ворота не
являются маленькими разумными контролёрами: это дифференцируемые числа от нуля
до единицы, которые учатся пропускать, стирать и показывать сигнал. Значение
одного такого числа переводится в число шагов памяти простой формулой, а
аддитивный путь решает не задачу «помнить», а задачу «донести градиент».
Пароль через длинную паузу
Последовательность начинается символом К, затем идут двести нерелевантных
знаков, а в конце нужно воспроизвести первый символ. Простая
RNN многократно переписывает ht и проводит градиент через
произведение матриц: на каждом шаге состояние целиком пропускается через
нелинейность, и от первого символа к концу почти ничего не доходит — ни
сигнала вперёд, ни производной назад.
LSTM меняет одну вещь. Рядом со скрытым состоянием ht появляется отдельное
состояние памяти ct, которое обновляется аддитивно: старое значение
умножается на число и к нему прибавляется новое. Никаких матриц на этом пути,
никакого tanh поверх всего состояния. Для входа xt и предыдущего
ht−1 вычисляются ворота:
Forget gate ft сохраняет часть старого, input gate it дозирует запись,
output gate ot решает, что показать наружу. Все операции покомпонентны:
координата памяти живёт своей жизнью и имеет собственный временной масштаб.
Обратите внимание на порядок аргументов: они начали не с памяти, а с
градиента. Проблема формулируется как «обратный поток ошибки затухает», и
конструкция ячейки является ответом именно на неё.
Рис. 74.1. Аддитивный путь памяти и одна координата в числах
Слева: на пути ct−1→ct стоят только умножение и сложение — ни одной
матрицы. Ворота приходят снизу, из [xt,ht−1]. Справа тот же шаг для одной
координаты: ct−1=2, ft=0,8, it=0,25, ct=−0,4,
ot=0,6 дают ct=1,5000 и ht=0,5431.
Одна координата, семь чисел
Разберём шаг руками, потому что вся дальнейшая интуиция держится на этой
арифметике. Пусть ct−1=2, ft=0,8, it=0,25,
ct=−0,4, ot=0,6. Память сохраняется в доле ft:
ftct−1=0,8⋅2=1,6000,
запись добавляет
itct=0,25⋅(−0,4)=−0,1000,
и вместе
ct=1,6000−0,1000=1,5000.
Наружу выходит не ct, а его сжатая и приглушённая версия:
ht=ottanh(ct)=0,6⋅0,9051=0,5431.
Чувствительность выхода к памяти равна произведению двух множителей:
∂ct∂ht=ot(1−tanh2ct)=0,6⋅0,1807=0,1084.
Если полностью закрыть запись, it=0, то ct=1,6 и ht=0,5530:
внешнее различие двух ситуаций — четыре сотых, тогда как внутри память
отличается на десятую. Это первый важный вывод: ht является отчётом о
памяти, а не самой памятью, и tanh вместе с ot умеют сжимать большие
внутренние различия до неразличимых внешних.
Почему сложение спасает градиент
Возьмём производную памяти по её же предыдущему значению вдоль прямого пути:
∂ct−1∂ct≈ft.
Тогда на отрезке от t до T
∂ct∂cT≈k=t+1∏Tfk.
Сравните с простой RNN, где на каждом шаге градиент домножается на
рекуррентную матрицу и производную нелинейности:
Первая сумма управляется одним обучаемым числом на шаг, вторая содержит
слагаемое, которое сеть не контролирует напрямую.
Множитель 1−hk2 не превосходит единицы и при насыщении близок к нулю,
поэтому произведение тает даже при аккуратно подобранной W. У аддитивного
пути такого множителя нет вовсе — есть только ворота, и сеть может держать их
близко к единице.
«Почти» в первой формуле существенно: ворота зависят от ht−1, поэтому
полный градиент имеет дополнительные пути. LSTM смягчает исчезновение, а не
доказывает бесконечную память.
Измерим это на живой сети. Возьмём задачу «запомни первый бит» с паузой в
D=100 посторонних символов и посмотрим, какая доля градиента доходит от
запроса до первого шага при инициализации, до всякого обучения. У простой
RNN норма ∥∂L/∂ht∥ падает за сто шагов в
704 раза. У LSTM градиент по памяти ∥∂L/∂ct∥
не падает вовсе: он даже вырастает в 3,72 раза, потому что вклады с разных
шагов складываются вдоль магистрали. Отношение двух «дальностей» — около
2620 раз.
Рис. 74.2. Куда доходит сигнал обучения при паузе в сто шагов
Обе кривые измерены на реальной сети (numpy, ручное обратное распространение).
До обучения градиент простой RNN ослабевает за сто шагов в 704 раза, а
градиент по памяти LSTM растёт в 3,72 раза. Жёлтая кривая — та же RNN после
обучения на задаче: она нашла почти тождественный рекуррентный путь и сохраняет
0,919 нормы. Абсолютный уровень у неё низкий, потому что задача решена и потери
почти нулевые; сравнивать нужно наклон, а не высоту.
Время полураспада: перевод ворот в шаги
Число f само по себе ничего не говорит. Переведём его в шаги. Если запись
выключена и forget gate постоянен, то
ct+k=fkct,
и время уменьшения амплитуды вдвое равно
t1/2=lnfln0,5.
Обратный перевод не менее полезен: если нужен горизонт H шагов, то
f=0,51/H=exp(Hln0,5).
Подставим: при f=0,9 получаем 6,6 шага, при f=0,95 — 13,5, при
f=0,99 — 69,0, а при f=0,999 — 692,8. Разница между 0,99 и
0,999 на глаз ничтожна, а память отличается в десять раз. Это и есть
причина, по которой обученные ворота выглядят «неинформативно»: почти все
интересные значения теснятся у самой единицы.
Четыре режима из одной формулы
Пара чисел (f,i) порождает качественно разные поведения одной и той же
координаты:
f≈1,i≈0 — хранить: значение стоит на месте;
f≈0,i≈1 — заменить: старое стёрто, записано новое;
f≈1,i>0 — накапливать: значение растёт как сумма;
f<1,i≈0 — забывать с заданной скоростью;
o≈0 — скрыть память от выхода, не удаляя её.
Последний режим отличает внутреннее хранение от наблюдаемого состояния. Модель
может помнить фазу процесса и не использовать её для текущего прогноза.
Рис. 74.3. Четыре режима одной формулы обновления памяти
Одна и та же формула ct=fct−1+ict при разных воротах.
Накопление с i=0,2 и c=0,2 за 80 шагов доводит c до 4,2,
затухание с f=0,9 сжимает единицу до 0,000218, а замена с f=0
переписывает всё за один шаг. Заметьте: снаружи накопленные 4,2 дают
tanh(4,2)=0,99955 — почти единицу, как и любое большое значение.
Про последнее стоит сказать отдельно. Накопитель не переполняется в смысле
арифметики: c растёт линейно и может дойти до сотен. Но ht ограничен
единицей, поэтому внешне разница между c=4 и c=40 почти незаметна.
Ограниченность выхода маскирует неограниченность внутреннего состояния — и
именно на этом ломаются длинные потоки без сброса.
Забавно, что forget gate — не часть исходной конструкции 1997 года: его
добавили через два года, когда LSTM стали кормить непрерывными потоками. Первая
версия умела помнить, но не умела вовремя забывать.
Эксперимент: запомни первый бит
Проверим тезис честным измерением. Задача: на первом шаге приходит бит (0 или
1), затем D посторонних символов из трёх «болтливых» значений, затем запрос —
и модель обязана назвать первый бит. Мы обучили в numpy, с ручным обратным
распространением, три ячейки с почти одинаковым бюджетом параметров: простую
RNN ширины 64 (4674 параметра), GRU ширины 36 (4718) и LSTM ширины 31 (4776).
Бюджет считается по формуле
P=g(dn+n2+n)+nk+k,g=1,3,4
для RNN, GRU и LSTM соответственно (d — размер входа, k — число классов).
Разброс размеров — 2,18 %, так что сравнение идёт не про число весов. Всё
остальное общее: Adam с шагом 2⋅10−3, батч 96, 1000 шагов, три
случайные инициализации, тест на 2000 свежих последовательностей.
Рис. 74.4. Одинаковый бюджет параметров, разная память
Средняя по трём запускам доля верных ответов; полупрозрачные точки — отдельные
запуски. При D=25 справляются все. При D=50 и D=100 простая RNN даёт
0,83 (в одном запуске из трёх она вообще не сходится и остаётся на уровне
угадывания), а GRU и LSTM решают задачу во всех запусках. При D=200 падают
все: RNN 0,497, GRU 0,494, LSTM 0,668 — то есть LSTM решила задачу лишь в одном
запуске из трёх. Ворота отодвигают границу, но не отменяют её.
Три вывода, которые важнее самих чисел. Первый: разница между RNN и воротами
существует и измерима, но она не бесконечна — граница просто сдвинулась с
полусотни шагов к сотне-двум. Второй: результат сильно зависит от
инициализации, поэтому одна цифра без разброса по seed’ам ничего не значит.
Третий: GRU при паузе 100 не хуже LSTM, хотя ворот у неё меньше — заранее
утверждать «LSTM помнит лучше» нельзя.
Что показывают ворота обученной сети
Обучим LSTM ширины 31 на паузе D=30 до точности 1,00 и посмотрим на её
ворота — не нарисованные от руки, а настоящие. Среднее по координатам значение
forget gate в паузе равно 0,956, что соответствует полураспаду 15,3 шага.
Input gate в паузе равен 0,529, то есть не закрыт: сеть продолжает писать в
память каждый шаг. Output gate тоже держится около 0,617 и слегка
приоткрывается к запросу, до 0,675.
Рис. 74.5. Ворота обученной LSTM и расхождение памяти
Верх: средние ворота обученной LSTM на задаче D=30. Низ: координата 6 памяти,
усреднённая отдельно по примерам с битом 1 и битом 0. Разрыв между кривыми и
есть хранимый ответ: он равен 0,179 сразу после ключа и 5,997 к запросу, то
есть вырос в 33,4 раза. Сеть не «положила бит в ящик и закрыла крышку», а
построила усилитель, который каждый шаг подтверждает решение.
Это неудобная для красивых лекций картина, и именно поэтому её стоит показать.
Учебная схема обещает it≈0 в паузе, а реальная сеть выбрала другую
стратегию: почти постоянное f чуть меньше единицы и постоянную дозапись — и
получила из этого монотонно расходящиеся траектории. Обе стратегии решают
задачу; оптимизация выбрала ту, которая ближе к её инициализации.
Лаборатория ворот
Forget gate, пауза, помехи и сохранённый ответ
График шире экрана — листайте по горизонтали →
Загружается живая иллюстрация…
Ключ приходит на шаге 5, ответ спрашивают на шаге 70. Виджет прогоняет один и
тот же сценарий дважды — с ключом +1 и −1 — и показывает обе траектории
памяти: сохранился ответ или нет, определяется расстоянием между ними, а не
их уровнем. Начните с f=0,95 и убедитесь, что полураспад 13,5 шага не
доносит сигнал через 65 шагов паузы; доведите f до 0,99 и посмотрите,
как одновременно поднимаются обе кривые внизу — память и дальность градиента
меняются одним и тем же числом. Затем закройте o и увидите, что ответ
остаётся в памяти, но исчезает с выхода.
Главный опыт — четвёртый ползунок. Включите шум в паузе при большом i: болтовня
пишется в память теми же воротами, что и ключ, и разделение кривых тает.
Уменьшите i — перестанет записываться и ключ. Постоянными воротами эту задачу
решить нельзя, и в этом весь смысл: в настоящей сети it является функцией
входа и закрывается именно на болтовне.
Не ищите буквальное «это нейрон памяти буквы К». Представление распределено:
одна координата может участвовать в нескольких функциях, а один факт храниться
в нескольких координатах.
Bias forget gate: prior на длинную память
В нашем эксперименте есть деталь, без которой ничего бы не вышло. Смещение
forget gate инициализировано числом 3, то есть в начале обучения
f≈σ(3)=0,953. Мы это проверили прямым экспериментом: при смещении 1 та же LSTM с тем же
шагом обучения не решила задачу с паузой 100 ни разу (0 успехов из 3
инициализаций, точность 0,494, 0,487 и 0,482 — чистое угадывание), а при
смещении 3 решила во всех трёх с точностью 1,00.
Объяснение простое. Инициализация нулевым смещением даёт f≈0,5 и
полураспад в один шаг: сеть стартует с состоянием, которое ничего не помнит, и
градиент, который должен научить её помнить, до нужного места не доходит.
Положительное смещение — это prior: «по умолчанию храни». Слишком большое
смещение вредно симметрично: сеть медленно учится забывать смену режима.
f=σ(b)⟹t1/2=lnσ(b)ln0,5.
GRU: меньше ворот, тот же принцип
Gated Recurrent Unit объединяет память и скрытое состояние:
Update gate zt интерполирует между старым и новым, играя роль сразу f и
i: связка f=1−z, i=z жёстко связывает «сколько забыл» и «сколько
записал». Reset gate rt позволяет вычислить кандидата, глядя на вход и лишь
частично на прошлое.
ht−ht−1=zt⊙(ht−ht−1)
— в такой записи видно, что zt есть скорость движения к новому значению.
При постоянном z развёртка даёт экспоненциальное сглаживание:
ht=zk=0∑t−1(1−z)kht−k+(1−z)th0,
то есть вес наблюдения падает геометрически с эффективной памятью
1/z шагов. При z=0,2 половина пути проходится за 4 шага.
Параметров у GRU меньше: три матрицы вместо четырёх. При равной ширине это
13762 против 18306 в нашей задаче. Но одинаковое число координат не означает
одинаковую ёмкость: при честном сравнении выравнивают хотя бы размер модели
или время обучения, как мы и сделали выше.
Маска, padding и неодинаковая длина
В batch последовательности дополняют padding. Маска mt∈{0,1} должна
сохранять состояние на фиктивных шагах:
Loss также умножают на маску. Иначе короткие примеры получают лишние нулевые
события, а последнее состояние относится к padding, не к данным. Нуль на входе
для сети — не «ничего не произошло», а вполне конкретное наблюдение: она честно
применит к нему ворота и сдвинет память.
Рис. 74.6. Дополнение нулями — это не «ничего не произошло»
Модельный пример при f=0,85: настоящая последовательность длится 8 шагов, к
ней приписаны 12 шагов padding. С маской память в конце равна 1,100, без маски
— 0,156, то есть 85,8 % содержимого съедено нулями. Модель, обученная так,
будет выдавать разный ответ на одном и том же объекте в зависимости от того, с
кем он попал в батч.
В медицинских рядах пропуск измерения несёт информацию: анализ могли назначить
из-за ухудшения. Маска наблюдаемости и время с последнего измерения становятся
входными признаками. Заполнить все пропуски нулём — значит смешать «значение
равно нулю» с «не измерено».
Реальные данные: велопрокат по часам
Проверим ячейку на настоящем ряде: почасовой прокат велосипедов, 17379 часов
наблюдений. Задача — предсказать число поездок в следующий час по окну из
24 предыдущих часов; первые 70 % времени идут в обучение, последние 30 %
(5207 часов) — в тест, без перемешивания. Среднее и разброс для нормировки
взяты только по обучающему периоду: 159,9 и 152,6 поездки.
Порядок сравнения тот же, что в уроке про регрессию: сначала
глупые baseline, потом умные модели.
MAE=N1k=1∑Nyk−yk.
Сезонный прогноз записывается одной строкой и не имеет ни одного параметра:
yt=yt−24.
Прогноз «как час назад» даёт MAE 86,7 поездки; «как ровно сутки назад» — 81,4;
ridge-регрессия по тем же 24 лагам и паре sin,cos часа — 55,5; LSTM ширины
24 — 34,4. Выигрыш над сезонным baseline составляет 57,8 %.
Рис. 74.7. Реальный велопрокат: прогноз на час вперёд
Неделя тестового периода и итоговые MAE на всех 5207 тестовых часах. Сезонный
прогноз повторяет форму суток, но не знает про погоду и про вчерашний уровень;
LSTM видит последние 24 часа и держится ближе. Обратите внимание, где остаётся
ошибка: на резких вечерних пиках.
Разбор по пикам обязателен. Порог «пикового часа» — 90-й процентиль обучающей
нагрузки, 380 поездок; в тесте таких часов 25,6 % (сам по себе тревожный
признак: во второй год проката стало заметно больше, распределение сдвинулось).
На пиках MAE у LSTM равна 53,7 против 131,4 у сезонного прогноза — модель
выигрывает, но её собственная ошибка на пиках в полтора с лишним раза выше
средней. Средняя цифра скрывает, что все интересные часы предсказываются хуже
обычных.
Автоматы Глушкова: состояние как понятие
За двадцать лет до трансформеров и за тридцать до LSTM понятие «состояние»
получило точное определение в советской школе кибернетики. Виктор Михайлович
Глушков, директор Института кибернетики в Киеве, в «Синтезе цифровых
автоматов» (1962) развил теорию абстрактного автомата: пятёрка из множества
входов, множества состояний, множества выходов и двух функций,
qt=δ(qt−1,xt),yt=λ(qt−1,xt).
Сравните с нашей ячейкой: q — это пара (ct,ht), δ — формулы ворот,
λ — выходной слой. LSTM буквально является автоматом Глушкова, у
которого множество состояний стало непрерывным, а функции δ и λ
— дифференцируемыми и обучаемыми.
Эквивалентность состояний определяется через поведение, а не через содержимое:
q∼q′⟺∀x1kλ∗(q,x1k)=λ∗(q′,x1k),
где λ∗ — выход автомата на всей входной строке.
Из этой оптики следуют вполне практические вещи. Задача синтеза автомата —
построить минимальную машину с нужным поведением; задача обучения LSTM —
подобрать веса, чтобы поведение совпало с данными. Понятие эквивалентных
состояний (двух состояний, неразличимых ни при каком продолжении входа) прямо
объясняет, почему бессмысленно требовать от координат памяти «смысла»: у
автомата есть целые классы состояний, ведущих себя одинаково, и обучение вправе
выбрать любой представитель класса.
Что ворота не решают
LSTM всё ещё обрабатывает шаги последовательно, что ограничивает
параллельность: сто шагов — это сто зависимых умножений, и никакая видеокарта
их не совместит. Состояние остаётся фиксированного размера, поэтому объём
памяти не растёт вместе с длиной входа: в сто чисел нельзя положить сто тысяч
токенов без потерь. Дальняя информация может затухнуть или быть перезаписана —
наш эксперимент при D=200 показал это прямо.
Для задач с прямыми связями между далёкими токенами attention
создаёт короткий путь: каждый шаг смотрит на каждый, и длина пути равна
единице, а не T. Для потоковой обработки на устройстве LSTM может быть
дешевле: состояние постоянного размера и один шаг на наблюдение против
квадратичной по длине памяти внимания. Архитектура выбирается по ограничениям,
а не по хронологии моды.
Связь с остаточными соединениями содержательная: и аддитивный
путь ct, и residual x+F(x) дают сигналу возможность пройти без полного
нелинейного переписывания. В обоих случаях речь не о выразительности, а о
проходимости — о том, чтобы производная имела короткую дорогу, как в
уроке об обратном распространении.
Проверки, которые стоит написать
Ошибки в работе с состоянием редко падают с исключением: они тихо портят
метрику. Минимальный набор тестов рядом с кодом.
Контракт сброса. Явно определите событие, при котором h,c обнуляются:
новый пользователь, новый двигатель, разрыв длиннее часа. Сохраните этот
контракт рядом с моделью, иначе offline и production вычислят разные состояния
на одних и тех же данных.
Независимость от порядка. Отсортируйте объекты в батче двумя способами и
сравните прогнозы. Если состояние перетекает между объектами, результат
зависит от технического порядка строк — и такой баг даёт особенно высокий
валидационный score, когда соседние записи относятся к одному устройству.
Длинное накопление. Прогоните последовательность в десять раз длиннее
обучающей и посмотрите на max∣ct∣. Ограниченный ht способен скрывать
рост внутреннего ct; в mixed precision позднее открытие output gate
насыщает tanh и стирает различия, о чём предупреждали авторы forget gate.
Неравномерное время. При irregular sampling добавьте Δt как
признак. Два одинаковых значения, разделённые минутой и сутками, означают
разную скорость процесса. Естественная параметризация — заставить ворота
зависеть от интервала:
ft=σ(⋅)Δt,
что при постоянном шаге совпадает с обычной формулой, а при пропуске в
k шагов забывает ровно столько, сколько забыл бы за k шагов.
Мини-исследование: ворота на смене режима
Сгенерируйте ряд, где скрытый уровень bt постоянен 50–150 шагов, затем
маркер mt=1 сообщает, что уровень заново выбран. Наблюдение
xt=bt+εt,εt∼N(0,0,22).
LSTM должна усреднять шум внутри сегмента и быстро забывать старое после
маркера. Постройте средние ft,it в окне от −10 до +20 вокруг
переключения. Ожидается падение forget gate и рост input gate, но проверяйте
одновременно ошибку: красивый профиль без улучшения прогноза ничего не
доказывает — мы только что видели, как обученная сеть решила ту же задачу
совсем другой стратегией.
Проведите counterfactual: удалите маркер из входа, сохранив сами значения.
Время адаптации должно увеличиться. Затем вставьте ложный маркер без смены
уровня. Если сеть полностью стирает память, возникнет краткий всплеск ошибки.
Так выясняется, как она объединяет явное событие и статистическое
свидетельство. Сравните с задачей об обнаружении разладки, где
переключение ищется по вероятностному критерию: LSTM обучает внутренний
детектор вместе с прогнозом, но не выдаёт калиброванную вероятность смены.
Ворота задают временной масштаб
LSTM делает память управляемой: отдельный аддитивный канал, запись, забывание
и чтение. Формула t1/2=ln0,5/lnf переводит значение ворот в число
шагов и объясняет, почему разница между 0,99 и 0,999 — это разница
между семьюдесятью и семьюстами шагами. Аддитивный путь спасает не память, а
градиент: до обучения он доносит сигнал через сто шагов в 2620 раз лучше, чем
рекуррентная матрица.
Но измерения важнее лозунгов. Ворота отодвинули границу с полусотни шагов к
сотне-двум, а не к бесконечности. Обученная сеть выбрала стратегию, которой не
было в учебнике. На реальном ряде выигрыш дала не столько ячейка, сколько
честное сравнение с baseline, нормировка по train и разбор ошибки на пиках.
Ячейка — это гипотеза о том, какой путь сигнала должен быть коротким; всё
остальное по-прежнему решают данные и дисциплина эксперимента.