이 포스팅에서는 AzureML 모델을 웹 서비스로 배포하고 Evaluation을 진행한다.
(4) AzureML - Azure Machine Learning 모델 배포(Deploy)
지난 포스팅 (3) AzureML - Azure Machine Learning 구성요소 에서 AzureML SDK를 이용해 머신러닝 모델을 만들고 모델을 Register 하는 과정까지 진행했다. 지난 포스팅 내용을 완료해야 이번 모델 배포(Deploy)를 완료할 수 있으니, 이전 문서를 참조해 model register까지 완료한다.
마찬가지로, 이 포스팅 역시 Github 공식 AzureML 노트북 문서를 이용해 진행된다.
모델 배포를 위한 AzureML 패키지 설정
지난 작업과 같다. 필요한 패키지 설정을 수행.
%matplotlib inline import numpy as np import matplotlib.pyplot as plt import azureml.core # display the core SDK version number print("Azure ML SDK Version: ", azureml.core.VERSION)
배포될 서비스에서 사용할 score.py 파일 설정
AzureML 배포 작업을 수행하면 docker 설정이 완료되며, container 환경에서 수행된다. Azure에서 제공하는 container 서비스는 ACI(Azure Container Instance)와 AKS(Azure Kubernetes Service)가 있으며, 양쪽 모두에 AzureML로 배포가 가능하다. 이 포스팅에서는 ACI로 배포를 수행하고, 이후 AKS 배포 역시 다른 포스트로 진행 예정.
이제 score.py 파일을 생성한다. Jupyter notebook에서 파일 쓰기 기능을 선언하고 작성한다.
%%writefile score.py import json import numpy as np import os import pickle import joblib def init(): global model # AZUREML_MODEL_DIR is an environment variable created during deployment. # It is the path to the model folder (./azureml-models/$MODEL_NAME/$VERSION) # For multiple models, it points to the folder containing all deployed models (./azureml-models) model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), 'sklearn_mnist_model.pkl') model = joblib.load(model_path) def run(raw_data): data = np.array(json.loads(raw_data)['data']) # make prediction y_hat = model.predict(data) # you can return any data type as long as it is JSON-serializable return y_hat.tolist()
배포 설정 파일 생성
ACI에 배포를 준비 중이다. 이 ACI에 배포하려면 "AciWebservice.deploy_configuration" 구성을 수행해야 한다.
아래 코드와 같이 1개 CPU를 사용하고, 1G의 메모리를 점유하는 ACI 컨테이너를 생성하고 배포한다.
from azureml.core.webservice import AciWebservice aciconfig = AciWebservice.deploy_configuration(cpu_cores=1, memory_gb=1, tags={"data": "MNIST", "method" : "sklearn"}, description='Predict MNIST with sklearn')
ACI로 배포 수행
이제, 모든 ACI 배포 설정이 완료되었다. 모델 배포를 수행하자.
지난 포스팅에서 트레이닝을 수행해 생성한 모델인 "sklearn_mnist" 모델을 참조한다.
... model = Model(ws, 'sklearn_mnist') ...
생성한 Environment를 가져온다.
... myenv = Environment.get(workspace=ws, name="tutorial-env", version="1") ...
Inference config를 설정하고, deploy를 수행한다.
... inference_config = InferenceConfig(entry_script="score.py", environment=myenv) service_name = 'sklearn-mnist-svc-' + str(uuid.uuid4())[:4] service = Model.deploy(workspace=ws, name=service_name, models=[model], inference_config=inference_config, deployment_config=aciconfig) ...
"service" Object가 이후 prediction에 사용된다. 자세히 살펴보자.
모델 배포에 사용할 설정을 완료했다. 실제 코드를 실행해 배포를 진행한다.
모델을 ACI로 배포하는 코드를 수행
%%time import uuid from azureml.core.webservice import Webservice from azureml.core.model import InferenceConfig from azureml.core.environment import Environment from azureml.core import Workspace from azureml.core.model import Model ws = Workspace.from_config() model = Model(ws, 'sklearn_mnist') myenv = Environment.get(workspace=ws, name="tutorial-env", version="1") inference_config = InferenceConfig(entry_script="score.py", environment=myenv) service_name = 'sklearn-mnist-svc-' + str(uuid.uuid4())[:4] service = Model.deploy(workspace=ws, name=service_name, models=[model], inference_config=inference_config, deployment_config=aciconfig) service.wait_for_deployment(show_output=True)
배포에 약간의 시간이 소요된다.
Scoring URL 출력
배포가 완료되면, 아래 명령으로 scoring을 수행할 URL을 출력할 수 있다.
print(service.scoring_uri)
이제 웹 서비스로 배포된 모델에서 Test를 수행한다.
배포가 완료된 웹 서비스에서 모델 테스트 수행
Python 코드를 이용해 생성된 모델로 test나 evaluation이 가능하다. 물론 이 노트북처럼 웹 서비스에 Restful API 방식으로 batch 요청을 보내 처리도 가능하다.
테스트 수행을 위해 test 데이터를 다운로드
import os from azureml.core import Dataset from azureml.opendatasets import MNIST data_folder = os.path.join(os.getcwd(), 'data') os.makedirs(data_folder, exist_ok=True) mnist_file_dataset = MNIST.get_file_dataset() mnist_file_dataset.download(data_folder, overwrite=True)
테스트 데이터를 로드
from utils import load_data import os import glob data_folder = os.path.join(os.getcwd(), 'data') # note we also shrink the intensity values (X) from 0-255 to 0-1. This helps the neural network converge faster X_test = load_data(glob.glob(os.path.join(data_folder,"**/t10k-images-idx3-ubyte.gz"), recursive=True)[0], False) / 255.0 y_test = load_data(glob.glob(os.path.join(data_folder,"**/t10k-labels-idx1-ubyte.gz"), recursive=True)[0], True).reshape(-1)
Predict 수행
service.run()이 prediction을 수행하는 코드이다. 이렇게 AzureML SDK가 제공하는 기능을 사용해 손쉽게 prediction이 가능하다.
import json test = json.dumps({"data": X_test.tolist()}) test = bytes(test, encoding='utf8') y_hat = service.run(input_data=test)
Confusion matrix 조회 / plotting 수행
실제 label 데이터와 예측한 y_hat 데이터가 있어서 confusion matrix 생성이 가능하다.
from sklearn.metrics import confusion_matrix conf_mx = confusion_matrix(y_test, y_hat) print(conf_mx) print('Overall accuracy:', np.average(y_hat == y_test)) # normalize the diagonal cells so that they don't overpower the rest of the cells when visualized row_sums = conf_mx.sum(axis=1, keepdims=True) norm_conf_mx = conf_mx / row_sums np.fill_diagonal(norm_conf_mx, 0) fig = plt.figure(figsize=(8,5)) ax = fig.add_subplot(111) cax = ax.matshow(norm_conf_mx, cmap=plt.cm.bone) ticks = np.arange(0, 10, 1) ax.set_xticks(ticks) ax.set_yticks(ticks) ax.set_xticklabels(ticks) ax.set_yticklabels(ticks) fig.colorbar(cax) plt.ylabel('true labels', fontsize=14) plt.xlabel('predicted values', fontsize=14) plt.savefig('conf.png') plt.show()
heatmap의 가독성이 약간 기대와 틀린 듯 한데... 여하간 출력하였다.
Prediction 결과 출력
30건 정도의 랜덤 샘플로 prediction을 수행하고, 결과를 plot으로 표시.
import json # find 30 random samples from test set n = 30 sample_indices = np.random.permutation(X_test.shape[0])[0:n] test_samples = json.dumps({"data": X_test[sample_indices].tolist()}) test_samples = bytes(test_samples, encoding='utf8') # predict using the deployed model result = service.run(input_data=test_samples) # compare actual value vs. the predicted values: i = 0 plt.figure(figsize = (20, 1)) for s in sample_indices: plt.subplot(1, n, i + 1) plt.axhline('') plt.axvline('') # use different color for misclassified sample font_color = 'red' if y_test[s] != result[i] else 'black' clr_map = plt.cm.gray if y_test[s] != result[i] else plt.cm.Greys plt.text(x=10, y =-10, s=result[i], fontsize=18, color=font_color) plt.imshow(X_test[s].reshape(28, 28), cmap=clr_map) i = i + 1 plt.show()
위의 prediction들은 모두 service.run() 으로 prediction을 수행했다. 물론, Restful API이기 때문에 Python Requests 패키지를 이용해 HTTP POST 방식으로 요청도 가능하다.
import requests # send a random row from the test set to score random_index = np.random.randint(0, len(X_test)-1) input_data = "{\"data\": [" + str(list(X_test[random_index])) + "]}" headers = {'Content-Type':'application/json'} # for AKS deployment you'd need to the service key in the header as well # api_key = service.get_key() # headers = {'Content-Type':'application/json', 'Authorization':('Bearer '+ api_key)} resp = requests.post(service.scoring_uri, input_data, headers=headers) print("POST to url", service.scoring_uri) #print("input data:", input_data) print("label:", y_test[random_index]) print("prediction:", resp.text)
배포 삭제
이렇게 ACI로 모델을 배포하고 prediction도 잘 수행했다. 여러 테스트가 완료되면 ACI를 삭제한다.
service.delete()
AzureML을 이용해 생성한 모델을 배포하는 과정을 수행하였다. 일반적으로 ACI는 테스트 형태로 validation 목적으로 배포해 사용하고, 실제 production 수준의 scale이나 GPU inference가 필요할 경우 AKS에 배포를 수행한다.
실제 어느정도 개발팀과 DS(Data Scientist) 팀에 규모가 있을 경우, 모든 배포 과정은 이렇게 코드를 통해 배포하지 않고, DevOps를 이용해 자동화해서 모델을 배포하게 된다. 이러한 머신러닝 모델 라이프사이클 관리가 MLOps이다.
다음 포스팅에서는 여러 AzureML의 구성요소에 대해 좀더 깊이 있게 다루는 과정을 진행할 예정이다.
참고자료
개발자 커뮤니티 SQLER.com - MLaaS - (1) 12가지의 머신러닝을 먼저 도입한 기업들의 고민
개발자 커뮤니티 SQLER.com - (2) AzureML - Azure Machine Learning 이란 무엇인가?
개발자 커뮤니티 SQLER.com - (3) AzureML - Azure Machine Learning 구성요소
안녕하세요! 제가 azure ml에 관해 몇가지 질문이 있는데 혹시 연락드릴 수 있는 방법이 있을까요?ㅠ