Какие способы валидации моделей временных рядов исключают просмотр в будущее при обучении
Что проверяют
Понимаете ли вы, что обычный KFold с перемешиванием на временном ряде даёт красивую и бесполезную метрику: модель учится на будущем и проверяется на прошлом. Следом почти всегда спрашивают, откуда ещё может протечь будущее, кроме самого разбиения.
Как отвечать
Базовое правило: обучение всегда строго раньше проверки. Дальше назовите схемы:
- отложенный хвост (holdout): последний отрезок ряда уходит в тест. Просто, но оценка держится на одном периоде и зависит от его сезонности;
- расширяющееся окно (expanding window, walk-forward): несколько фолдов, обучающая часть растёт, тест сдвигается вперёд. Так по умолчанию работает
TimeSeriesSplitиз scikit-learn; - скользящее окно (rolling window): обучающая часть фиксированной длины едет вперёд, старые данные выпадают. Полезно, когда закономерности устаревают. В
TimeSeriesSplitэто задаётся черезmax_train_size; - зазор (gap, embargo): между обучением и тестом пропускается интервал не короче горизонта прогноза и окна признаков. В
TimeSeriesSplitдля этого есть параметрgap, в финансовых задачах используют purged k-fold с эмбарго.
Отдельно скажите про утечки внутри признаков. Скейлер, импьютер и target encoding обучаются только на трейне своего фолда, поэтому вся предобработка живёт внутри Pipeline. Скользящие средние считаются со сдвигом shift(1), а не с center=True. Признак берётся в том виде, в каком был доступен на момент прогноза: данные, которые приходят с задержкой на день, и в обучении должны отставать на день. Гиперпараметры подбираются тоже на временных фолдах, а финальный тест остаётся нетронутым.
Где спотыкаются
Делят по времени, но предобработку делают на всём датасете до разбиения. Нормировка по полному ряду уже знает будущие среднее и дисперсию.
Забывают про горизонт. Если модель прогнозирует на 7 дней вперёд, а тест начинается сразу за последним днём трейна без зазора, лаговые признаки перекрываются, и метрика завышается.
При множестве рядов (магазины, товары) делят по идентификатору, а не по дате. Тогда модель видит соседний магазин в том же будущем месяце и выучивает общий тренд, которого на проде не будет.