Привет! Продолжаю знакомить вас с библиотекой Prophet в качестве инструмента прогнозирования продаж. Первая часть тут.
Функции для критериев качества в нашей прогнозной модели будут выглядеть следующим образом:
Далее выбираем для трех гипер-параметров значения, из которых будем компоновать модели. Параметр seasonality_prior_scale рекомендуется устанавливать в диапазоне до 10 и это и есть значение по умолчанию. Как было сказано ранее, сезонность в нашем рассматриваемом ряду очень выраженная, поэтому логично предположить, что значение параметра должно быть достаточно близко к максимальному. Можно было бы оставить только 10, но попробуем взять также уменьшенное в 2 раза, т.е. 5.
Параметр changepoint_prior_scale изменяется в диапазоне от 0.01 до 0.5 – возьмем минимальное значение (0.01), дефолтное (0.05), максимальное (0.5) и еще два между ними. Последний параметр changepoint_range также имеет смысл брать максимально близким к максимуму – возьмем дефолтное 0.8, также 0.9 и 0.95. Итого набор гипер-параметров будет иметь вид:
Построим модели для каждого из сочетаний (всего будет 30) и выберем лучшую – для которой относительная ошибка выборки будет минимальной.
Лучшей стала модель с параметрами seasonality_prior_scale = 10, changepoint_prior_scale = 0.5 и changepoint_range = 0.95, что было ожидаемо – максимальная величина сезонных колебаний и максимальная доля исторических данных для обучения. Для данной модели построим прогноз.
Относительная ошибка (MAPE) лучшей модели составила 0.98%, абсолютная (MAE) – 14.62.
Для сравнения ошибки худшей модели (с параметрами 5, 0.1, 0.8) составили, соответственно, абсолютная – 39.76 и относительная – 2.67%.
Результаты прогноза также удобно визуально оценить на графиках. Библиотека Prophet имеет собственные средства визуализации, например, с помощью метода plot_components, который позволяет посмотреть отдельно на все компоненты модели: тренд, сезонность, праздники.
На графиках с праздниками (holidays) отображаются корректировки модели в основные периоды с большим количеством нерабочих дней – январь, конец февраля-начало марта, май.
Сезонность очень точно смоделирована – как по дням недели, так и по месяцам.
Помимо этого, с помощью стандартного метода Prophet.plot можно построить график, на котором будут отображены факт, основные расчетные прогнозные значения, а также границы доверительного интервала – на рисунке это области, выделенные светло-синим. Красным цветом выделены точки перелома тренда – тот самый гипер-параметр changepoint prior scale.
Также построим график, на котором отобразим факт только за последние 3 месяца (чтобы сделать его более информативным) и прогноз.
Видим, что прогноз практически бесшовно продолжает ряд фактических значений.
В целом модель демонстрирует вполне удовлетворительные результаты и вполне может служить рабочим вариантом для прогнозирования. Далее построим прогноз отдельно для каждого канала, филиала и сегмента.
Строим итоговую прогнозную модель
Данные по продажам FTTB-FMC хранятся и обновляются на кластере, для выгрузки используем PySpark (версия 3.2.4). Выгружаем данные по продажам за прошедшие 2 года, только FTTB и конвергентные минуса, без переездов, по каналам, филиалам и сегментам. Конкатенируем значения полей канал, филиал и сегмент для создания ключа, по которому будем формировать группы. Это будет основной дата-фрейм.
Как уже упоминалось ранее, все группы по каналу/филиалу/сегменту делятся в сущности на два больших кластера. Первый из них – это группы с четким и ярко выраженным трендом, сезонностью, стабильным количеством продаж – для них мы будем использовать модель с трендом, как рассмотрели выше. Второй кластер– это отсутствие тренда, практически нулевые продажи или мерцающего типа. Для таких групп будем использовать модель без тренда (growth = flat).
Чтобы присвоить каждой группе флаг наличия или отсутствия тренда, считаем среднее значение продаж за последние 3 месяца и, в случае если оно оказывается меньше установленного порогового значения, присваиваем индекс отсутствия тренда. Либо можно сделать наоборот – если значение больше, что тренд наличествует, в данном случае это не принципиально. Получаем таким образом второй дата-фрейм из двух столбцов – ключ группы и флаг наличия тренда.
Прогноз будем строить на 2 месяца вперед – текущий, в данном случае это октябрь и ноябрь 2024. Устанавливаем период для модели.
В данном случае нет необходимости выделять модель и прогноз как мы делали на этапе подбора параметров, тогда функция для расчета прогноза будет иметь вид:
Сначала строим модель для кластера с трендом – всего в нем будет 492 группы, то есть чуть меньше половины.
Затем, от противного, находим перечень групп с отсутствующим трендом и для них также строим прогнозную модель.
Конкатенируем оба дата-фрейма и агрегируем данные по месяцам – прогнозная модель готова. Оценим качество прогноза на визуализации.
Для наглядности отобразим на графике только данные за 12 месяцев, с ноября 2023 по ноябрь 2024, фактические значения – это синяя линяя и прогнозные – сиреневая. На график видно, что прогноз достаточно хорошо описывает имеющиеся исторические данные – есть эффект сглаживания, прогноз повторяет тренд и сезонность.
На этом графике представлены отклонения прогноза от факта за выбранный период. Видно, что максимальные отклонения приходятся на декабрь 2023, когда прогноз оказался ниже и в июле 2024, когда, наоборот, прогноз оказался завышен. В данном случае эти отклонения не стоит считать критичными – например, касательно июля все объясняется структурными изменениями в одном из каналов и связанной с этим практически полной остановкой продаж.
Абсолютная ошибка и относительная ошибка, рассчитанные по агрегированным данным, составили, соответственно, 800.74 и 2.55%.
В целом могу сказать, что прогнозная модель Phophet заслуживает высокой оценки и вполне подходит для моих ежедневных задач.
Итоги
Подводя итог, еще раз отметим достоинства модели Phophet. Самое главное – это интерпретируемость и гибкость. Модель позволяет выбрать функцию для тренда, учесть сразу все варианты сезонности, управлять гипер-параметрами, причем все компоненты модели представлены в «человеко-интерпретируемом» виде. Очень важная особенность – возможность добавлять аномальные дни, причем есть возможность корректировать поведение модели не только в эти указанные дни, но и в заданное количество дней до и после. Подобные вещи позволяют делать модель более гибкой.
В модель Phophet можно добавлять факторы (или регрессоры). В моей задаче мы не использовали регрессоры или, точнее, использовали в качестве фактора только время, но все же считаю важным отметить это преимущество. Например, если прогнозировать выручку или выживаемость, то в качестве фактора можно добавить активную базу абонентов, пользователей услуги и т.п.
Еще одно преимущество Phophet заключается в том, что модель хорошо обучается на коротких временных рядах, менее 100 наблюдений. На самом деле, чтобы построить приемлемый вариант прогноза на Phophet достаточно иметь хотя бы 12 наблюдений (то есть 1 год по месяцам), не всякая прогнозная модель способна на таком объеме исторических данных построить что-то адекватное.
Теперь о недостатках модели. В первую очередь я бы выделила не слишком высокую скорость. Одна итерация считается примерно за 3-5 секунд, соответственно, в моем случае с учетом 1000+ итераций весь расчет занимает больше часа.
Следующий недостаток – это невозможность учесть в явном виде авторегрессию, как, например, это делается в моделях SARIMA. Как вариант, если учитывать авторегрессионные процессы необходимо, то можно использовать библиотеку Neural Prophet, но в рамках просто Prophet авторегрессию не добавить.
И последнее, что относится не только к Phophet, но и вообще к подобному классу моделей – они обладают достаточной степенью устойчивости при небольших или даже средних колебаниях, но, конечно, не могут справиться с каким-то серьезными изломами тренда. Например, во время пандемии в 2020-м многие тенденции оказались нарушены – в некоторых каналах продажи были остановлены. Подобные кризисные явления не способна описать модель, базирующаяся на трендах. Для таких случаев подходят адаптивные модели, вроде экспоненциального сглаживания.
ceoofmsc
Большое спасибо за полезную статью!!