이 게시글은 "BentoML - v1.0.5" 기준으로 작성되었습니다.
Model Serving 이란
MLOps는 모델 관리, 모델 배포, 모델 서빙, 모니터링 등 다양한 요소로 구성되어 있습니다. 이 글에서는 모델 배포와 서빙을 중점적으로 살펴보겠습니다. 모델 서빙이란, 머신러닝 모델을 사용할 수 있도록 배포 혹은 API를 제공하는 것을 의미합니다. 즉, 실질적으로 개발된 머신러닝 모델의 예측값을 사용자에게 전달해주는 것으로 생각할 수 있습니다.
그렇다면, 모델을 서비스하기 위해서는 어떤 방법이 가장 좋을까요? 정답은 없습니다. 사용하는 환경에 따라서 모델들을 독립적으로 배포하거나 자주 변경할 필요가 있을 수 있습니다. 적은 컴퓨팅 자원으로 효율적으로 처리할 필요가 있는 경우도 있고, 반대로 실시간에 가까운 응답이 필요할 수도 있습니다. 서비스의 목적과 환경에 따라서 적합한 방법을 찾는 것이 중요하다고 생각합니다.
최상의 서비스를 바로 제공할 수 있다면 좋겠지만, 현실적으로 우선 서비스를 제공하고 피드백을 받아 개선해 나아가며 점차 더 좋은 서비스를 만들어 과정이 필요하다고 생각합니다. 이를 위해, 모델을 쉽게 테스트하고 배포할 수 있도록 도와주는 다양한 Machine Learning Serving 라이브러리가 존재합니다. 이 글에서는 다양한 라이브러리 중에서도 쉽게 많은 기능을 사용해 볼 수 있는 BentoML을 살펴보겠습니다.
Why BentoML?
BentoML은 최근 업계에서 많이 사용하며 빠르게 생태계를 확장해 나가고 있습니다. 왜 BentoML을 선택할까요? BentoML의 기능과 장점을 한번 살펴보겠습니다.
BentoML의 구성
BentoML은 크게 Bento, Runner, Yatai의 구성으로 이뤄져 있습니다.
- Bento : 머신러닝 모델 및 실제 서비스 코드가 포함되어 하나의 Bento로 패킹된 것
- Runner : 저장된 모델을 계산하여, 실질적인 inference가 수행되는 부분
- Yatai : Bento의 배포 및 단위 관리
BentoML의 특징
- 다양한 머신러닝 프레임워크를 지원
PyTorch, Tensorflow, XGBoost 등 주요 프레임워크와 연동해 모델을 서빙할 수 있습니다. 또한, 하나의 API에서 여러 프레임워크를 사용하는 멀티 모델 기능도 지원합니다.
- Online / Offline Serving 및 Adaptive Micro Batching 지원
대표적인 서빙 방식인 Online / Offline Serving은 물론, 들어오는 요청을 모아서 모델에게 전달해주는 Adaptive Micro Batching 메커니즘을 지원합니다.
- 그 외에도 MLOps에서 필요한 다양한 기능을 제공합니다.
Model Serving with BentoML
모델 준비하기
model.py
import bentoml
import numpy as np
import torch
import torchvision
from torchvision.models.segmentation import deeplabv3_mobilenet_v3_large, DeepLabV3_MobileNet_V3_Large_Weights
# load model
weights = DeepLabV3_MobileNet_V3_Large_Weights.DEFAULT
model = deeplabv3_mobilenet_v3_large(weights=weights)
def get_transform():
transform = torchvision.transforms.Compose([
torchvision.transforms.ToPILImage(),
torchvision.transforms.Resize(520),
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
return transform
transform = get_transform()
# wrapping model
class deeplabv3_mobilenet(torch.nn.Module):
def __init__(self, model):
super().__init__()
self.model = model
def forward(self, json_input):
# convert json input to tensor
image = np.array(json_input['image'], dtype=np.uint8)
tensor_image = transform(image).unsqueeze(0)
# convert tensor output to json
output = self.model(tensor_image)['out'].squeeze(0)
output = torch.argmax(output, dim=0)
return output
if __name__ == "__main__" :
# saving model for BentoML service
# signatures를 수정하여, batch 옵션을 설정할 수 있습니다.
saved_model = bentoml.picklable_model.save_model(
"deeplabv3_mobilenet", deeplabv3_mobilenet(model), signatures={"__call__": {"batchable": False}}
)
다음 코드를 실행하여 ML model을 BentoML 서비스에서 사용할 수 있도록 BentoML API로 만듭니다.
$ python model.py
생성된 API는 CLI command를 통해서 확인할 수 있습니다.
$ bentoml models list
Tag Module Size Creation Time
mnist_cnn:vbwwwccghsghn67y bentoml.pytorch 4.58 MiB 2022-10-07 21:36:25
deeplabv3_mobilenet:i5fhc6sflcghn67y bentoml.pytorch 42.33 MiB 2022-10-06 18:21:37
deeplabv3_mobilenet:ytyttlcessghn67y bentoml.pytorch 42.33 MiB 2022-10-05 19:02:06
서비스 준비하기
service.py
from typing import Any
from pydantic import BaseModel
import bentoml
from bentoml.io import JSON
# load model as runner instance
segmentation_runner = bentoml.picklable_model.get("deeplabv3_mobilenet").to_runner()
svc = bentoml.Service(
name ="deeplabv3_mobilenet_demo",
runners=[segmentation_runner],
)
class InputData(BaseModel):
image: Any
# 기본설정은 function 이름이 end-point URL로 설정됨.
# URL을 설정하고 싶으면 api 데코레이터에 route argument로 설정
@svc.api(input=JSON(), output=JSON())
async def predict_image(data: InputData):
prediction = await segmentation_runner.async_run(data)
return prediction
bentofile.yaml
service: "service:svc"
description: "file: ./README.md"
include:
- "*.py"
exclude:
- ""
conda:
environment_yml: ./conda.yaml
conda.yaml
name: deeplabv3_mobilenet
channels:
- pytorch
- defaults
dependencies:
- python=3.8
- pytorch
- torchvision
- cudatoolkit=11.3
- numpy
- pip
- pip:
- pydantic
BentoML 서비스하기
BentoML 이미지 빌드
$ bentoml build
저장한 모델과 서비스 코드를 하나의 Bento로 포장합니다.
BentoML 컨테이너 생성
$ bentoml containerize deeplabv3_mobilenet_demo:latest
# 사용할 컨테이너 확인
$ bentoml list
Tag Size Creation Time Path
deeplabv3_mobilenet_demo:fq2ygmcdy6ghn67y 42.33 MiB 2022-10-04 18:30:23 ~/bentoml/bentos/deeplabv3_mobilenet_demo/fq2ygmcdy6ghn67y
$ docker run -d -it -p 3000:3000 deeplabv3_mobilenet_demo:fq2ygmcdy6ghn67y
포장된 Bento를 실제 사용자에게 배포하기 위해서, 컨테이너를 생성하여 도커로 실행시킵니다.
그래서 BentoML?
API, Docker 등 간단하게 생성할 수 있는 편리하다는 큰 장점이 있습니다. 그 외에도 로깅이나 모니터링을 위한 기능을 기본적으로 제공하여 강력한 MLOps 모델 서빙 도구라고 볼 수 있습니다. 하지만, 다른 성능 관점에서는 다소 아쉬운 부분들이 보였습니다.
끝으로 제 생각을 말씀드리면, BentoML과 Nvidia Triton Inference Server를 비교해보며 동일 조건에서 BentoML의 CPU의 사용량이 많다고 느꼈습니다. 가벼운 모델을 서비스하기 위해서는 BentoML도 크게 성능이 차이가 나지 않지만, 다소 무거운 모델과 한정된 CPU에서는 성능 차이가 다소 발생하였습니다. 결론적으로, "빠르고 편리하게 배포할 수 있는 큰 장점이 있고, 서비스 환경에 따라서 성능은 다소 검토해 볼 필요가 있다." 정도로 정리해 볼 수 있을 것 같습니다.
References
- https://github.com/bentoml/BentoML
- https://github.com/bentoml/gallery
- https://docs.bentoml.org/en/v1.0.5/
- https://zzsza.github.io/mlops/2021/04/18/bentoml-basic/
- https://engineering.linecorp.com/ko/blog/mlops-bentoml-1/
- https://engineering.linecorp.com/ko/blog/mlops-bentoml-2/
의견과 질문은 언제나 감사합니다.
'Study > MLOps' 카테고리의 다른 글
AWS Container Support Service (1/3) (0) | 2024.03.07 |
---|---|
근본의 Ansible? (0) | 2024.01.03 |
Slurm과 Kubernetes 정답은? (0) | 2023.12.06 |
도대체 MLOps는 무엇일까? (1) | 2023.11.21 |
pydantic을 사용하여, 안정성 높이기 (0) | 2023.01.26 |