Планирование смен сотрудников в офлайн ритейле: как упорядочить хаос

Всем привет! На связи команда ad-hoc аналитики X5 Tech. В этой статье мы — Лев Баскин, Андрей Полушкин и Александр Сахнов — расскажем, как без регистрации и смс спланировать смены для сотрудников офлайн-магазинов. Казалось бы, задача достаточно тривиальная: берём симплекс метод или другой метод условной оптимизации и на основе ожидаемой загрузки получаем расписание сотрудников. Однако, не всё так просто. 

Первое препятствие на пути — масштабы. У Х5 порядка 25 000 магазинов от Калининграда до Владивостока и более 378 000 работников, обеспечивающих непрерывное функционирование бизнеса. У каждого магазина своя специфика и различающиеся бизнес-процессы. Во-вторых, даже зная, сколько часов занимает тот или иной процесс и как он локализован во времени, из-за внешних факторов нельзя так просто взять и поместить его в расписание. Например, обстановка на дорогах может повлиять на время поставки и, как следствие, сдвинуть ряд процессов в магазине. Достаточно предисловия, перейдём к сути!

Всю задачу можно разбить на три этапа:

  1. Анализ активностей сотрудников магазинов. 

  2. Оценка и прогноз общей ресурсной потребности в течение дня.

  3. Построение графиков сотрудников на основе ресурсной потребности и физических ограничений.

Анализ активностей работника магазина

Какие могут быть задачи в магазине? Сразу приходит на ум то, с чем мы сталкиваемся каждый раз при походе в магазин — кассовый узел. Помимо этого есть ряд других активностей, лишь малая часть которых отражена на схеме:

c6624acb3d0b4811c61f51afa0ff87bf.png

Каждая активность требует адекватной оценки ресурсной потребности. Например, если в час пик вывести одного сотрудника на кассу вместо двух, то возникнет очередь, покупатель потеряет время, расстроится, и, в конечном итоге, больше не придёт к нам в магазин. Если мы переоценим ресурсную потребность на кассовом узле, то получим нехватку людей в зале. Из-за этого вероятно возникновение проблем с доступностью: покупатель, придя в магазин за своим любимым творожком, не найдёт его на полке и, расстроившись, уйдёт к конкурентам. Поэтому важно правильно балансировать ресурсы при планировании.

Активности можно кластеризовать на 3 группы:

  1. Сильно локализуемые во времени активности: например, прогнозируя трафик магазина в течение дня, можно детально определить загрузку кассового узла.

  2. Слабо локализуемые во времени активности: например, определить точное время приёмки товара может быть сложно из-за дорожной ситуации.

  3. «Плавающие» активности: их можно выполнять в течение дня в свободное от других задач время. К подобным активностям можно отнести ревизию склада.

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

Оценка общей ресурсной потребности в течение рабочего дня

Итак, мы разобрались с тем, какие активности есть в магазине, и теперь нам нужно конвертировать это знание в человеко-часы, которые впоследствии надо распределить на отрезки длиной 15 минут для учёта нагрузки в течение дня при планировании смен. Как это сделать? Краткий ответ на этот вопрос даёт схема:

731dc3f27c739983a605887c040912a9.png

Первым шагом является построение прогноза количества операций в дневной грануляции. 

Данные, которые нам понадобятся, можно разделить на 3 группы:

  1. Количество операций за прошедшие n дней.

  2. Описательные данные магазина (например, торговая площадь, регион или число проработанных дней).

  3. Временные признаки для учёта сезонности.

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

Какой метрикой оценить качество прогноза? Первым в голову может прийти MAPE (Mean Average Percentage Error). Однако магазины имеют разный размер, и количество операций может отличаться в разы. Поэтому данная метрика может вести себя очень нестабильно. Более удачным решением, на наш взгляд, является метрика WAPE (Weighted Average Percentage Error), которая «взвешивает» ошибки каждого наблюдения. Это помогает, например, балансировать наблюдения в будни, выходные, а также праздничные дни.

6cf746676be262db6c2a4f091b35203f.png

  1. Аt — истинные значения

  2. Ft — прогнозные значения

Итак, мы получили ежедневный прогноз количества операций. Как известно, дьявол кроется в деталях, поэтому теперь нам нужно «размазать» прогноз по операциям по 15-минуткам. Для этого нужно построить кривую профиля дня, которая будет по своим свойствам схожа с плотностью вероятности. Пример синтетического профиля приведён на рисунке:

25bad13bcf63a73da8a5b723277f44ee.png

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

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

Умножив прогноз количества операций на профили соответствующих дней, получим заветный прогноз по 15-минуткам. Осталось совсем немного, чтобы получить заветный прогноз человеко-часов!  

Теперь нужно определиться с нормами на операции. Как понять, сколько закладывать времени на расчёт с покупателем? 10 секунд? А может, много покупателей долго ищут свою карту или паспорт при покупке алкоголя и надо заложить минуту?

Когда заложил 0.2 секунды на пробитие одного товара...

Когда заложил 0.2 секунды на пробитие одного товара…

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

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

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

Рассмотрим синтетический пример. Пусть норма на операцию — 1 минута. Логично, что за 15 минут, при условии непрерывной работы, сотрудник должен совершить 15 операций. На основе ретроспективных данных в пиковые часы собираем данные по фактическому количеству операций за 15 минут. 

Далее строим график распределения количества сотрудников по количеству выполненных операций за 15 минут:

bc205cf111428b846ba468adcc3ce018.png

В идеальном мире красная вертикаль, символизирующая ожидаемый результат в 15 операций, должна оказаться где-то посередине или чуть правее фактического распределения (конечно, при условии отсутствии простоя в час пик). Однако мы видим, что сотрудники даже при хорошем сценарии никак не успевают выполнить 15 операций, из-за чего снижается качества сервиса. Это повод задуматься об увеличении нормы на операцию в 2 раза, что может улучшить качество сервиса в магазине.

Вернёмся к нашим расчётам. Умножим наш прогноз количества операций за 15 минут на норму и получим ресурсную потребность на 15-ти минутку.

Скажем, в какой-то временной отрезок мы получили потребность в 0.2 кассирах. Как интерпретировать этот результат? Тут в дело вступают правила округления: они призваны исключать ситуации, когда, например, потребность в 0.3 кассирах может привести к пустому кассовому узлу.

Итак, применив правила округления, получим итоговую ресурсную потребность на 15 минут. Если вы ещё с нами, то не переключайтесь, нам остался всего один шаг!

Построение графиков сотрудников на основе ресурсной потребности

На текущий момент мы оценили ожидаемое количество операций, нормы на операцию и получили ресурсную потребность. Теперь остаётся покрыть её сменами.

Для начала поймём, как мы будем оценивать качество алгоритма. В нашем случае используются две метрики качества, которые балансируют друг друга:  

  1. Покрытие — какая доля ресурсной потребности покрывается сменами сотрудников.

  2. Утилизация — какая доля cмен сотрудников покрывается ресурсной потребностью.

Для иллюстрации рассмотрим пример для конкретной 15-минутки:

Расчётная ресурсная потребность, чел

4

5

4

Количество сотрудников, выводимое оптимизатором, чел

4

4

5

Покрытие

100%

80%

100%

Утилизация

100%

100%

80%

С метриками разобрались, теперь перейдём к функционалу, который предстоит оптимизировать. 

Он выглядит так:

253210eb9e5dc8e52e00ecc01649d0bf.png

  1. Nexp — расчётная ресурсная потребность.

  2. Nopt — количество выводимых оптимизатором сотрудников. 

Почему мы оптимизируем именно модуль? Наша задача — одновременно максимизировать утилизацию и покрытие, и модуль позволяет нам это сделать.

При этом у нас есть ряд ограничений:

  1. покрытие ≥ p%;

  2. утилизация ≥ u%;

  3. длины смен составляют заранее фиксированную длину (например, 6, 8 и 10 часов);

  4. количество рабочих мест ограничено;

  5. перерывы на обед;

  6. резерв под болезни;

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

ad1a694b1cd488ae5f2ed1b0205a72fa.png

Мы получили графики для сотрудников. Но на этом мы не остановились: сопоставив график ресурсной потребности с результатами моделирования, можно переместить «плавающие» активности внутри дня с периодов недопокрытия ресурсной потребности в периоды перепокрытия, тем самым ещё улучшить метрики.

Итак, мы получили график сотрудников, позволяющий эффективно (в смысле покрытия и утилизации) использовать время сотрудников.

Итого, для решения задачи WFM (workforce management) необходимо пройти этапы отрицания, торга, депрессии и принятия:

  1. Убедиться, что бизнес-процессы в достаточной степени оцифрованы. 

  2. Убедиться, что значительная часть процессов может быть достаточно локализована во времени: если, например, самые ресурсоёмкие задачи имеют люфт в 6 часов, то и планирование смен будет менее точным.

  3. Построить прогноз количества операций на основе исторических данных и выстроенных бизнес-процессов.

  4. Определиться, какие операции могут выполняться в течение дня в любой момент, а какие имеют жёсткую привязку ко времени.

  5. Перевести операции в человеко-часы, обратив особенное внимание на нормы и правила округления.

  6. Уточнить все имеющиеся ограничения, связанные с планированием смен.

  7. Использовать pyworkforce или написать свою библиотеку с применением условной оптимизации для построения графиков cмен.

Итак, в этой статье мы показали подход по построению системы WFM, обсудили, как строить прогноз ресурсной потребности и графиков сотрудников, как измерить их качество и с какими сложностями можно столкнуться на пути. Итоги нашего ad-hoc исследования помогли с определением пути внедрения обновлённой системы WFM в X5. Надеемся, написанием этой прикладной статьи мы помогли и кому-то ещё. 

Авторы статьи:

Баскин Лев — DA/DS X5 Tech

Полушкин Андрей — Teadlead DA/DS в X5 Tech

Сахнов Александр — Head of DA/DS в X5 Tech

© Habrahabr.ru