Прогноз — это промежуточный продукт
Торговая сеть заказывает прогноз спроса, но платит за другое: за то, чтобы товар был на полке и при этом не пришлось списывать остатки. Между прогнозом и заказом стоит решение, и именно оно определяет деньги.
Это различие мы вынесли в самое начало проекта, потому что оно меняет постановку задачи. Модель, идеальная по среднему отклонению, может стабильно проигрывать по деньгам — если ее ошибки распределены не в ту сторону.
Недовоз и перевоз стоят разного
Не хватило товара — потеряна маржа с непроданной единицы, а иногда и покупатель, ушедший к конкуренту. Привезли лишнего — заморожены деньги и место на полке; для скоропорта все жестче: излишек списывается в ноль.
Поэтому функция ошибки в обучении асимметричная, и коэффициенты у нее свои для разных товарных групп. Для длительного хранения перевоз дешев и модель может быть щедрой. Для свежей продукции штраф за излишек высокий, и прогноз сознательно смещается вниз.
Именно эта настройка дала основную часть из минус 27% потерь. Точность как таковая улучшилась скромнее — на восемнадцать процентов по среднему отклонению.
Прерывистый спрос ломает привычные метрики
Большая часть позиций в матрице сети продается редко: ноль, ноль, ноль, две штуки, снова ноль. На таких рядах привычные показатели точности либо неопределены, либо вводят в заблуждение — модель, всегда предсказывающая ноль, выглядит превосходно.
Для этой части ассортимента считается не число продаж, а вероятность спроса на горизонте пополнения. Решение о заказе принимается из нее и стоимости хранения. Оценка качества тоже другая: сколько раз товара не оказалось на полке при наличии спроса.
Промо перевешивает историю
Акция меняет спрос кратно, и модель, обученная на истории, где акции размазаны, будет ошибаться в обе стороны: перезакажет после промо и недозакажет в промо.
Поэтому календарь акций — обязательный вход модели, а не опция. Отдельно учитывается каннибализация: скидка на один товар проседает продажи соседнего по полке. Без этого сеть исправно завозит лишнее по соседним позициям каждый раз, когда объявляет акцию.
Почему полный прогон укладывается в минуты
420 тысяч сочетаний товара и точки — это не 420 тысяч отдельных моделей. Наивная схема «одна модель на ряд» дает часы работы и невозможность обновлять прогноз чаще раза в сутки.
Вместо этого работает небольшое число моделей, обученных на всей матрице сразу, с признаками товара, точки и календаря. Расчет векторизован и идет пачками. Плюс иерархия: агрегированный уровень категории и региона считается отдельно и служит опорой для разложения на нижние уровни, где данных мало и шум велик.
Минуты вместо часов дают практическое следствие: прогноз можно пересчитать по факту утренних продаж, а не жить со вчерашним.
Данные, которых обычно нет
Три вещи, за которые идет борьба на любом таком проекте:
- Отсутствие товара на полке. В истории продаж ноль продаж и ноль остатка выглядят одинаково, а смысл противоположный. Без этой отметки модель учится на заниженном спросе и воспроизводит дефицит.
- Реальные даты поставок. Плановый график и факт расходятся, а горизонт пополнения считается по факту.
- Списания и их причины. Это прямая обратная связь по перезаказу.
Если этих данных нет, первый этап проекта — их сбор, и мы говорим об этом до старта.
Горизонт считается от поставщика
Прогноз имеет смысл ровно на том горизонте, на котором принимается решение о заказе. Если поставка приходит через три дня и заказ размещается раз в неделю, прогнозировать нужно на десять дней вперед. Цифра берется из договора с поставщиком и графика логистики, и для разных групп товара она разная.
Это звучит очевидно и регулярно ломается на практике: в сети встречались категории, где прогноз строился на сутки, а физически заказ доезжал за неделю. Модель при этом была точной, а полка все равно пустела. Первым делом в проекте мы свели матрицу горизонтов по категориям — до всякого обучения.
Что осталось за человеком
Категорийный менеджер видит рекомендованный заказ и может его изменить, но каждое изменение фиксируется. Через месяц такой работы появляется статистика: где человек систематически правит модель в одну сторону. Иногда это повод исправить модель, иногда — обнаруженное знание, которого в данных нет вообще. Оба исхода полезны.
Направления рядом — предиктивная аналитика и эксплуатация ML-моделей; оценка бюджета — калькулятор.