Симуляционная оптимизация помощь другу в моделировании и оптимизации службы поддержки его компании.

Симуляционная оптимизация Как помочь другу в моделировании и оптимизации службы поддержки его компании

Сгенерировано DreamStudio.

История создания модели оптимизации с помощью моделирования симуляции для оптимизации подразделения службы поддержки

Введение

Все началось с довольно простой просьбы. Мой друг, который ведет и управляет службой поддержки, столкнулся с некоторыми трудностями. В любой момент времени агенты службы поддержки казались неоптимально организованными, либо перебралось, либо их было недостаточно. У него были неплохие данные о времени поступления звонков (звонки, сообщения в чате и электронные письма), ожидании звонящих на удержании и длительности разговора. Зная мой опыт в области исследования операций (OR), мой друг представил мне эту проблему. Я был взволнован – в своей карьере я не часто использую принципы OR. Это была возможность погрузиться в то, чему я посвятил пять лет своей жизни.

Ключевым элементом любой программы OR является теория очередей, и это был классический случай (дословно) м/м/c-очереди. Звонки поступают с установленной стохастической скоростью, несколько агентов обрабатывают входящие звонки, все звонки обрабатываются с установленной стохастической скоростью, и стохастические скорости должны следовать экспоненциальному распределению. Так что я запустил Jupyter Notebook и использовал scipy для подгонки экспоненциальных распределений к некоторым входящим вызовам и времени обработки. Я обнаружил, что у нас действительно были параметры, которые достаточно близко соответствовали экспоненциальным распределениям.

очередь м/м/c. Диаграмма автора.

Теперь, если мой друг просто хотел знать, сколько агентов должно работать в службе поддержки, есть формулы, которые позволяют точно это определить; в основном Erlang-C. [1] Однако, как и в любом реальном сценарии, эта формула быстро ломается, когда мы начинаем вводить множество параметров, влияющих на этот конкретный центр поддержки. Наименовать несколько: изменяющийся спрос на входящие вызовы в течение дня, эффективность агентов, перерывы, необходимость работы агентов посменно и так далее. Так что это привело меня к симуляции, еще одному основному элементу OR.

Симуляция

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

Запуск симуляции 5 раз против 50 раз. Диаграмма автора.

Итак, я приступил к работе. В течение следующих пары дней на Python я создал симуляцию службы поддержки, используя реальные входные данные. Основные части моей симуляции включали учет переменного времени поступления звонков и времени обработки агентами в течение дня, при этом учитывая такие компоненты, как длина очереди и работа агентов при изменении параметров. Пришло время решить, что мы будем измерять, из которых было множество вариантов. Я начал с измерения использования агентов и средней длины очереди, однако одним из основных показателей для служб поддержки является уровень обслуживания в срок (SLA). [2] SLA – это, по сути, согласованное целевое измерение, которое показывает, как долго людям следует ждать в очереди. SLA важно отслеживать не только в среднем, но и в виде временного ряда в течение дня. Службы поддержки хотят, чтобы звонки отвечали в короткое и предсказуемое время, независимо от времени звонка.

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

Сравнение результатов симуляции с средней длительностью ожидания в очереди за 1 неделю. Диаграмма автора.

Оптимизация

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

Проблема заключалась в том, что для оптимизации нам нужна формула, а у нас была симуляция. Однако мне пришло в голову, что нет никаких причин, почему мы не можем использовать симуляцию в качестве целевой функции для оптимизационной задачи. Она принимает набор входных данных и, с достаточным количеством запусков симуляции, дает уверенный результат. К счастью, 30 лет назад исследователи пришли к этой же мысли и начали изучать область оптимизации с использованием симуляции. Умные люди проделали всю тяжелую работу за меня. [3, 4]

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

Моя цель – составить расписание. Расписания состоят из смен. Смены – это определенное время в течение “рабочего” дня симуляции (скажем, с 9:00 до 17:00, с 10:00 до 16:00), в течение которого агент может работать. Расписание – это набор всех смен с указанием количества работающих агентов на каждой смене. Хорошее расписание – это такое, которое поддерживает SLA примерно на целевом уровне и минимизирует общее количество рабочих часов (количество работников * продолжительность их смен). Некоторые смены имеют ограничение по количеству работающих людей (например, на полудневную утреннюю смену может работать только 10 человек), а у каждой смены есть определенное расписание перерывов. SLA никогда не должно превышать жесткого предела выше целевого значения (например, наше целевое значение SLA составляет 3 минуты, но никто не должен ждать больше 10 минут).

Я создала структуру так, чтобы все эти ограничения были учтены, и теперь я была готова к оптимизации. Некоторые проблемы, рассмотренные в исследованиях по оптимизации симуляции, сложны, потому что их симуляции являются чёрными ящиками, то есть, помимо ответа симуляции, вы не получаете полезных сигналов. К счастью, эта симуляция отличается от таких. Мы измеряем время ожидания в очереди на протяжении “рабочего” дня симуляции, поэтому мы можем видеть, как сравниваются разные смены между собой.

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

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

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

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

Создано DreamStudio.

Итак, какой самый естественный градиентный шаг? Возьмите худший график (тот, который в среднем наиболее удален от цели) и добавьте агента к сдвигу, если среднее значение выше вашей цели, или уберите агента, если среднее значение ниже цели. Если вы застряли в ситуации, когда все изменения смены делают график еще хуже, но SLA не близко к цели, вернитесь к предыдущему хорошему графику и начните сначала. Я пробовал другие способы выбора следующего графика, но этот оказался наиболее последовательным. Как понять, когда остановиться? Установите допуск, чтобы сказать, что если каждая смена в среднем отличается от цели менее чем на 30 секунд (например), считайте, что это решено. Остановитесь, если было сделано слишком много шагов, и выберите лучший график из сэмулированных.

Выбор следующего графика. Диаграмма авторства.

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

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

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

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

Результаты работы оптимизации. Диаграмма авторства.
#schedule is {(start_time, end_time): num_agents}{'Schedule':   {(0, 540): 5,   (30, 570): 2,   (60, 600): 1,   (90, 630): 1,   (120, 660): 4,   (150, 690): 1,   (180, 720): 0,   (210, 750): 1,   (240, 780): 18,   (0, 660): 0,   (30, 690): 0,   (60, 720): 0,   (90, 750): 0,   (120, 780): 3}'Average Wait': 0.5738814985851588'Worker Units': 660.0'Worst Shift Time In Queue, Relative to Target': 0.5965600329117189}

Заключение

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

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

Контейнерный порт - модульная система. Фото CHUTTERSNAP на Unsplash.

Финальные мысли

Огромное спасибо Джереми Харперу, другу в этом проекте.

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

Ссылки

1. Rahul Awati, Earlang C, techtarget.com

2. Naveen Mahadevan, Service Level Agreement (2022), sprinklr.com

3. N. Jian, S. Henderson, Введение в оптимизацию с помощью симуляции (2015), Конференция зимней симуляции

4. Y. Carlson, A. Maria, Оптимизация симуляции: методы и приложения (1997), Конференция зимней симуляции