이번 시간에는 지난 포스트에 이어, MLflow로 Model을 배포하는 방안을 살펴본다.
개발자 커뮤니티 SQLER.com - Azure Databricks - MLflow를 이용한 머신러닝(1)
개발자 커뮤니티 SQLER.com - Azure Databricks - MLflow를 이용한 머신러닝(2) - Tracking
개발자 커뮤니티 SQLER.com - Azure Databricks - MLflow를 이용한 머신러닝(3) - Project
개발자 커뮤니티 SQLER.com - Azure Databricks - MLflow를 이용한 머신러닝(4) - Model Registry
개발자 커뮤니티 SQLER.com - Azure Databricks - MLflow를 이용한 머신러닝(5) - Model 배포
Azure Databricks - MLflow를 이용한 머신러닝(5) - Model 배포
scikit-learn model deployment on Azure ML - Azure Databricks | Microsoft Docs 문서의 내용을 참조.
이 포스팅에서 사용되는 전체 코드는 아래 github 리포지토리에서 확인 가능.
CloudBreadPaPa/pyspark-basic: pyspark basic self-study repo (github.com)
MLflow Model은 무엇이고 왜 사용하는가?
공식 문서의 내용으로, MLflow Model은 머신러닝 모델들이 다양한 어플리케이션(downstream tools)에서 사용되기 위한 패키징 표준 포맷이다. 예를 들어, REST API로 실시간 서비스를 제공하거나, Apache Spark에서 배치 예측 서비스 형태로 사용이 가능하다. 포맷은 모델을 각각 다른 "flavors"로 저장하게 정의하는 규약이며, 여러 어플리케이션(downstream tools)에서 사용될 수 있다.
An MLflow Model is a standard format for packaging machine learning models that can be used in a variety of downstream tools—for example, real-time serving through a REST API or batch inference on Apache Spark. The format defines a convention that lets you save a model in different “flavors” that can be understood by different downstream tools.
간략히, Model Serving을 위해 제공되는 포맷이며, Databricks에서 이 포맷으로 만들면 따로 모델을 로드하고 추론(Inference)하는 어플리케이션 개발 없이 REST API 웹서비스나 Batch 형태로 사용이 가능하다.
하지만, 실제 현업에서는 그리 간단하지 않다. 그 이유는 이 문서 마지막에서 기술한다.
MLflow Storage Format
Storage Format은 Databricks MLflow 모델을 포함하는 디렉토리 구조로, 모델파일 정의와 "flavors"를 포함한다.
예를 들어, sklearn이면,
# Directory written by mlflow.sklearn.save_model(model, "my_model") my_model/ ├── MLmodel ├── model.pkl ├── conda.yaml └── requirements.txt
이런 구조로 정의되어 있다.
MLmodel 파일은 "flavors"를 포함하고 있으며, 이러한 패턴이다.
time_created: 2018-05-25T17:28:53.35 flavors: sklearn: sklearn_version: 0.19.1 pickled_model: model.pkl python_function: loader_module: mlflow.sklearn
conda.yaml 파일과 requirements.txt 파일은 일반적인 python conda와 pip 패키지 정의 파일이다.
Model Signature
모델을 서빙 하려면, 당연히 Input과 Output이 정의되어야 한다. 이 구조를 Signature에 기록하며, 보통 다음 패턴이다.
Iris 데이터셋 패턴의 signature이다.
signature: inputs: '[{"name": "sepal length (cm)", "type": "double"}, {"name": "sepal width (cm)", "type": "double"}, {"name": "petal length (cm)", "type": "double"}, {"name": "petal width (cm)", "type": "double"}]' outputs: '[{"type": "integer"}]'
Tensorflow나 Keras, PyTorch, ONNX 포맷은 아래와 같이 NumPy array 포맷으로 전달한다. MNIST 데이터셋일 경우 아래 Signature 형태로 Input과 Output을 설정한다.
signature: inputs: '[{"name": "images", "dtype": "uint8", "shape": [-1, 28, 28, 1]}]' outputs: '[{"shape": [-1, 10], "dtype": "float32"}]'
Model API
Databricks MLflow는 model을 save/load하는 여러 방법을 제공한다. 또는 mlflow.models.Model class를 이용해 직접 model을 save/load하는 루틴을 제작 가능하다. 기본 제공하는 flavor에 없다면 이 방법으로 생성해 사용하면 된다.
우리가 사용할 만한 머신러닝 프레임워크나 toolkit은 거의 대부분 이미 제공하는 중이기 때문에, 따로 개발할 필요 없이 flavor를 이용하면 될 수준이다.
Built-in Model flavors
- Python Function (python_function)
- R Function (crate)
- H2O (h2o)
- Keras (keras)
- MLeap (mleap)
- PyTorch (pytorch)
- Scikit-learn (sklearn)
- Spark MLlib (spark)
- TensorFlow (tensorflow)
- ...
추가적으로 지원되는 Model flavors는 MLflow 공식 가이드 내용을 참조한다.
Model Customization
다양한 Built-in 모델들이 제공되지만, 지원하지 않을 경우 직접 생성 가능하다. 이때 Custom Python Models 또는 Custom Flavors를 생성해 사용 가능하다. 이건 나중에 필요할 때 찾아서 보도록 하자.
Built-In Deployment Tools
Databricks는 Cloud vender에서 사용 가능하며, 독립적인 설치나 on-prem에서 구성이 불가하다. 이렇게 Cloud vender에서 서비스를 제공하기 때문에 동적 Compute instance를 vender 제공 방식으로 사용하는데, Azure나 AWS 방식에 맞춰 원하는 대로 이용이 가능하다.
Azure일 경우 AzureML에서 제공하는 배포 방식을 이용하게 된다. MLflow의 Model 배포는 container 방식이기 때문에, Azure에서 제공하는 ACI(Azure Container Instance)와 AKS(Azure Kubernetes Service)를 이용 가능하며 AWS는 SageMaker를 통해 제공되는 Amazon ECR을 이용해 제공된다.
MLflow Model Registry의 Serving
여기까지 듣고 약간 이질적이다 라는 생각이 들면 정상이다.
- 왜 AzureML을 통해 Deployment를 릴레이 하는지? 다른 Vender가 다르면, AWS의 SageMaker를 이용?
- MLflow에 분명이 Model Serving 항목이 Model Registry에 있는데 이것은 어떻게 사용될까?
각 Cloud Vender의 입장과 Databricks간 정확한 이유는 알기 어렵지만, 각 Cloud Vender가 제공하는 컴퓨팅 리소스 관리 모델과의 통합에 이슈가 있어서 늦어지는 것이 아닐까 조심스럽게 예측해 본다.
2021년 10월 현재, Databricks의 MLflow - Serving 기능이 Preview로 제공되고 있다.
MLflow Model Serving on Azure Databricks - Azure Databricks | Microsoft Docs
Model Registry에서 배포까지 연속적으로 이어지고,
Monitoring까지 Databricks 관리 화면에서 이루어진다.
Databricks MLflow를 이용해 모델 트레이닝부터 배포까지 진행하기 원한다면, Azure에서 곧 제공할 MLflow Deployment를 기대해도 좋을 것이다.
그럼 끝으로, AzureML에서 MLflow model Serving을 하는 노트북 코드를 진행해 전체 과정을 코드로 살펴본다.
AzureML에서 MLflow model Serving 노트북 코드
이 코드는 위에서 언급한 것처럼, AzureML의 배포 모델을 MLflow에서 사용하는 패턴으로 제공된다. 노트북을 실행하기 위해서 AzureML 리소스를 Azure 포털에서 생성하고 아래 코드를 진행했다. 필요하다면, AzureML을 생성하지 않고 Python SDK 코드로 생성하는 부분도 포함.
Databricks notebook에서 추가 package 설치
# 필요한 패키지를 추가 설치한다. %pip install mlflow %pip install azureml-mlflow %pip install azureml-sdk[databricks]
azureml-sdk[databricks] 패키지는 불필요할 수 있으며, 다른 코드에서 삽질하다가 추가되었을 수도 있다.
Iris 데이터셋 트레이닝 및 Signature 추가
... iris = datasets.load_iris() iris_train = pd.DataFrame(iris.data, columns=iris.feature_names) clf = RandomForestClassifier(max_depth=7, random_state=0) clf.fit(iris_train, iris.target) # model with signature signature = infer_signature(iris_train, clf.predict(iris_train)) mlflow.sklearn.log_model(clf, "iris_rf", signature=signature)
Model을 Deploy하는 루틴이기 때문에, 위에서 논의한 Signature를 추가해야 한다.
추가된 Signature는 이렇게 Model 명세에 기록된다.
MLflow Model 배포를 위해 AzureML workspace를 연결
나는 이미 생성해 둔 AzureML workspace에 연결했다. 이런 패턴으로 workspace이름과 구독id, 리소스그룹을 알면, interactive login이 가능하고, AzureML workspace에 연결할 수 있다.
# 미리 생성해둔 AzureML workspace 연결 import azureml from azureml.core import Workspace azure_workspace = Workspace.get(name="dwazuremlws", subscription_id='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', resource_group='rg-databricks') # AzureML workspace를 생성하고 연결 # # Create or load an existing Azure ML workspace. You can also load an existing workspace using # # Workspace.get(name="<workspace_name>") # workspace_name = "<Name of your Azure ML workspace>" # subscription_id = "<Your Azure subscription ID>" # resource_group = "<Name of the Azure resource group in which to create Azure ML resources>" # location = "<Name of the Azure location (region) in which to create Azure ML resources>" # azure_workspace = Workspace.create(name=workspace_name, # subscription_id=subscription_id, # resource_group=resource_group, # location=location, # create_resource_group=True, # exist_okay=True)
AzureML workspace를 생성하고 연결하는 것도 아래의 코드를 통해 가능하다.
ACI 배포 설정
ACI는 serverless container 서비스라고 생각하면 쉽다. AzureML로 ACI를 하나 생성하고, 이 ACI에 배포하게 된다. 일반적으로 AKS와 같은 Staging/Production 환경에 배포하기 전에 개발/테스트 용도로 ACI를 이용한다.
# Create a deployment config aci_config = AciWebservice.deploy_configuration(cpu_cores=1, memory_gb=1)
MLflow로 Model을 register하고 배포 수행
model_uri = 'runs:/38789e5586854a65909bfae6fdb378ed/iris_rf' # iris_rf 로 설정 - training 코드 참조 # Register and deploy model to Azure Container Instance (ACI) (webservice, model) = mlflow.azureml.deploy(model_uri=model_uri, workspace=azure_workspace, model_name='iris-model', service_name='iris-aci-service', deployment_config=aci_config)
model_uri는 보통 runs:/RUNID/MODELNAME 패턴이다. 다른 예제 노트북은 모델부분이 "model"로 지정된 경우가 있어서 시간이 소요되었다.
확실치 않을 경우, Experiment의 model을 artifact에서 클릭하면 runid와 model uri를 확인 가능하다.
수행하면, docker image를 build해 Azure ACR(Azure Container Registry)에 올린 후, ACI에 이 image가 배포된다.
배포 후 Scoring uri 확인
# 배포 후 scoring URI 확인 print("Scoring URI is: %s", webservice.scoring_uri)
uri는 아래에서 테스트 scoring에 사용한다.
mlflow 배포 테스트 scoring
# Serving되는 모델에서 테스트 Scoring 실행 import requests import json # iris 샘플 데이터 입력 # `sample_input` is a JSON-serialized pandas DataFrame with the `split` orientation sample_input = { "columns": ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)'], "data": [[1.0, 2.0, 3.0, 4.0]] } response = requests.post( url=webservice.scoring_uri, data=json.dumps(sample_input), headers={"Content-type": "application/json"}) response_json = json.loads(response.text) print(response_json)
Postman이나 아무 Restful API 툴을 이용하는 것도 가능하고, curl로도 가능하다. Python code로 이렇게 requests 패키지로 처리해 결과를 확인할 수 있다.
이렇게 전반적인 배포 과정을 살펴보았다. 각 Cloud service vender가 제공하는 computing resource를 사용해야 하기 때문에 제약이 있고, Azure일 경우 AzureML, AWS일 경우 SageMaker를 이용하여 배포하는 처리로 진행된다.
AzureML을 사용하는 경우라면 과연 Databricks를 사용할까 살짝 고민되지만, Spark과 Databricks에 익숙하다면, 충분히 배포 역시 잘 이용 가능할 것이다.
그렇다면, MLflow의 이런 배포 패턴이 현업에서 많이 사용될까?
AzureML로 현업에서 MLOps 프로젝트와 배포 작업을 진행하면서 느끼는 것은, 이미 pre-built된 flavors나 코드를 이용하는 경우보다는, 대부분의 경우 model을 배포하는 코드를 custom docker 이미지로 생성하고 배포한다.
단순히 socring정도면 문제 없으나, 모니터링, 로깅, re-training에 사용하기 위한 dataset으로 적재 등 여러 루틴을 고려해 어플리케이션과 docker 이미지를 생성한다. 기본적으로 제공되는 구성에 이후 추가적으로 custom 이미지를 생성해 사용하게 될것이고 이부분도 잘 리뷰해 두면 이후 프로젝트에서 도움될 것이다.
이렇게 MLflow의 Model 배포까지 확인해 보았다.
참고자료
MLflow Models — MLflow 1.20.2 documentation
Deploy MLflow models as web services - Azure Machine Learning | Microsoft Docs
MLflow Model Serving on Azure Databricks - Azure Databricks | Microsoft Docs
개발자 커뮤니티 SQLER.com - Azure Databricks - MLflow를 이용한 머신러닝(1)
개발자 커뮤니티 SQLER.com - Azure Databricks - MLflow를 이용한 머신러닝(2) - Tracking
개발자 커뮤니티 SQLER.com - Azure Databricks - MLflow를 이용한 머신러닝(3) - Project
개발자 커뮤니티 SQLER.com - Azure Databricks - MLflow를 이용한 머신러닝(4) - Model Registry
CloudBreadPaPa/pyspark-basic: pyspark basic self-study repo (github.com)