Прогноз нейросетями: LSTM и обзор

Разбираемся, как нейросети прогнозируют ряды, что такое LSTM и когда тяжёлая артиллерия действительно нужна.

LSTM — рекуррентная нейросеть с механизмом «памяти» (ячейкой состояния и вентилями), способная улавливать длинные зависимости в последовательностях.

Зачем нейросети для рядов

ARIMA и сглаживание линейны и одномерны. Когда зависимости нелинейны, рядов много и они связаны (тысячи товаров, сотни магазинов), а признаков целый ворох, нейросети начинают выигрывать. Они учат сложные паттерны напрямую из данных. Но это дорого: нужно много данных, тщательная настройка и инфраструктура. Для одного короткого ряда нейросеть почти всегда проигрывает простому Хольту-Винтерсу.

Ключевое слово здесь — масштаб. Если у вас один ряд продаж за два года, нейросеть не на чем учиться: классика обыграет её и по точности, и по стоимости. Но если у ритейлера тысячи товаров в сотнях точек, картина меняется. Спрос на молоко в одном магазине похож на спрос в соседнем; продажи зонтов коррелируют с дождём; новый товар без истории можно прогнозировать по поведению похожих товаров. Одна большая нейросеть учится сразу на всём этом массиве и переносит знание между рядами — это называют global-моделью, и для классики такой трюк недоступен.

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

Как ряд подаётся в сеть

Рекуррентную сеть кормят окнами-последовательностями: берут L подряд идущих точек как вход и следующую точку как цель. Скользящее окно нарезает ряд на множество таких обучающих примеров.

series = [1, 2, 3, 4, 5, 6, 7, 8]
L = 3                                # длина входной последовательности

samples = []
for i in range(len(series) - L):
    x = series[i:i+L]
    y = series[i+L]
    samples.append((x, y))

for x, y in samples:
    print("вход:", x, "-> цель:", y)

Вывод:

вход: [1, 2, 3] -> цель: 4
вход: [2, 3, 4] -> цель: 5
вход: [3, 4, 5] -> цель: 6
вход: [4, 5, 6] -> цель: 7
вход: [5, 6, 7] -> цель: 8

Так одномерный ряд превращается в набор пар «последовательность → следующее значение». Сеть учится по этим парам, а на инференсе ей подают последние L точек и получают прогноз. Реальный код использует PyTorch/TensorFlow, который в браузере не запустить.

Длина окна L — важный гиперпараметр. Сделаете окно слишком коротким — сеть не увидит сезонный цикл и не сможет его учесть; слишком длинным — резко вырастет число параметров и потребность в данных, а обучение замедлится. Обычно L выбирают так, чтобы окно покрывало хотя бы один полный период сезонности: для дневного ряда с недельным ритмом это минимум 7 точек, а лучше несколько недель. Заметьте также, что нарезка окон сокращает выборку на L точек — короткому ряду после такой нарезки попросту не из чего учиться.

import torch.nn as nn

class Forecaster(nn.Module):
    def __init__(self, hidden=32):
        super().__init__()
        self.lstm = nn.LSTM(input_size=1, hidden_size=hidden, batch_first=True)
        self.head = nn.Linear(hidden, 1)
    def forward(self, x):
        out, _ = self.lstm(x)
        return self.head(out[:, -1, :])   # прогноз по последнему шагу

Архитектура минимальна: слой LSTM прокатывает последовательность и хранит внутреннее состояние, а линейная «голова» превращает финальное состояние в одно число — прогноз. Параметр hidden задаёт размер памяти сети: больше нейронов — выше ёмкость и риск переобучения, меньше — модель проще и устойчивее. Брать прогноз именно из последнего шага (out[:, -1, :]) логично: к нему сеть уже «прочитала» всю историю окна и накопила нужный контекст.

Семейство архитектур

МодельИдея
LSTM / GRUрекуррентная память последовательности
1D-CNNсвёртки по времени, ловят локальные паттерны
Transformer (Informer и др.)внимание на длинные зависимости
N-BEATS / NHITSспециализированы под прогноз рядов

LSTM и GRU — классика рекуррентного подхода, надёжная, но медленная из-за последовательной обработки шаг за шагом. Свёрточные 1D-CNN считаются параллельно и хорошо ловят локальные формы вроде коротких всплесков. Трансформеры через механизм внимания связывают далеко отстоящие точки напрямую и сейчас задают тон в длинногоризонтном прогнозе. А N-BEATS и NHITS созданы специально под временные ряды и нередко бьют универсальные архитектуры на бенчмарках, оставаясь при этом частично интерпретируемыми.

Как работает под капотом

LSTM хранит ячейку состояния, проходящую сквозь время почти без изменений, и три вентиля (забывания, входной, выходной), которые решают, что запомнить и что выдать. Это спасает от затухания градиента, мучившего простые RNN, и позволяет помнить события за десятки шагов. Обучение идёт обратным распространением во времени: ошибка прогноза прокатывается назад по всей развёрнутой последовательности.

Разберём роль вентилей чуть подробнее. Вентиль забывания решает, какую долю старой памяти стереть; входной — сколько новой информации с текущего шага записать; выходной — что из накопленного отдать наружу как ответ. Каждый вентиль — это маленькая обучаемая функция, выдающая числа от 0 до 1, то есть «ворота», которые сеть сама учится открывать и закрывать в нужный момент. Благодаря почти линейному пути ячейки состояния градиент при обратном распространении не затухает экспоненциально, как в простых RNN, и сеть реально дотягивается до зависимостей за многие шаги назад — например, до прошлого понедельника или до того же дня в прошлом году.

Частые ошибки

  • Брать нейросеть для одного короткого ряда — простые модели тут точнее и дешевле.
  • Забыть нормировать вход — сети чувствительны к масштабу признаков.
  • Нарезать окна с заглядыванием в будущее — та же утечка, что и везде.
  • Считать параметры нормировки по всему ряду, включая тест, — статистики из будущего утекают в обучение.
  • Гнаться за сложной архитектурой, не проверив сначала простой бейзлайн на честном бэктесте.

Итоги

  • Нейросети оправданы при множестве связанных рядов, нелинейностях и обилии признаков.
  • Ряд подаётся окнами-последовательностями «вход → следующая точка».
  • LSTM помнит длинные зависимости через ячейку состояния и вентили.
  • Длину окна выбирают под период сезонности, а перед обучением входы нормируют.
Проверьте себя
1. Как обычно подают временной ряд в рекуррентную сеть (LSTM)?
AЦеликом одним числом
BОкнами-последовательностями: L точек на вход, следующая — цель
CВ случайном порядке
DТолько среднее ряда
2. Когда нейросети для прогноза обычно НЕ оправданы?
AПри тысячах связанных рядов
BДля одного короткого ряда — простые модели точнее и дешевле
CПри сильной нелинейности
DПри множестве признаков