Машинное обучение для прогнозирования продаж в Nestlé

Я хотел бы рассказать вам о прогнозировании продаж с точки зрения Nestlé. Я покажу вам идеи/методологию нашего подхода. Однако, если вы хотите что-то из него использовать, приглашаю вас на GitHub, где мы показали реализацию этого проекта на Python. Наш подход был представлен на Саммите по науке о данных. Примеры на реальных данных, но, разумеется, обезличены. Я работаю в центре Data Science Hub в Nestlé. Используя Python или R, я реализую модели машинного обучения для поддержки процессов принятия бизнес-решений. Центр Data Science Hub – это аналитическая группа Nestlé, которая поддерживает Европу, Северную Африку и Ближний Восток.

Повестка дня

Повестка дня этой статьи состоит в том, чтобы начать с бизнес-проблемы, затем понимать данные, преобразовывать их (Разработка функций), я собираюсь закончите аспектами обучения модели.

Если вы хотите увидеть оценку, то есть оценку модели на тестовом наборе, сравнение прогноза с реальными значениями, то эта часть находится в решении на GitHub.

Понимание бизнеса

➔ Прогнозирование продаж

Правильный прогноз важен с точки зрения бизнеса. Если наш прогноз предполагал, что продано меньше продукции, чем фактический спрос, мы теряем прибыль. С другой стороны, если наш прогноз был завышен, поэтому мы на самом деле продаем меньше продуктов, мы также теряем, мы несем стоимость запасов продукта или, что еще хуже, срок годности наших продуктов истекает. Один плохой прогноз имеет последствия для бизнеса, производства и логистики.

Продажи можно разделить на Продажи и Продажи.

Продажи — это количество продуктов, которые производитель (в нашем случае Nestlé) продает розничному продавцу, а Продажи — это количество продуктов, проданных розничным продавцом конечным покупателям. . Мы, как производитель, заинтересованы в Продаже. Здесь уже видна взаимосвязь между Продажи и Продажи. Розничные продавцы не будут продавать товары, если мы их не поставляем. Более того, если они хотят продавать больше, потому что планируют продвижение нашего продукта, они также должны заказывать у нас больше товаров.

Условия бизнеса и производства требуют еженедельного прогноза продаж на срок до 3 месяцев или в среднем на следующие 12 недель. Прогноз должен быть еженедельным, потому что производство или логистика планируются еженедельно.

Прогнозирование продажи

➔ Зачем продавать в будущем?

Мы уже знаем, зачем бизнесу нужен хороший прогноз, давайте посмотрим на данные и проведем Eисследовательский анализ данных, чтобы лучше их понять. .

Продажи суммируются по неделям — столбец PERIOD_TAG, который сообщает нам о конкретной неделе в году.

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

Продажи можно разделить на:
- отгрузки — фактические продажи, то есть количество товаров, доставленных продавцу.< br /> - заказы — фактический спрос, количество товаров, заказанных у нашего покупателя. Иногда может случиться то, о чем я уже говорил, то есть количество заказанных товаров превышает количество реально проданных товаров. Это может быть связано, в том числе, с заниженным прогнозом.

Следующая переменная — Sell Out, которая представляет собой количество товаров, проданных из розницы конечным покупателям, сколько мы как общество покупаем в магазинах.

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

Продажа продуктов с течением времени — это не что иное, как временной ряд. Продажа нескольких продуктов для разных розничных продавцов — это несколько временных рядов.

Давайте рассмотрим пример продажи одного продукта для одного из ритейлеров.

На первой диаграмме показано количество заказанных товаров. Как видите, скользящая средняя во времени постоянна, но в какие-то недели она зависима — отсюда и значительный рост.

На следующем графике мы добавляем Sell Out и видим, что он отстает от Sell In. Если мы увидим значительный рост количества заказов товаров нашими покупателями, то можно ожидать, что в среднем в следующие 3–4 недели магазины этого покупателя будут продавать больше товаров, чем обычно. Продолжительность задержки Sell Out и Sell In может варьироваться от продавца к продавцу.

На третьем графике добавляем количество доставленных товаров, как я уже говорил, оно не всегда равно количеству заказанных товаров. Но здесь мы можем увидеть и другие зависимости, например, если мы не доставим столько, сколько заказывали, то, возможно, в следующие недели наш клиент повторит заказ.

На последнем графике представлены только Продажи и рекламные данные, от которых этот Продажи в значительной степени зависит.

Отсюда наш заключение в Nestlé. Во-первых, мы должны спрогнозировать Продажи, на основе которых мы будем прогнозировать Продажи.

Разработка функций

➔ Преобразование временных рядов в задачу обучения с учителем

Наша методология основана на машинном обучении, поэтому мы используем одну модель для прогнозирования нескольких продуктов.

Эндрю Нг однажды сказал:

Прикладное машинное обучение — это, по сути, разработка функций.

Очень часто говорят, что данные — это топливо для машинного обучения. Хотя на самом деле это не совсем так. Если мы просто возьмем данные, которые у нас есть, в большинстве случаев мы не подготовим хорошие модели. Лучше сказать, что данные подобны нефти. Таким образом, преобразование сырой нефти в топливо должно быть сделано в первую очередь. В нашем случае это преобразование представляет собой разработку функций.

Мы создаем новые функции на основе существующих, которые позволяют работать алгоритмам машинного обучения. Получение правильных данных значительно повышает качество данных, потому что мы преобразуем необработанные данные в информацию, которую модель преобразует в знания. Тогда модель сможет лучше понять мир и будет давать более качественные прогнозы.

В настоящее время мы видим тенденцию к использованию таких моделей, как XGBoost или нейронные сети. Конечно, иногда у нас нет выбора, примером может служить классификация объекта на фотографии с помощью сверточных нейронных сетей. Однако, на мой взгляд, мы всегда должны хорошо анализировать данные, а выводы следует преобразовывать в преобразование данных. Когда я преподаю классификацию, мне нравится показывать пример того, что логистическая регрессия может дать лучшую точность с хорошо преобразованными данными, чем XGBoost на необработанных данных. Кроме того, если модель менее сложна, она также лучше интерпретируема, что часто также важно для бизнеса. Таким образом, мы знаем и можем объяснить, как переменные влияют на предсказание нашей модели.

Однако вернемся к нашему проекту. Прежде чем мы сможем использовать алгоритмы машинного обучения, наши временные ряды должны быть преобразованы в задачу контролируемого обучения. Во временных рядах не существует понятия переменных X и y. Поэтому нам нужно выбрать то, что мы будем прогнозировать (y), и использовать разработку функций для создания всех X переменные, которые будут использоваться для прогнозирования.

На первом этапе мы создаем наши цели, значения, которые будет прогнозировать модель. Эти значения представляют собой цифры того, сколько клиент продаст через неделю, через 2 недели и т. д., а также сколько клиент закажет у нас через неделю, через 2 недели и т. д.

➞ Это будет наш y.

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

Для последних дат мы не можем создавать будущие значения, потому что мы их не знаем. Однако мы не удаляем недостающие созданные из-за этого. Эти пропажи могут возникнуть для последних дат. То есть на предпоследнюю дату, 22 декабря, мы можем сделать Прогноз только на неделю вперед, чтобы сравнить его с истинным значением. Однако мы не можем прогнозировать на 2 недели вперед. В зависимости от горизонта прогноза перемещаем окно для тестовых данных только на прогнозные значения того же периода, например, 2019 года.

Далее мы создаем переменные X, функции, на которые модель будет соответствовать, а затем составляем прогноз. Такими значениями могут быть характеристики из будущего, которые известны на момент составления прогноза — в нашем случае это просто переменные акции, какой будет эта акция на следующей неделе, через 2 недели и т.д.

➞ Это будет наш X.

Это единственные признаки будущего, которые мы используем и которые известны на момент выполнения прогноза. Нет утечки данных. Это важно и известно практикам, но часто упускается из виду исследователями или заинтересованными сторонами. Утечка данных происходит, когда модель имеет доступ к информации, которая на практике была бы недоступна.

Запаздывающие значения, сколько мы продали неделю назад, 2 недели назад и т. д. Это простой способ изменить время последовательно в задачу обучения с учителем. Здесь, с другой стороны, у нас нет этих функций для первых строк, потому что нет данных, из которых можно их получить.

➞ Это будет наш X.

Здесь мы видим аналогичную ситуацию с отсутствующими значениями, но эти отсутствующие признаки появятся в индексах впервые. Нам нужны все переменные X, и мы не собираемся заменять их другим значением. Поэтому мы удаляем созданные таким образом наблюдения с отсутствующими значениями.

Следующим шагом после добавления необработанных лаговых значений является добавление скользящей статистики, то есть для скользящего окна мы вычисляем различную статистику. Это может быть среднее значение, медиана, стандартное отклонение, сумма или, по крайней мере, разница между различными значениями. Последним может быть разница между суммой заказанного и доставленного товара. Такая переменная сообщает модели, что розничный продавец может перезаказывать, потому что он не получил столько, сколько заказывал в прошлом. Вычисляем статистику для окон разной ширины, например, скользящее среднее 2-х предыдущих, 3-х предыдущих значений и так далее.

➞ Это будет наш X.

Во временном ряду помимо тренда может присутствовать и сезонность, означающая, что в определенный период года продаж больше, чем в другой. Чтобы использовать номер недели в качестве информации, я преобразую неделю в циклическую переменную, которая представляет собой синус и косинус. Таким образом, я преобразовываю одну переменную в две переменные. Здесь я преобразую номер недели, но мы можем использовать тот же подход для других циклических переменных, таких как час или день недели. На примере дня недели я объясню, почему это преобразование может быть лучше других.

Если бы мы преобразовали день недели в числовую переменную, понедельник мог бы иметь значение 1, а воскресенье — 7. Таким образом, для модели два дня были бы очень далеки друг от друга. друг от друга, но на самом деле за воскресеньем следует понедельник.

Другим преобразованием может быть OneHotEncoder, но тогда мы создадим несколько двоичных переменных.

➞ Эти переменные также будут нашим X.

Это примеры преобразования данных, я бы сказал базовые. Мы найдем еще другие в зависимости от проблемы. Мы также должны преобразовать категориальные переменные, такие как клиент и продукт.

Цепная многовыходная регрессия

➔ Методология использования моделей ML для многовыходной регрессии

Мы уже создали новый набор функций для X и y, поэтому возникает вопрос: как вы подходят модели в Nestlé? Стандартные алгоритмы машинного обучения (я не говорю о нейронных сетях) предназначены для прогнозирования одного числового значения, поэтому нам нужна отдельная модель для каждого горизонта. В качестве модели мы используем Random Forest. Кроме того, как я упоминал ранее, мы хотели бы сделать прогноз "Продажи", а затем прогноз "Продажи". Напоминаем, что Sell Out — это количество продуктов, проданных розничным продавцом конечным покупателям, а Sell In здесь — это количество продуктов, заказанных у Nestlé розничным продавцом. Мы сначалапрогнозируем следующие20 недель для продажи, затем следующие 15 недель для продажи. Более длительный горизонт для Sell Out, потому что для Sell In требуется прогноз будущих значений Sell Out, а из исследовательского анализа мы знаем, что Sell Out самое большее составляет 3–4 недели. позади Продажи. Мы выбрали еще одну неделю по рациональным причинам.

В качестве методологии обучения модели мы используем цепную регрессию с несколькими выходами, которая представляет собой линейную последовательность моделей. Первая модель, которая представляет собой модель для Распродажи на 1 неделю вперед, использует созданные нами переменные. Следующая модель рассчитана на распродажу на 2 недели вперед и имеет те же функции и прогнозы, что и предыдущая модель. После того, как мы подобрали все модели для продажи, мы подгоняем модели для продажи. Каждая модель имеет доступ к тем же функциям и прогнозу, что и предыдущие модели. Кроме того, у каждой модели есть выбор функций, о которых я напишу на секунду.

Обучение одной модели

➔ Выбор функции / выбор гиперпараметров

Теперь я собираюсь показать единую модель обучения, основанную на модели "Продажи через 3 недели вперед".

Я начинаю с выбора функций. С помощью конструирования признаков мы создали множество функций, из-за которых мы сталкиваемся с проблемой проклятия размерности, а также бывает, что функции коррелированы между собой, следовательно, многие из них несут одинаковую информацию, по которой мы можем обнаружить, что модель считает одну информацию более важной, даже если в действительности это не так. Другая причина в том, что мы не хотим обучать модель шуму. Следовательно, необходимо использовать выбор функций. Мы можем разделить его на переменные, созданные во время разработки функций и прогнозирования предыдущих моделей.

Я собираюсь начать с прогнозов, которые мы видим внизу. Наша модель использует прогнозы предыдущих моделей для Sell In, но не использует все прогнозы Sell Out. Мы выбираем только следующие 5 прогнозов продаж, а именно «Продажи 4Н», «Продажи 5Н», «Продажи 6Н», «Продажи 7Н» и «Продажи 8Н». Это связано с нашим исследовательским анализом данных и деловыми отношениями. Теперь ритейлеры будут заказывать у нас больше товаров, потому что они намерены сами продавать больше товаров за 3 недели, продвигая их.

Что касается созданных нами функций, мы в первую очередь не выбираем те, которые связаны с распродажей, такие как задержки для распродажи, скользящая статистика для распродажи, рекламные данные, потому что эти переменные уже сведен к прогнозу. В некотором смысле, в этом случае мы уменьшаем многомерность наших данных с помощью прогноза, основанного на них.

Мы используем только характеристики, связанные с Sell In, а также циклические и категориальные переменные. Однако мы берем не все, а только нужные. Однако может оказаться, что скользящее среднее для разной ширины окна считается уместным. Мы не должны брать их все, а только наиболее релевантные или наиболее коррелированные.

Из-за того, что я сказал, практически каждая модель использует разные функции.

У нас уже выбраны функции, так что же представляет собой само обучение? Этот процесс максимально стандартен. Однако я хотел бы кратко остановиться на выборе гиперпараметров. Данные, которые мы используем, представляют собой временные ряды, поэтому наблюдения зависят друг от друга. Мы не можем использовать рандомизацию при разделении обучающего/тестового набора и не можем использовать перекрестную проверку. В этом случае произойдет утечка данных. Следовательно, в каждом из этих разделений тестовые или проверочные индексы должны быть выше, чем обучающие индексы.

Большое спасибо. Надеюсь, я не утомил вас, так как все, что я показал, соответствует искусству науки о данных. Со стороны это может показаться сложным, но когда мы углубимся в детали, вы увидите, что он состоит из многих основных методов, используемых в машинном обучении. Во-первых, это работает, я показал, как использовать машинное обучение для временных рядов, и нам не пришлось использовать как минимум поиск по дереву Монте-Карло (шучу). Кроме того, вы видели, как мы превратили бизнес-задачу в решение для машинного обучения.

😎