Хабр, привет!

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

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

Status Quo Ante Bellum


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

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

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

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

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 — часто хороший и быстрый результат, но в нашем случае порадовал только KNN с точностью 0.44. Случайный лес обычно дает perfomance на небольших выборках, у нас получилась точность 0.48. Ну и, конечно, мы не забыли про Xgboost, тем более после небольшой кросс-валидации мы сумели получить лучший результат — 0.51

image

Concerns


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

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

image

image

Intermediate Results


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

Brand November SL FY19 November SL FY20 SL Delta
Brand1 73% 89% 16%
Brand2 80% 85% 5%
Brand3 63% 93% 30%
Total 73% 89% 16%

Комментарии (7)


  1. gofat
    09.12.2019 13:02

    А вы уверены, что при прогнозировании объема продаж стоит использовать Accuracy (точность)? Кажется, что это не самая лучшая метрика для такой задачи.


    1. mikhail_gavrikov Автор
      09.12.2019 14:02

      Было бы подозрительно показывать результаты не стандартных моделей на не стандартных для компании метриках


      1. gofat
        10.12.2019 10:41

        Ок, я не заметил введенную собственную accuracy, моя невнимательность.
        Но! Есть стандартные обозначения для некоторых метрик, так что такое название сбивает с толку.


  1. SobolevP
    09.12.2019 19:12

    Добрый день! нормальная метрика, но в формуле неточность. Сумму модулей расхождений между фактом и прогнозом нужно поделить на сумму факта (или сумму плана)


    1. mikhail_gavrikov Автор
      09.12.2019 19:47

      благодарю, поправил


  1. swiitch
    10.12.2019 10:53

    Не все тренды можно сгенерить с помощю ML. У меня в рейндже более 70,000 SKU's. Прогон статистики за 10/5/3/1 год через ML дает совершенно несопоставимые результаты, потому что конкуренция на рынке достаточно жесткая и тренды меняются из года в год. Поэтому опытный Demand Planner использует массу инструментов для сегментации товаров и нормализации данных продаж. То что вы очишете Lost Sales (заказы) от дубликатов — это хорошая практика. Еще надо упомянуть об очищении конечных данных и их нормализации (скачки/падения/сезонность… да, сезонность нужно нормализовать, если у вас не только дистрибьюция/ритейл, но и производство, которое имеет capacity contains)


    1. mikhail_gavrikov Автор
      10.12.2019 18:21

      Насчет долгосрочного прогноза соглашусь — на горизонте нескольких лет градиентный бустинг не даёт значительного преимущества.
      Касательно очистки от пиков также соглашусь, для конкретно Хольта-Винтерса явные выбросы мы убирали и расчет велся с учетом очистки — это увеличило точность.
      Сегментация позиций с дальнейшим выбором какую именно модель использовать разумна, но в конкретном кейсе этого не делали, только в планах