Цель
Затевая автоматизацию расчета прогнозов, мы преследовали следующие цели:
- обеспечить единый подход к прогнозированию временных рядов для всех задач прогнозирования;
- централизовать информацию об особенностях прогнозов разных метрик (учесть гиперпараметры, регрессоры);
- сделать добавление прогнозов простым и быстрым.
Далее я расскажу, как мы выстроили процесс прогнозирования. Чтобы объяснение было прозрачнее, договоримся об общих понятиях.
Немного терминов
Задача прогнозирования — формирование численного образа будущего для набора данных, описанного конкретной логикой. Например, прогноз количества регистраций на ближайшие два квартала. Исходные данные задачи прогнозирования — это совокупность данных, регрессоров и гиперпараметров (параметров алгоритмов, значения которых устанавливаются перед запуском процесса обучения).
Набор данных — набор «дата — число» или SQL-запрос, который этот набор формирует. Набор данных состоит из столбцов: ds — дата, y — значение.
Регрессор — временной ряд, корректирующий «вес» значений в наборе данных для учета несистемных влияний среды и других нестандартных условий. Пример регрессора: набор из нулей и единиц, где 1 — рабочий день, 0 — выходной. Пользовательская активность сильно зависит от дня недели. Если какому-то дню в будущем соответствует 0, модель занизит значения для этого дня.
Гиперпараметры — параметры алгоритмов, значения которых устанавливаются перед запуском процесса обучения. Модели машинного обучения с гиперпараметрами склонны к деградации и требуют регулярного тюнинга.
Схема единого прогнозатора «Ванга»
Для выполнения прогнозирования мы используем Python-библиотеку fbprophet, но можно взять и любую другую.
Мы назвали прогнозатор «Ванга» и развернули его на сервере FLASK.
Вместо вынесения прогнозатора в отдельную функцию мы развернули его на отдельной машине. Это позволяет обращаться к единому коду из разных приложений и с разных машин — например, прода и разработчика.
«Ванга» — микросервис, к которому даги прогнозирования обращаются по эндпойнту, состоящему из адреса виртуальной машины и пути к требуемой функции. Вот как выглядит схема работы всей системы прогнозирования.
Что делают даги, выполняющие задачи прогнозирования:
- Забирают исходные данные из аналитического хранилища.
- Отправляют запрос на прогноз в «Вангу».
- Получают прогноз и формируют конечную витрину данных.
- Записывают витрину в хранилище.
Параметры прогнозирования
Параметры задачи прогнозирования хранятся в таблице hyperparameters с такими столбцами:
- changepoint_prior_scale — гиперпараметр prophet, определяющий гибкость тренда, в частности то, насколько сильно тренд меняется в точках смены тренда;
- seasonality_prior_scale — гиперпараметр prophet, контролирующий гибкость сезонности;
- holidays_prior_scale — гиперпараметр prophet, определяющий влияние праздничных дней;
- seasonality_mode — гиперпараметр prophet, устанавливающий аддитивность или мультипликативность сезонности (additive или multiplicative);
- mape — значение ошибки прогнозирования, полученное при этих параметрах;
- sql — код SQL-запроса для формирования набора данных;
- forecastMarker — уникальный идентификатор задачи прогнозирования;
- date — дата подбора гиперпараметров модели;
- regressors — список регрессоров.
Каждая строка таблицы описывает отдельную задачу прогнозирования. Для расчета прогноза «Ванга» принимает набор параметров в виде POST-запроса, например такого:
Для передачи доступен ряд параметров:
- dataframe — переменная типа DataFrame, которая содержит минимум две колонки: ds — даты, y — значения. Обязательный параметр, если не передаётся параметр sql_query;
- sql_query — строковая переменная, которая содержит SQL-запрос, возвращающий набор данных в формате ds — дата, y — численное значение (форматы INT или FLOAT). Должен быть передан или dataframe, или sql_query.
Остальные параметры необязательные:
- forecastMarker — идентификатор задачи прогнозирования. На основе этого значения из таблицы hyperparameters выбираются регрессоры и гиперпараметры. Если параметр не указан, модель старается самостоятельно подобрать оптимальные настройки;
- sender — имя клиента, запросившего прогноз. Используется для ведения лога запросов на прогноз;
- forecasting_period — количество дней вперед, для которого необходимо спрогнозировать значения. По умолчанию 365 дней;
- fake_yesterday — дата, после которой нужно начать прогнозировать значения. Если параметр не передается, выбирается вчерашний день.
Регрессоры
Регрессоры для задач прогнозирования хранятся в отдельной таблице regressors в аналитическом хранилище. Каждый регрессор представлен в ней отдельным столбцом так, чтобы каждой дате временного ряда соответствовало свое значение.
Разные задачи прогнозирования используют свои регрессоры (то есть обращаются к своим столбцам), но все они по умолчанию используют регрессор dow, определяющий вес будней и выходных.
Таким образом, схема таблицы regressors выглядит так:
- ds — дата из прошлого в границах периода, за который есть фактические данные, и на несколько лет вперед;
- dow — регрессор дня недели;
- набор столбцов ситуационных регрессоров. Например, в ковидный локдаун 2020 года некоторые метрики изменились, поэтому начиная с этих дат для соответствующих задач прогнозирования значение регрессора отличается от 1.
Таблица регрессоров может иметь такой вид:
Код микросервиса «Ванга»
Обратиться к «Ванге» можно с помощью POST-запроса из стандартной библиотеки requests.
Код самого прогнозатора состоит из главного файла main.py, принимающего запрос, и файла wanga_classes.py, где описаны класс и функции, необходимые для прогнозирования. По ссылкам приводится урезанная версия кода тех времен, когда мы использовали в качестве аналитического хранилища BigQuery. В дальнейшем по ряду причин мы от него отказались.
Модель принимает только те регрессоры из переданных ей, которые нашлись в таблице regressors. Их список сохраняется в переменной available_regressors. Так что обозначения регрессоров в столбце regressors таблицы hyperparameters должны совпадать с именами соответствующих столбцов в таблице regressors.
В целом же представленный алгоритм — стандартное применение модели fbprophet.Prophet.