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

Привет, Хабр. Нас зовут Александр Кузьмичёв и Александр Казначеев. Мы пилотируем проект «ML-сервис по оттоку». В этой статье мы поделимся нашим опытом разработки модели и выкатки её в прод с помощью Cloud ML Platform.

Предыстория 


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

Запрос и исходные данные


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

После первичного анализа проекта мы поняли, что:

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

Исходя из этого, мы решили делать ML-модель на CatBoost. Это универсальная Open-Source-библиотека с поддержкой категориальных переменных, которая в том числе решает задачи смещения градиента (Gradient Bias) и смещения предсказания (Prediction Shift). Библиотека CatBoost подходила нам и потому, что даёт высокое качество обучения, а работать с ней можно из Python, R и командной строки.

Подготовка модели


Мы разработали модель на собственном сервере. Написали её на Python. Для работы с моделью мы подготовили пайплайн, который позволяет реализовать простой алгоритм взаимодействия с сервисом:

  • загрузили данные и переменные;
  • ML-модель выполнила расчёт;
  • пользователь получил интерпретируемый результат.

Для обучения мы собрали датасет из 2 млн записей, в который вошли исторические данные за 1,5 года — с ноября 2021 года по апрель 2023 года. В исходной выборке среднее значение оттока было на уровне 11% в месяц при более 100 000 клиентов в месяц. 

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

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

После обучения модели и её тестирования мы получили на выборке OOT показатель индекса Gini на уровне 75%. Этот индекс часто используется при оценке предсказательных моделей в задачах бинарной классификации при сильной несбалансированности классов целевой переменной. Так мы убедились, что правильно выбрали признаки и модель не требует дообучения.

Выкатка ML-модели в прод


После подготовки модели нам надо было выбрать платформу для её размещения. Хостить на своём железе мы изначально не хотели и не планировали. В качестве основного варианта развертывания рассматривали облако:

  • в нём можно получить нужные ресурсы и инструменты для развёртывания;
  • к облаку легче подключить конечных пользователей;
  • при развёртывании в облаке мы выносим за пределы нашей ответственности администрирование сервисов вроде MLFlow и управления инфраструктурой;
  • доверие к продукту увеличивается благодаря стабильности инфраструктуры.

Мы выбрали сервис Cloud ML Platform от VK Cloud — платформу для полного цикла ML‑разработки. В нашем случае ключевым было наличие MLFlow и JupyterHub, а также поддержка нужных нам библиотек. 

В качестве среды для упаковки ML-моделей и их автоматического развёртывания в облаке мы выбрали MLflow Deploy. Для этого последовательно создали инстанс JupyterHub и инстанс MLflow — с инструкциями от VK Cloud проблем не возникло.

При запуске важно вручную поменять ресурсы на 2 Гб и 2 CPU, иначе есть вероятность выйти за пределы ограничений VK по умолчанию.



Этап подготовки модели для нас свёлся к паре кликов: поскольку мы подготовили и обучили её заранее, нам понадобилось только загрузить её в MLFlow, который расписан в папке tutorial, и развернуть.

Правда, после хоста модели в Cloud ML Platform нам понадобилось несколько доработать её для обеспечения полной совместимости с платформой. Дело в том, что MLFlow не воспринимает никакие другие функции, кроме predict. Но наша модель была сделана на основе библиотеки CatBoost, в которой за вызов предсказаний отвечает функция predict probe. После консультаций с командой VK Cloud мы сделали небольшую «прокладку», отвечающую за конвертацию класса: теперь у ML Flow вызывается predict, а у CatBoost он вызывает и присылает predict probe.

%load_ext autoreload
%autoreload 2
import pandas as pd
import mlflow
import catboost
import pickle

# Импортируем нашу модель
loaded_model = pickle.load(open('1_model_all.pickle', 'rb'))
# Переопределяем класс
class AddN(mlflow.pyfunc.PythonModel):
    def __init__(self, model):
        self.model = model

    def predict(self, context, model_input):
        # Здесь мы говорим, что вызвать у нашей модели в нашем случае 
        # predict_proba.
        # Здесь вы также можете прописать любые проверки уведомления или преобразования данных
        # перед вызовом предикта
        return self.model.predict_proba(model_input)
    
# Применяем класс
add5_model = AddN(loaded_model)

# Сохраняем модель в MLFLOW
mlflow.set_experiment(experiment_name='demand_forecasting')
with mlflow.start_run():
    model_info = mlflow.pyfunc.log_model(artifact_path="model",   python_model=add5_model)


# Пример деплоя модели из MLFLOW
import mlflow
from mlflow.deployments import get_deploy_client
client = get_deploy_client('vk-cloud-mlplatform')
deploy_server_name='deploy_server_q2'
auth_value = "user:PasswordDA@dvv//!123$"
auth_deployment_name = "test"
model_source_uri = 'mlflow-artifacts:/3/69715f65259c43d68360584710909fc0/artifacts/model'
client.create_deployment(deploy_server_name, auth_deployment_name, model_source_uri, auth=auth_value)

Под саму модель подняли конфигурацию на 2 CPU и 2 Гб. По результатам наших тестов выделенных мощностей достаточно для обработки 10 000 запросов в минуту при 50 переменных. Для текущей модели этого более чем достаточно. На эту конфигурацию, не поднимая новую, мы положим следующие модели.

Сейчас наша ML-модель для предсказания склонности клиента к оттоку доступна по API. Для обращения к ней достаточно простого запроса в одну строку. Для работы с моделью пользователю надо иметь только уникальную ссылку, логин и пароль.

# Пример
import requests

data={"inputs":[0.045341,  0.050680,  0.060618,  0.031065,  0.028702,0.045341]}
response = requests.post('https://ml-platform-77777777.ml.msk.vkcs.cloud/deploy/7777777-5299-4109-a6a6-7777777/test/invocations', json=data, auth=("user", "PasswordDA@dvv//!123$"))
print(response.text)
{"predictions": [0.9838204200479245, 0.01617957995207549]}

Весь алгоритм работы с моделью выглядит так:

  1. Пользователь загружает сырые данные. Подготовку датасета, сбор и выбор фичей мы оставили на стороне пользователя. При таком подходе он может оперировать данными, которые у него есть, без каких-либо ограничений.
  2. На стороне Cloud ML Platform происходят все преобразования. Отдельных обработок, исключений и чего-то подобного поверх не предпринимается: все обработки стандартные, которые выполняются по умолчанию в модели CatBoost.
  3. Модель выдаёт пользователю прогноз в виде числа от 0 до 1, на основании которого можно делать выводы о вероятности оттока клиента в ближайшие два месяца.

Такой алгоритм позволил вынести все потенциальные сложности пользователя за скобки: для него вся механика вычислений, преобразований, логарифмы, деление, сенсибилизация, PPCA и другие процессы остаются в Black Box. Это уменьшает требования к компетенциям пользователей и снижает порог входа: не надо нанимать DevOps-разработчика, который всё поднимет и доведет модель до выдачи прогнозов.

Перспективы улучшения


ML-модель уже используется. Но это не единственная и не финальная реализация.

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

И первую, и вторую доработки мы можем выполнить, используя ресурсы Cloud ML Platform. Это важно для нас, потому что не требует выведения модели из прода и поиска дополнительных инструментов для реализации.

Послесловие


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

Комментарии (2)


  1. fivlabor
    18.12.2023 11:59

    Какой экономический эффект был получен? Можете прикинуть, сколько человеко-часов потрачено на "выпуск ML-сервиса в прод"? Сроки окупаемости этой работы?

    Точные цифры не надо, интересует порядок чисел.


  1. sneg2015
    18.12.2023 11:59

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