Data Engineering 및 Infra

BentoML이란? 사용법과 example 정리 - 머신러닝(machine learning) 모델을 API로 serving하기

이수진의 블로그 2021. 8. 2. 08:28
반응형
728x170

포스팅 개요

이번 포스팅은 머신러닝 모델(machine learning model) 혹은 딥러닝 모델(Deep Learning model)을 API 형태로 서빙(serving) 할 수 있는 Python BentoML에 대해서 간단하게 소개하고 예제(example)을 정리하는 글입니다.

 

BentoML글은 아래와 같이 총 2개 혹은 3개 정도의 글로 정리하려고 합니다.

  • Machine learning model serving BentoML 간단 소개 및 설치 방법과 기본 예제(example) ( 이번 글 )
  • Tensorflow(Keras)와 같이 사용하는 법, 2개 이상 모델을 사용하는 법 및 Docker 등 다양한 예시 정리

이번 포스팅은 위의 내용 중 

  • bentoml이란 무엇인가?
  • bentoml 사용법과 예제(example) 정리

를 정리하려고 합니다.

 

제가 참고한 자료는 아래와 같습니다.

 

bentoml/BentoML

Model Serving Made Easy. Contribute to bentoml/BentoML development by creating an account on GitHub.

github.com

 

또한 제 블로그에 올린 관련 전체 코드는 아래 github에서 관리 및 업로드 하고 있습니다.

 

GitHub - lsjsj92/python_bentoml_example: Python bentoML(API serving for machine learning model) example & tutorial code

Python bentoML(API serving for machine learning model) example & tutorial code - GitHub - lsjsj92/python_bentoml_example: Python bentoML(API serving for machine learning model) example & tu...

github.com


포스팅 본문

BentoML이란 무엇인가?

가장 먼저 BentoML이란 무엇인지 정리하면서 포스팅을 진행하고자 합니다. BentoML github에서는 BentoML을 이렇게 설명하고 있습니다.

BentoML is a flexible, high-performance framework for serving, managing, and deploying machine learning models.

- Supports multiple ML frameworks, including Tensorflow, PyTorch, Keras, XGBoost and
- Cloud native deployment with Docker, Kubernetes, AWS, Azure and many
- High-Performance online API serving and offline batch serving
- Web dashboards and APIs for model registry and deployment management

머신러닝과 딥러닝(machine learning and deep leaning) 모델을 만들고 이후 이 model을 어떻게 serving할 것인가는 큰 고민거리입니다. 단순히 ML/DL model predict 결과를 Database에 저장하여 사용할 것인지 아니면 API를 사용할 것인지 등을 고려애햐 합니다. 또한, 이 모델이 우리가 의도한 의도대로 동작이 되는지 테스트 해보는 것도 중요하죠. 

 

MLOps에서 이야기 할 때 많이 언급되기도 하는 BentML은 이러한 고민거리에 포커싱 되어진 라이브러리입니다. 

AI 프로젝트를 진행하는 팀이 machine learning(deep learning) model을 만들면 해당 모델을 쉽게 배포, 테스트 등을 할 수 있어야 합니다. BentoML은 이러한 부분을 쉽게 제공해줍니다. 파이썬(Python) simple한 코드 몇 줄로 쉽게 production에 적용할 수 있는 API 서버를 구성할 수 있고 또한, Dockerfile도 제공해주어 docker build로 image를 간편하게 만들 수도 있습니다.


BentoML 설치 방법

BentoML을 설치하는 방법은 굉장히 간단합니다. 저는 아래와 같은 환경에서 BentoML을 설치해보고 테스트를 진행해 보았습니다.

  • MacOS
    • Catalina version10
    • Python3.8
  • Windows
    • Version 10
    • Python3.7
    • 단, windows에서는 bentoml cli 적용이 쉽지 않아서 docker image를 build하여 docker로만 사용함

윈도우에서는 bentoml cli가 쉽게 적용이 되지 않은 문제가 있었습니다. ( 적어도 제 환경에서는요 ) 그래서 윈도우는 bentoml을 docker image를 build하여 사용했습니다.

 

bentoml은 Python 라이브러리 이므로 설치하는 방법은 pip install bentoml 로 설치해주시면 됩니다.

pip install bentoml

BentoML 간단한 예제

이렇게 설치한 bentoml을 간단한 예제를 통해 바로 확인해봅니다. 이번 글의 간단 예제에서는 아래와 같은 환경으로 진행합니다.

  • 캐글(kaggle)에 올라와 있는 titanic data를 활용
  • tensorflow(keras)가 아닌 scikit-learn을 활용 ( tensorflow 활용 예제는 다음 글에 올릴 예정입니다. )

보다 더 자세한 그리고 다양한 예제는 개요에 링크로 올린 bentoml gallery를 보시면 다양한 예제가 많이 있으니 참고하시면 되겠습니다.

간단 예제의 전체 코드 및 bentoml serving은 아래와 같은 프로세스로 흘러갑니다.

  1. 타이타닉 csv data load
  2. 전처리(preprocessing)
  3. 모델 훈련(model training with randomforest)
  4. training 된 model return
  5. model packing
  6. bentoml service bundle 생성
  7. bentoml serving
  8. web 화면 & api test

관련 코드

타이타닉 데이터 전처리하고 machine learning model을 training 하는 부분의 코드는 생략하겠습니다. 이미 캐글 등에 많이 나와 있는 코드이므로 그것들을 사용하시면 되겠습니다. 제가 만든 전체 코드가 궁금하시면 개요에 올려드린 제 github(https://github.com/lsjsj92/python_bentoml_example)를 참고해주세요.

 

main.py

main에서는 진행하는 titanic bentoml example code의 main process를 담당합니다.

titanic.run()을 통해 scikit-learn의 랜덤포레스트(randomforest) model이 return 되어서 가져오게 됩니다.

그리고 가져온 model을 bentoml에 packing합니다.

 

*참고 bentoml에서 packing이란?

  • 머신러닝 또는 딥러닝 모델을 저장하는 개념
from titanic import TitanicMain
from bentoml_process import BentoML

if __name__ == "__main__":

    titanic = TitanicMain() 
    bento_ml = BentoML()
    model = titanic.run()  # 타이타닉 관련 코드 실행 -> 모델 return
    bento_ml.run_bentoml(model)  # model을 넘겨줘서 bentoml 프로세스 실행
    
    
'''

참고. 위의 titanic.run() 부분 코드는 아래와 같습니다.

def run(self):
    data = self._get_data(self.titanic_path)
    data = self.run_preprocessing(data)
    X, y = self._get_X_y(data)
    model = self.run_sklearn_modeling(X, y)

    return model


'''

 

bentoml_process.py

  • 머신러닝 혹은 딥러닝 모델(machine learning or deep learning model)을 입력으로 받음
  • bentoml classifier 객체를 생성해서 packing을 진행
  • packing을 한 후 결과값 저장

해당 코드에서는 위에서 넘겨 받은 model을 BentoML 환경에 맞게 packing하는 과정을 진행합니다. 그리고 이러한 환경 값들을 저장하여 docker 등의 다양한 파일을 떨궈줍니다.

from config import EnvConfig
from classifier import TitanicClassifier

class BentoML:
    def run_bentoml(self, model):
        classifier_service = TitanicClassifier() # classifier객체 생성
        classifier_service.pack('rf_model', model) # packing

        saved_path = classifier_service.save() # 저장

*참고 bentoml 실행 후 저장 결과 예시

 

classifier.py

  • classifier.py ( 여기선 TitanicClassifier )
    • 각종 bentml의 기능을 담고 있는 파일
    • BentoService를 상속하여 사용
    • @env, @artifacts, @api 등 다양한 데코레이터 사용
    • @api로 붙은 def의 이름은 api call시 명시되는 경로값으로 사용되고 경로에 따른 def가 호출 됌

classifier는 BentoService를 상속하는 클래스를 관리합니다. 해당 클래스에서는 @env, @artifacts, @api 등의 데코레이터를 통해서 BentoML에서 관리하는 artifact들, 환경(environment, env), api input 등 다양한 옵션을 설정할 수 있습니다. 이 decorator를 사용할 수 있는 다양한 방법은 아래 추가적인 사용 방법 섹션에 정리해두었습니다. 여기서는 간단한 예시만 보기로 하였으니, 사용 방법만 간단히 정리합니다.

from typing import Mapping
import pandas as pd

from bentoml import env, artifacts, api, BentoService
from bentoml.adapters import DataframeInput
from bentoml.frameworks.sklearn import SklearnModelArtifact
from bentoml.service.artifacts.common import PickleArtifact

@env(infer_pip_packages=True)  # pip package를 설치 -> 추정해서 설치하도록 함
@artifacts([PickleArtifact('rf_model')]) # artifact로 관리. model을 아티팩트화 한다
class TitanicClassifier(BentoService):

    @api(input=DataframeInput(), batch=True)
    def predict(self, df: pd.DataFrame): # 입력은 dataframe 형태로 받음
        return self.artifacts.rf_model.predict(df) # model predict결과 return



bentoml API serve 실행 및 api 호출 결과

이제 만들어진 bentoml process를 실행합니다. 제 환경에서는 main.py를 실행하면 titanic 데이터 load - preprocess - model training - bentoml packing - bentoml save 까지 관련 프로세스들이 실행됩니다.

python main.py

이렇게 bentoml과 관련된 코드를 실행시키면 INFO logging이 나오면서 bentoservice bundle과 함께 만든 classifier class 이름 그리고 버전이 명시되어서 나옵니다. 또한, save 경로도 함께 출력이 됩니다.

이때 bentoml이 저장되는 곳은 기본 경로로 아래와 같은 경로에 저장이 된다고 합니다. ( 설정으로 바꿔줄 수 있다고도 본 것 같습니다. )

  • ~/bentoml/repository/{name}/{version}

따라서 python main.py로 실행한 후 해당 경로로 들어간 뒤 tree 명령어를 보면 아래와 같은 구조를 확인할 수 있을겁니다.

bentoml에서 가장 특이한 점은 바로 Dockerfile을 생성해 준다는 점입니다. 저 Dockerfile을 이용해서 단순히 docker build 한 뒤 사용해주면 되기 때문에 정말 간편합니다. docker로 사용하는 글은 해당 글이 너무 길어지기 때문에 다음 글에 정리하도록 하겠습니다.

 

이렇게 만들어진 bentoml service를 이제 serving 하면 됩니다. 아래와 같은 명령어로 실행할 수 있습니다.

bentoml serve {classifier}:{version}

위 사진과 명령어와 같이 실행시키면 running on http~ 라고 나오면서 잘 실행이 된 것을 확인할 수 있습니다. 이렇게 하면 API 서버(API server)가 활성화 되었다고 생각하시면 될 것 같습니다.

실제로 저기서 제공해주는 127.0.0.1:5000으로 들어가게 되면 아래와 같은 swagger web ui 화면을 확인할 수 있습니다.

이제 이 실행된 bentoml serve에 api를 호출해보시면 관련 결과 값을 받을 수 있습니다. 저는 타이타닉 데이터이므로 데이터를 넘겨주면 생존하였는가? 혹은 생존하지 못했는가?의 1과 0의 결과값이 response 될 것입니다. API server가 켜진 commend line말고 새로운 cmd를 켜서 API 호출로 확인해보겠습니다.

curl -i --header "Content-Type: application/json" \
    --request POST --data '[[1, 1, 5], [0, 2, 3], [0, 1, 1]]' \
    http://localhost:5000/predict

위 사진과 같이 결과가 [1, 0]으로 나오는 것을 확인할 수 있습니다. 즉, titanic classifier가 api 호출을 받고 해당 데이터를 기반으로 생존하였는지, 못 하였는지 예측 값을 return 해주는 것이죠.

그러면 앞서 server를 실행시킨 cmd에서는 어떻게 나올까요?

api를 호출하면 api serving을 하고 있는 cmd에선 위와 같은 log가 나오는 것을 볼 수 있습니다. 저 log 값들을 사용하면 나중에 다른 방면으로 활용할 수도 있겠죠?


BentoML 추가적인 사용 방법

추가적인 bentoml decorator(데코레이터) 사용 방법

위에 classifier에서는 @env, @api, @artifacts등 다양한 decorator를 활용해서 bentoml의 다양한 환경 등을 설정할 수 있다고 했습니다. 해당 데코레이터 안에는 다양한 옵션을 넣을 수 있습니다. 간단하게 이러한 옵션들을 알아보겠습니다. 더 자세한 것은 공식 문서를 참고하시면 되겠으며 제 후속 글에서도 다루도록 하겠습니다.

 

@env decorator

각종 환경과 관련된 설정을 넣을 수 있습니다. 이번 예제에서는 infer_pip_packages=True 값을 넣어주었는데요. 아래와 같은 옵션들을 넣어줄 수도 있습니다.

  • infer_pip_packages : 필요한 package를 추론해서 설치
  • requirements_txt_files : requirements.txt 파일등을 경로로 설정해서 사용할 수 있음 
    • ex) requirements_txt_files="./requirements.txt"
  • pip_packages : 필요한 package를 직접 명시
    • ex) pip_packages=['scikit-learn==0.24.1', 'tensorflow==2.2.0']
  • docker_base_image : docker 환경으로 셋팅
  • setup_sh : shell script를 이용한 설정

 

@api decorator

api와 관련된 설정을 넣을 수 있습니다. 위 예제에서는 input에 DataframeInput을 넣었습니다. 이외에도 JsonInput()과 같은 것을 사용해서 Json 형태로 데이터를 받을 수도 있습니다. bentoml JsonInput으로 받는 예제는 아래와 같이 사용할 수 있습니다. 또한, 아래 예제에서는 bentoml의 @env에서 requirements_txt_file 매개값을 이용해 requirements.txt를 적용한 예제입니다.

from bentoml.types import JsonSerializable
from bentoml.adapters import DataframeInput, JsonInput

@env(
    requirements_txt_file="./requirements.txt"
)
@artifacts([KerasModelArtifact('tf_model'), PickleArtifact('mapping')])
class TitanicTFClassifier(BentoService):

    def mapping_json_value(self, data):
        return self.artifacts.mapping.get(data)

    @api( input = JsonInput(), batch = True )
    def predict(self, json_list: List[JsonSerializable]):
        results = []
        for i in json_list:
            i['Gender'] = self.mapping_json_value(i['Gender'])
            predict_data = np.array([value for _, value in i.items()]).reshape(1, -1)
            results.append( self.artifacts.tf_model.predict( predict_data )[0])
        return results

 

curl -i \
  --header "Content-Type: application/json" \
  --request POST \
  --data '[{"Gender": "male", "Age_band": 2, "Pclass": 1}, {"Gender": "female", "Age_band": 1, "Pclass": 3}]' \
  localhost:5000/predict

BentoML에서 api를 JsonInput으로 받게 되면 List[JsonSerializable]로 받을 수 있습니다. 이렇게 되면 API로 호출한 값들이 리스트로 들어오게 되고 각각을 json 형태로 받을 수 있게 됩니다. 즉, for문을 이용해 list의 요소 하나하나에 접근하고 요소 하나하나가 json이기 때문에 .items()와 같은 것을 사용할 수 있는 것입니다.

 

@artifacts decorator

bentoml에서 사용하는 아티팩트(artifact)들을 지원해주는 데코레이터입니다. 많이 사용하는 artifacts decorator는 아래와 같습니다.

  • SklearnModelArtifact : 사이킷런(scikit-learn) 머신러닝 모델(machine learning model)을 아티팩팅 할 때 사용합니다.
  • JSONAritfact : Json data를 아티팩팅 할 때 사용할 수 있습니다.
  • KerasModelArtifact : 텐서플로 케라스(tensorflow keras)의 모델을 아티팩팅 할 때 사용합니다.
  • PickleArtifact : 다양한 데이터를 pickle 형식으로 아티팩팅 합니다. bentoml을 사용하다보면 sklearnmodelartifact가 에러가 날 때가 있는데요. 이떄 PickleArtifact를 사용하면 에러없이 사용할 수 있습니다. 제 본문에서도 이렇게 사용했습니다.

기타 다른 방법은 공식 문서를 참고해주세요.


Yatai 사용하기

bentoml에서는 model serving api만 제공하는 것이 아니라 Yatai라는 것을 사용할 수 있습니다.

*참고 Yatai란?

  • bentoml에서 실행되는 각종 머신러닝, 딥러닝 모델들을 관리해주는 서비스

yatai는 아래와 같이 실행할 수 있습니다.

 bentoml yatai-service-start

저는 도커(docker)로 실행하였습니다.

  docker run \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v ~/bentoml:/bentoml \
    -p 3000:3000 \
    -p 50051:50051 \
    bentoml/yatai-service:latest

yatai를 실행하면 맨 아래 예시가 나옵니다. 이 예시들은

  • bentoml list --yatai-url 
  • bentoml push {Classifier}:{version} --yartai-url=127.0.0.1:50051

과 같은 예시입니다. 즉, Yatai에서 model을 관리하고 볼 수 있도록 설정할 수 있는데요. push를 해보겠습니다.

bentoml push TitanicSKlearnClassifier:20210715190338_478857 --yatai-url=127.0.0.1:50051

 

그리고 나서 list를 확인해보면 방금 push한 모델 정보가 들어간 것을 확인할 수 있습니다.

또한, 해당 모델 정보는 웹 페이지에 들어가도 나오게 됩니다.

 

즉 이렇게 yatai를 이용하면 모델을 web ui상으로 쉽게 관리할 수 있습니다.

 


마무리

본 포스팅은 머신러닝 모델(machine learning model)과 딥러닝 모델(deep learning model)을 API 형태로 serving 할 수 있게 도와주는 bentoml의 기본적인 사용 방법에 대해 정리해봤습니다.

다음 글(https://lsjsj92.tistory.com/624)에서는 기본적인 예제 외에 다양한 사용 법에 대해서 정리해보려고 합니다.

부디 도움이 되시길 바랍니다.

 

반응형
그리드형