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

Контекст

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

Хотя даты пакета являются гибкими, клиент по-прежнему имеет некоторый контроль над тем, когда он будет путешествовать. Мы отправляем им форму с просьбой указать три предполагаемые даты, на которые они хотят отправиться, и мы постараемся разместить их в пределах этих дат или как можно ближе к этим датам (при условии, что мы найдем хорошие предложения на эти даты). Поиск лучшего авиабилета для клиента является сложной задачей, мы должны учитывать несколько факторов, таких как: предпочтения клиентов (путешествие утром или ночью, возможность ожидания длительных пересадок), обеспечение соответствия цены авиабилетов наш бюджет, а также собственные ограничения пункта назначения. Например, Морро-ду-Сан-Паулу — пункт назначения на острове, поэтому клиенту необходимо прибыть вовремя, чтобы доставить лодку на остров до наступления темноты.

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

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

Решение

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

Первым шагом было согласование ожиданий и понимание бизнес-проблемы, решение таких вопросов, как:

  • Как модель будет использоваться и реализовываться?
  • Есть ли какое-то ограничение, которое нам нужно учитывать, например задержка?
  • Каковы возможные входы модели?
  • Как должна быть доставлена ​​модель? Как API?
  • Как будет оцениваться модель? Есть ли у нас базовый уровень?
  • Каким должен быть MVP?

Затем мы начали изучать доступные данные. У нас уже были годы данных о предыдущих вариантах перелетов, вручную отправленных клиентам, и их результатах (принято или отклонено). Таким образом, перед нами стояла задача классификации!

Мы начали с оценки данных посредством исследовательского анализа данных, который включал:

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

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

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

Затем мы использовали PCA (анализ основных компонентов), чтобы понять, ведут ли себя выбранные функции линейно, и визуально попытаться разделить классы. Удивительно, что мы нашли положительный знак в сторону его линейности и смогли визуализировать классы, что также означало, что мы на правильном пути к решению проблемы.

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

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

Кроме того, мы экспериментировали с выбором различных признаков и проектированием признаков, например, с использованием преобразования sin/cos для циклических признаков или группировки и обработки их как категориальных. Кроме того, мы экспериментировали с различными категориальными преобразованиями, такими как один горячий кодировщик, средний кодировщик и многое другое.

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

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

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

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

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

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

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

Выполнение

Мы разработали API с использованием пакета BentoML, который абстрагирует и упаковывает модель. Затем мы создали и развернули образ докера BentoML в Vertex AI. После этого мы реализовали и развернули модель на конечной точке, также используя Vertex AI.

BentoML отлично подходит для абстрагирования и ускорения разработки API. Vertex AI — отличный и интуитивно понятный инструмент для масштабирования и развертывания модели, модели также имеют версии внутри Vertex AI, и мы также можем тестировать модели A / B, что является очень полезной функцией.

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

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

Обслуживание

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

Поэтому мы создали два основных рабочих процесса, которые автоматически управляются инструментом Flyte, работающим в Kubernetes:

  1. Ежемесячно отслеживайте производительность модели за предыдущие два месяца. Это связано с тем, что есть периоды, когда объем нашей работы уменьшается, потому что мы не работаем в периоды высокого сезона.
  2. Если производительность модели ниже порогового значения, автоматически переобучайте модель. Мы использовали простую стратегию для выбора данных для повторного обучения, период окна данных за последние два года для повторного обучения, он повторно обучается на той же конфигурации модели, но снова выполняет гипернастройку. Обучение снова отслеживается в MLFlow. Затем, если производительность модели выше порогового значения, разверните ее в Vertex AI.

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

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

Также важно отметить, что у нас есть управление версиями модели как в Vertex AI, так и в MLFlow Model Registry, а также управление версиями кода в Github, поэтому мы контролируем происходящее и можем откатиться, если что-то пойдет не так.

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

Заключение

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

Кроме того, модель постоянно обновляется новыми данными и реагирует на изменения в поведении клиентов. Это стало возможным благодаря интеграции инструментов с открытым исходным кодом, таких как MLFlow, BentoML и Flyte, со стеком и инструментами Google, такими как VertexAI и Bigquery.

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

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