Чтобы сделать наши курсы для DevOps-инженеров и специалистов по Machine Learning еще более полезными, сегодня рассмотрим, как автоматизировать развертывание и обслуживание ML-моделей согласно концепции MLOps с помощью GitLab CI/CD, BentoML, Yatai, MLflow и Kubeflow.
BentoML для CI в MLOPS
При развертывании ML-модели необходимо учитывать следующие аспекты:
- как была построена модель и что влияет на ее обслуживание;
- как будет использоваться обслуживаемая модель;
- как масштабировать рабочие нагрузки;
- как контролировать сервис и реализовать логирование;
- как модель может быть переобучена и автоматически развернута.
Концепция MLOps предполагает целостное решение всех этих вопросов через использование специальных открытых и проприетаных инструментов, которые позволяют выстроить сквозной конвейер разработки, оразвертывания и поддержки эксплуатации системы машинного обучения. К таким инструментам относятся Kubeflow, MLflow и BentoML. О том, что представляет собой Kubeflow и MLflow, мы писали здесь.
А BentoML – это открытая библиотека для быстрого создания MVP систем машинного обучения. Она упрощает создание API методов для доступа к обученной ML-модели и совместима со всеми крупными фреймворками: Tensorflow, Keras, PyTorch, XGBoost, scikit-learn и fastai. BentoML поддерживает адаптивную микропакетную обработку данных, а также предоставляет функции управления моделью и ее развертывания. Поэтому BentoML отлично реализует идеи MLOps, позволяя разработчикам моделей машинного обучения использовать лучшие практики DevOps.
Специалисты по Data Science и инженеры Machine Learning используют BentoML для ускорения и стандартизации процесса запуска моделей в производство, позволяя создавать масштабируемые и высокопроизводительные ML-сервисы. Библиотека поддерживает непрерывное развертывание, мониторинг и сопровождение сервисов в производственной среде.
Впрочем, перед автоматизированным развертыванием модели необходимо автоматизировать ее обучение. Это можно сделать, реализовав конвейер с использованием Kubeflow, что гарантирует повторяемость и воспроизводимость обучения ML-модели. Как только модель успешно обучена, она регистрируется в реестре моделей с помощью MLFlow. Также автоматически регистрируются такие показатели работы ML-модели, в частности, точность. Благодаря регистрации модели в реестре MLflow к ней можно будет обратиться по уникальному URL-адресу, например:
model = mlflow.sklearn.load_model(f"runs:/{run_id}/model")
Здесь run_id — это уникальный идентификатор, к примеру, 8aa4630a023c4e94b22c6e738127ee7a. Он будет передаваться в инструмент непрерывного развертывания (CI, Continuous Integration), который запускается после успешного обучения модели. Используя GitLab CI/CD, можно запустить задание CI с помощью инструмента командной строки curl, передав HTTP-методом POST идентификатор запуска MLflow в качестве переменной среды при выполнении задания:
curl --request POST \ --form token=<token> \ --form ref=<branch> \ --form "variables[MLFLOW_RUN_ID]=8aa4630a023c4e94b22c6e738127ee7a" \ "https://gitlab.com/api/v4/projects/<project-id>/trigger/pipeline"
Это можно быстро превратить в код Python используя один из многочисленных конвертеров, например, https://curlconverter.com/, чтобы быстро создать компонент Kubeflow:
def trigger_ci(mlflow_run_id: str, branch: str = "main"): import requests files = { "token": (None, "your-token-here"), "ref": (None, branch), "variables[MLFLOW_RUN_ID]": (None, mlflow_run_id), } response = requests.post( "https://gitlab.com/api/v4/projects/project-id/trigger/pipeline", files=files ) return response.text
Чтобы развернуть ML-модель, упакованную в RESTfull API решение с помощью BentoML, в Kubernetes, можно воспользоваться сервисом Yatai, который обеспечивает развертывание, сопровождение и масштабирование BentoML-решений в Kubernetes. Как это сделать, рассмотрим далее.
Автоматизация развертывания Bento-службы в Yatai
Следующий YAML-файл .gitlabci.yml содержит все необходимые команды BentoML:
bentoml-build-and-push: image: "python:3.8" stage: bentoml script: - apt-get update -y - apt-get install -y jq - pip install --upgrade pip - pip install -r $CI_PROJECT_DIR/bento/requirements.txt - export BENTO_MODEL="aml-case" - python $CI_PROJECT_DIR/bento/save_model_to_bentoml.py --model_name ${BENTO_MODEL} --run_id $MLFLOW_RUN_ID - bentoml build -f $CI_PROJECT_DIR/bento/bentofile.yaml - bentoml yatai login --api-token $YATAI_API_TOKEN --endpoint http://yatai.yatai-system.svc.cluster.local - export BENTO_DEPLOYMENT_NAME="${BENTO_MODEL}-${CI_COMMIT_SHORT_SHA}" - bentoml push ${BENTO_MODEL} - export BENTO_MODEL_AND_TAG=`bentoml list ${BENTO_MODEL} -o json | jq '.[0]["tag"]'` - cp $CI_PROJECT_DIR/bento/deployment.yaml ./deployment.yaml - 'sed -i "s/BENTO_MODEL_AND_TAG/$BENTO_MODEL_AND_TAG/g" ./deployment.yaml' - 'sed -i "s/BENTO_DEPLOYMENT_NAME/$BENTO_DEPLOYMENT_NAME/g" ./deployment.yaml' - 'sed -i "s/BENTO_MODEL/$BENTO_MODEL/g" ./deployment.yaml' artifacts: paths: - deployment.yaml only: - triggers bentoml-deploy: image: bitnami/kubectl:latest stage: bentoml script: - kubectl create -f deployment.yaml needs: ["bentoml-build-and-push"] only: - triggers
Первые четыре команды устанавливают jq, необходимый для работы с JSON, и зависимости для службы BentoML, включая scikit-learn и MLflow. Команда save_model_to_bentoml.py сохраняет ML-модель, с указанием ее имени и идентификатором run_id, который ранее передавался при ручном запуске CI. Код регистрации модели в реестре BentoML выглядит следующим образом:
def main(model_name: str, run_id: str): model = mlflow.sklearn.load_model(f"runs:/{run_id}/model") saved_model = bentoml.picklable_model.save_model( name=model_name, model=model, signatures={"predict_proba": {"batchable": True}} ) runner = bentoml.picklable_model.get(f"{model_name}:latest").to_runner() runner.init_local() EXAMPLE_INPUT = np.random.rand(4, 24) data = pd.DataFrame(EXAMPLE_INPUT) predicted_probs = [x[1] for x in model.predict_proba(data)] print(predicted_probs) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--model_name") parser.add_argument("--run_id") args = parser.parse_args() main(model_name=args.model_name, run_id=args.run_id)
Первые две строки этого скрипта загружают модель из MLflow, используя идентификатор run_id, а затем сохраняют ее в реестре моделей BentoML с ранее переданным именем. После того, как модель зарегистрирована в реестре BentoML, можно начать создание службы Bento. Остальная часть скрипта выполняет проверку работоспособности, удостоверяясь, что загруженная модель в BentoML может работать с некоторыми случайными входными данными. YAML-файл службы Bento довольно прост:
model = mlflow.sklearn.load_model(f"runs:/{run_id}/model") saved_model = bentoml.picklable_model.save_model( name=model_name, model=model, signatures={"predict_proba": {"batchable": True}})
Команда bentoml build -f $CI_PROJECT_DIR/bento/bentofile.yaml создает службу Bento, которая упаковывает все в единый артефакт, чтобы использовать его для развертывания ML-модели. Сервис Yatai играет роль центрального хранилища Bento-моделей. Перед развертыванием в Yatai, нужно войти в кластер с токеном API:
bentoml yatai login --api-token $YATAI_API_TOKEN --endpoint http://yatai.yatai-system.svc.cluster.local
И выполнить команду проталкивания Bento-службы в Yatai:
bentoml push ${BENTO_MODEL}
В случае успеха Yatai приступит к контейнеризации Bento, а пока это происходит, можно подготовить развертывание Bento, подготовив YAML-файл deployment.yaml:
apiVersion: serving.yatai.ai/v1alpha2 kind: BentoDeployment metadata: name: BENTO_DEPLOYMENT_NAME namespace: ds-models spec: bento_tag: BENTO_MODEL_AND_TAG ingress: enabled: true resources: limits: cpu: "1" memory: "1Gi" requests: cpu: "500m" memory: "512m" runners: - name: BENTO_MODEL resources: limits: cpu: "1" memory: "1Gi" requests: cpu: "500m" memory: "512m"
Чтобы упростить управление развертываниями, их можно называть по имени ML-модели и версии Git. Это позволит сопоставить, какое развертывание было получено из какой фиксации Git. Затем следует создать образ Docker, который будет использовать Bento-развертывание с нужными sed и jq:
export BENTO_DEPLOYMENT_NAME="${BENTO_MODEL}-${CI_COMMIT_SHORT_SHA}" export BENTO_MODEL_AND_TAG=`bentoml list ${BENTO_MODEL} -o json | jq '.[0]["tag"]'` cp $CI_PROJECT_DIR/bento/deployment.yaml ./deployment.yaml 'sed -i "s/BENTO_MODEL_AND_TAG/$BENTO_MODEL_AND_TAG/g" ./deployment.yaml' 'sed -i "s/BENTO_DEPLOYMENT_NAME/$BENTO_DEPLOYMENT_NAME/g" ./deployment.yaml' 'sed -i "s/BENTO_MODEL/$BENTO_MODEL/g" ./deployment.yaml'
Команда cp $CI_PROJECT_DIR/bento/deployment.yaml ./deployment.yaml создает копию файла deployment.yaml, который будет передаваться на следующий шаг CI-конвейера. Чтобы завершить развертывания Bento, осталось выполнить команду ее создания в kubectl:
bentoml-deploy: image: bitnami/kubectl:latest stage: bentoml script: - kubectl create -f deployment.yaml needs: ["bentoml-build-and-push"] only: - triggers
По завершении развертывания оно отобразится в пользовательском интерфейсе Yatai, где также можно выполнять обслуживание, мониторинг и ведение журнала. При этом мониторинг и ведение журнала нужно сперва включить вручную:
После этого каждая развертываемая вами модель будет сопровождаться мониторингом через Grafana и ведением журнала через Loki. А используя URL-адрес конечной точки развернутой ML-модели, можно перейти в веб-инструмент тестирования REST API Swagger, чтобы проверить ее работу:
В заключение отметим, что все рассмотренные MLOPS-инструменты также поддерживают переобучение моделей Machine Learning. В частности, можно просто запланировать периодический запуск конвейера Kubeflow по расписанию. Это позволит не ждать, пока сработают предупреждения об обнаружении дрейфа данных или модели, а начать ее переобучение, когда для этого будут доступны свежие данные. Для этого нужны метрики оценки, чтобы сравнить новые модели с теми, которые работают в производстве. Сделать это поможет компонент Trigger CI в GitLab. Альтернативой является простое переключение службы в Ingress на модель с наилучшей производительностью. Напомним, Ingress — объект API, который управляет внешним доступом к объектам Service в проекте Kubernetes, он идентифицирует маршруты HTTP и HTTPS из внешней среды для объектов Service проекта. Маршрутизация трафика контролируется правилами, определенными для ресурса Ingress.
Например, если имеется следующий вход:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: aml namespace: ds-models spec: rules: - host: aml-case.ds-models.dev.jago.data http: paths: - backend: service: name: "aml-123" port: number: 3000 path: / pathType: ImplementationSpecific
Ingress указывает на службу aml-123, которую можно заменить на другую вручную или с помощью триггера CI.
Таким образом, Kubeflow, MLflow и BentoML с Yatai позволяют автоматизировать развертывание и переобучение модели Machine Learning в любой среде. Чем BentoML отличается от другого популярного фреймворка FastAPI и что лучше для MLOps, читайте в нашей новой статье.
Как применять эти и другие современные инструменты MLOps в проектах аналитики больших данных, вы узнаете на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:
Источники