Pull to refresh

Про Планирование Спроса, Holt-Winters и XGboost

Reading time5 min
Views4.6K
Хабр, привет!

На сайте много статей про прогнозирование sell-outs различных категорий FMCG, в то же время другие товарные категории не так популярны. Кроме того, обычно исследуется проблематика retail с прогнозом на несколько дней вперед, но не дистрибьютора с прогнозом на 2 месяца вперед – хотя последний заинтересован в качественном прогнозе чаще даже более, чем ритейлер. Как дополнительный вызов стоит расценивать консервативность значительной части дистрибьюторов в смысле выбора технологий прогнозирования. Достаточно легко себе представить практику прогнозирования продаж средней руки компании: сбор продаж из SAP + мастер-данных в рукотворном Excel Tool, автоматизация в таких случаях ограничивается достаточно простым методом прогнозирования, который недалеко уходит от среднего/линейного тренда с rocket science в виде HoltWinters.

Так получилось, что по долгу службы я столкнулся с производителем бренда недорогой декоративной косметики (порядка 500 SKU) и увидел грустные последствия консервативного прогнозирования в виде низких KPI. Следовало внести небольшие изменения в систему планирования, в том числе в процесс прогнозирования и далее я расскажу о своих изысканиях.

Status Quo Ante Bellum


Основной головной болью бренда на протяжении нескольких лет являлся крайне низкий уровень сервиса (УС = Отгружено / Заказано), значительно ниже, чем в среднем по компании, что усугублялось прогнозом на основе средних продаж ( Прогноз = Средние продажи ). Замкнутый круг: клиент заказывает объемы, не получает полных количеств и в следующий раз приходит с увеличенной потребностью, а мы планируем будущее только по удовлетворенной потребности.

Исходя из этого, решено было прогнозировать не продажи, а заказы, очищенные от повторов (т.е. если клиент хочет 100 штук и заказывает каждую неделю, то мы предполагаем, что спрос в месяц 100 штук, а не 400), поэтому здесь и далее продажами мы будем называть очищенные от дублей заказы. После улучшения уровня сервиса разница между терминами нивелируется. В качестве оценки точности прогноза в компании используется формула (Точность прогноза = (1 — Сумма модулей расхождений между фактом и прогнозом)/Прогноз), её будем использовать и мы. Важный момент: прогноз в данном случае это прогноз с лагом 2, т.е. если мы оцениваем точность в октябре, то мы сравниваем продажи октября с прогнозом, который сделан в августе. Принято считать, что результат более 35% можно трактовать как удовлетворительный. Кстати, здесь стоит отметить, что мы не ожидали, собственно, роста точности в первое время — мы ожидали роста уровня сервиса и результаты будем оценивать именно на основе качества отгрузок товаров клиентам.

Над выборкой для обучения не пришлось долго потеть – хотя в компании нет аналитического DWH, но есть выгрузка заказов по месяцам, которую небольшой цикл на Python собрал и очистил. Аналогичным образом мы получили мастер-данные. События и промо пришлось проигнорировать в расчетах из-за излишней зашумленности (мы опасались добавить больше шума, чем полезной информации), так как наиболее крупный ритейлер периодически проводил промо без договоренностей и уведомления, оценка объемов событий примерная и т.д.

В качестве модели мы решили использовать 3 ветки — Naive, Exponential Smoothing и MachineLearning.

Naive Forecasting


Основная причина, по которой наивное прогнозирование все еще в ходу — простота интерпретации для человека. Действительно, если в компании принято разбирать каждый код подробно, по методике 5 Why, то прогноз по среднему подходит как нельзя лучше. Клиент заказывает 10 штук в среднем в месяц? Логично, что он закажет 10 штук в следующем месяце. Результат не такой, как мы ожидали и клиент заказал 50 штук? Вероятно, клиент просто не умеет прогнозировать/сломался автозаказ/робот взбесился и т.д., следует внедрять Joint Forecasting и обмениваться файлами, дабы снять напряжение и улучшить точность прогноза (конечно, шутка, но с долей правды).

Чтобы добавить немного актуальности методам, мы предположили, что сезонность товаров идентична сезонности категории (для выявления сезонности использован пакет statmodels, на картинке результат по 3 основным).

image

Мы взяли 4 метода — средняя и медиана по всей истории продаж (точность 0.32 и 0.30 соответственно) и по последним 6 точкам (0.36 и 0.26). 0.36 будет нашим бенчмарком — в дальнейшем мы обязаны получить результаты лучше.

ESM Forecasting


Экспоненциальное сглаживание часто выступает пределом мечтаний в планировании спроса и легко понять почему. Оценки точности в лоб показывают минимум сопоставимые результаты у ESM и ML по уровню точности, они включены во все промышленные системы прогнозирования (JDA, Oracle RDF и т.д.), расчет быстрее и проще интерпретируется — поэтому-то классика живее всех живых. С другой стороны, результат может быть не совсем честным из-за недостаточной подготовки фич.

Для прогнозирования мы использовали все тот же пакет statmodels. Для начала мы взяли класс Holt для всей истории продаж с очищенной групповой сезонностью и для последних 6 точек (точность 0.34 и 0.37).

Далее мы разделили SKU на 2 группы — товары с длинной историей мы прогнозировали классом HoltWinters, а для короткой истории оставили Holt по 6 точкам. Результат получился значительно лучше — 0.44, это легко объяснимо. Если на верхнем уровне кажется, что все товары братья-близнецы, то, спускаясь на сабкатегории, мы можем увидеть различия.

image

ML Forecasting


Основным минусом стандартных методов является недостаток глубины расчетов, т.к. мы не используем всю доступную информацию. Например, история событий: обычно, в классическом подходе, мы должны вычесть из истории случившиеся пайпы, сделать прогноз базовой линии и добавить планируемые пайпы с соответствующей календаризацией. В случае недостаточно точного учета событий, результат может оказаться разочаровывающим (в случае Holt-Winters у нас получилось — 5 п.п. к точности). Можно представить много причин — например, КАМ категории занижает объемы для того, чтобы показать перевыполнение и получить бонусы. Если мы перейдем от подхода (Прогноз = Базовая линия + Пайпы) к прогнозу, основанному на фичах, то мы сможем дополнительную часть информации, доступной нам. Для этого мы собрали список из 50 фич (цены, мастер-данные, продажи, сплит клиентов и т.д.). Из библиотеки Sklearn мы взяли базовые Lasso/Ridge/KNN Regressor, которые часто дают quick win, но в нашем случае порадовал только KNN с точностью 0.44. Случайный лес имеет хороший perfomance на небольших выборках, в нашем случае точность равна 0.48. Ну и, конечно, мы не забыли про Xgboost, который после небольшой кросс-валидации выдал лучший результат — 0.51. Ниже график с точностью каждой модели

image

Concerns


Какие могут быть консерны относительно использовании ML в прогнозировании продаж? К примеру, обратная связь: ряд еком и оффлайн ритейлеров использует нейронные сети и градиентный бустинг и периодически пугает безумными заказами. Да, конечно, если ритейлер будет измерять аккуратность прогноза, то результат может быть оптимистичным, но это в определенной степени самоисполняющееся пророчество: если ошибка, то включается распродажа/черная пятница/день рождения сети и т.д.

Поэтому для нас важно показать, что результат Xgboost не только точнее, но и стабильнее (а не случайная рулетка, как может показаться неподготовленному планеру). Для этого мы сравнили распределения ошибок HoltWinters и Xgboost и удостоверились, что результаты последнего имеют более плотный центр вокруг нуля и light-tailed

image

image

Intermediate Results


С момента начала написания статьи/первого run прогноза еще 2 бренда декоративной косметики были переключены на Xgboost, в связи с позитивными результатами. На конец ноября средний рост уровня сервиса составил + 16%, т.е. был достигнут средний уровень компании

Brand SL FY19 November SL FY20 November SL Delta
Brand1 73% 89% 16%
Brand2 80% 85% 5%
Brand3 63% 93% 30%
Total 73% 89% 16%
Tags:
Hubs:
Total votes 6: ↑6 and ↓0+6
Comments7

Articles