Прогнозирование продаж с использованием библиотеки Prophet, часть 1
Прогнозирование можно считать одной из основных задач аналитика. Прогноз продаж, оттока, выручки, затрат — всех основных KPI развития бизнеса — может потребоваться где и когда угодно, начиная от небольших ad hoc кейсов до масштабных задач вроде процесса бюджетирования на предстоящий год.
Меня зовут Нина Фещенко, я работаю в команде аналитики продаж FTTB-FMC (или иначе — ШПД и ковергентных продуктов) Билайн. В данной статье мы рассмотрим прогнозирование продаж FTTB-FMC для целей ежедневной отчетности.
Начнем с того, что мы понимаем под продажами ШПД и конвергенции.
Для отчетности интерес представляют только новые подключения ШПД — то есть либо чистый сегмент FTTB, либо так называемые «конвергентные минуса» — ситуация, при которой у клиента до продажи не было интернета, а наличие сим-карты в данном случае не существенно. Также как правило не рассматриваем переезды, то есть перенос существующего договора на новый адрес. Это логично, поскольку переезд мы не можем считать новой продажей — он никак не влияет на прирост абонентской базы. Как выбрать прогнозную модель
Выбор прогнозной модели и всех ее параметров можно без преувеличения назвать самым важным и самым трудоемким этапом прогнозирования. Один из основных критериев успеха построения прогноза — это достаточно глубокое понимание своего продукта и его особенностей. Иначе говоря, прежде чем браться за предсказание того как будет развиваться нужный нам показатель в будущем, сначала нужно понять, как он ведет себя в настоящем.
Вот самые основные вопросы, на которые предстоит ответить аналитику перед началом построения прогнозной модели:
Однородны ли данные — можем ли мы построить один прогноз для всей совокупности данных или нужно предварительно разделить данные на группы и строить отдельные прогнозы для каждой группы
Имеется ли в динамическом ряду тренд
Имеется ли сезонность
Какую глубину данных оптимально использовать.
В моем случае, в контексте продаж FTTB-FMC, ответы на вопросы будут следующими.
Однородность — нет, построить один общий прогноз точно не получится. В отчетности продажи представлены всегда в разрезе каналов и филиалов, а также разделены на сегменты: FTTB и FMC. В каждом канале продаж есть свои особенности — есть так называемые «управляемые» каналы (D2D, Dealers, Web-партнеры), есть пассивные каналы (например, Inbound), в одних каналах просматриваются очень четкие тенденции, в других будет всего десяток продаж за несколько месяцев. Кроме того, свои особенности накладываются также исходя из деления по филиалам — один и тот же канал в одном филиале развивается достаточно стабильно и предсказуемо последние 5 лет, а в другом — только начал развиваться в прошлом году или, наоборот, был закрыт. Очевидно, что прогноз нужно строить отдельно для каждого значения канал-филиал-сегмент и таких значений наберется более тысячи штук.
Тренд. Как было сказано выше, однозначного ответа здесь нет, для каждой группы по-разному, но в большинстве случаев считаем, что тренд есть — даже если нет ярко выраженного движения вверх или вниз.
Сезонность — да и очень четкая. Во-первых, имеется сезонность внутри года — спад в январе и мае (следствие большого количества выходных дней), также спад в летние месяцы (период отпусков), рост продаж всегда в последнем месяце квартала и особенно в сентябре (своеобразная компенсация летнего спада).
Данные тенденции сохраняются даже в период пандемии, что говорит о том, что модель непременно должна их учитывать.
Кроме этого, есть очень четкая сезонность по дням недели — спад в выходные дни, взлет продаж в понедельник (здесь аналогия с взлетом сентября по отношению к лету) и постепенное снижение с небольшим подъемом в пятницу.
Глубина данных. Казалось бы, здесь ответ очевиден — чем больших период ретроспективных данных мы используем, тем более точный прогноз можем получить. Однако не все так однозначно. На продажи влияет большое количество факторов, в том числе структурных, и слишком давняя история может просто потерять свою актуальность. Объем продаж FTTB-FMC сейчас однозначно ниже, чем 5 лет назад и даже чем 3 года назад. И здесь не будет уместно говорить о нисходящем тренде, просто 3–5 лет назад основной задачей было наращивание объемов, а сейчас — в большей степени повышение качества продаж и снижение фрода. Для нашего ряда, с учетом особенностей продукта и его развития, оптимальная глубина ретроспективных данных составит 2 года.
В настоящее время существует достаточно большое количество моделей анализа динамических рядов, начиная от простейшей модели линейной регрессии и заканчивая продвинутыми моделями машинного обучения. Каждая модель имеет свои преимущества и недостатки, я сейчас не буду на этом подробно останавливаться. Для своих целей прогнозирования я выбрала модель Prophet, рассмотрим ее более подробно.
Модель Prophet
До этого мой опыт прогнозирования включал в себя только построение «ручных» моделей в Excel. Мои модели обладали достаточно высокой степенью точности и устойчивости, включали в себя и сезонность, и случайные параметры в виде авторегрессионного процесса и доверительный интервал. Теперь мне предстояло использовать имеющийся опыт для построения современной и функциональной модели на Python или, если точнее, на PySpark — поскольку исходные данные по продажам у нас хранятся и ежедневно обновляются на кластере (DMP) и обращение к ним происходит с использованием Spark.
На первом этапе мне требовалась не только достаточно проверенная и надежная модель, но и относительно простая для понимания. Я выбрала Prophet.
Prophet — это библиотека прогнозирования временных рядов с открытым исходным кодом, разработанная data science командой Facebook. Это достаточно мощный, гибкий и при этом простой в использовании инструмент для прогнозирования с интуитивно понятным, «человеко-интерпретируемым» набором параметров. Кроме того, модель Prophet хорошо работает с динамическими рядами, в которых присутствуют сильные сезонные эффекты (это как раз то что мне нужно), устойчива при работе с пустыми значениями и выбросами.
Библиотека доступна помимо Python также и для R, но мы будем рассматривать только Python.
Прогнозная модель Prophet представляет собой аддитивную регрессионную модель, состоящую из следующих компонент:
,
где:
y — прогнозное значение;
g — долговременная тенденция развития (тренд) в виде линейнойили логистической функции;
s — сезонная компонента, включает все виды сезонности (годовая, недельная);
h — эффект аномальных дней, например праздников (опциональный параметр);
e — ошибка модели, вся информация, не учитываемая моделью. Предполагается, что имеет нормальное распределение.
С точки зрения выбора параметра для тренда наши данные можно разделить на 2 группы — где тренд имеется и где отсутствует. При этом под наличием тренда мы будем понимать только наличие линейного тренда. Логистическая функция, при которой с увеличением показателя снижается темп его роста, не подходит для описания продаж. Точнее, подходит для каких-то специфических случаев, например, продаж в рамках маркетинговых акций, но не в нашем случае. Таким образом в нашей модели параметр growth принимает значения linear или none. Линейная функция в модели Prophet выглядит следующим образом:
где:
k — коэффициент роста;
δ — параметр для корректировки коэффициента роста;
m — параметр смещения;
γ — параметр служит для того, чтобы сделать функцию непрерывной.
Что касается сезонности, то она в наших данных есть, причем различных видов — как годовая, так и месячная, и недельная. Опять же это справедливо для случаев наличия тренда. В модели Prophet сезонность моделируется с помощью рядов Фурье. Все виды сезонности принимают значения True или False.
Праздничные дни также оказывают существенное влияние на объемы продаж — в Новогодние праздники, в майские тоже продажи практически останавливаются. Так что данную компоненту модели обязательно включаем. Моделируем перечень необходимых дат с помощью модуля make_holidays.
Также помимо основных параметров, модель Prophet позволяет задавать гипер-параметры. Их предусмотрено достаточно много, мы будем использовать только самые основные, а именно:
changepoint_prior_scale — параметр, с помощью которого задается количество «переломных моментов» динамического ряда, чем выше значение — тем больше таких точек перелома. По умолчанию равно 0.05, рекомендуемый диапазон от 0.001 до 0.5;
seasonality_prior_scale — параметр, задающий величину сезонных колебаний, чем выше значение — тем сильнее колебания. Значение по умолчанию 10.
changepoint_range — доля исторических данных, в пределах которых меняется тренд. По умолчанию 0.8 (то есть точки перелома формируются на основании первых 80% ретроспективных данных), диапазон — от 0 до 1.
Подбираем параметры для нашей модели прогноза продаж
Для простоты на этапе подбора параметров будем рассматривать агрегированные данные, то есть суммарный объем продаж по всем каналам и филиалам, и обоим сегментам. Это будет оправдано, поскольку в сущности мы подбираем параметры только для тех групп, где есть линейный тренд –, а они составляют порядка 80% общего объема продаж.
На этом этапе важно убедиться, что дата имеет формат datetime, а данные отсортированы по дате.
Устанавливаем период, на который делаем прогноз — на три месяца вперед, то есть в данном случае прогнозируем 4 квартал 2024 года, с октября по декабрь.
Переименовываем колонки дата фрейма — поле с датой продажи должно называться ds, а поле с суммой продаж — y. Разделяем дата фрейм на обучаемую часть (в сущности это все исторические данные) и прогноз. Тогда функция для построения прогнозной модели будет выглядеть следующим образом.
Функция принимает на вход тип тренда, лист с датами праздничных дней и три гипер-параметра: changepoint_prior_scale, seasonality_prior_scale
и changepoint_range
.
Функция для построения собственно прогноза будет принимать на вход прогнозную модель, полученную на предыдущем этапе:
Для оценки качества модели можно использовать разные критерии, в данном случае будем использовать абсолютную и относительную ошибку выборки.
Абсолютная ошибка выборки или MAE (Mean Absolute Error) представляет собой разницу по модулю фактических и прогнозных значений:
Относительная ошибка выборки или MAPE (Mean Absolute Percentage Error) — это отношение абсолютной ошибки к фактическим значениям:
MAPE считается более удобной в использовании за счет того, что относительная величина не зависит от размерностей и позволяет сравнивать даже разные наборы данных. В нашем случае будет интересно оценивать как абсолютную так и относительную ошибку.
В следующем посте мы поговорим о функциях для критериев качества в нашей прогнозной модели и подведём итоги использования Prophet.