- PostgreSQL DB: Backend Store로서 이용 - 모델의 accuracy, f1-score, loss, hyperparameter와 같은 수치 정보 & MLflow의 운영 정보, 메타 데이터 (run_id, run_name, experiment_name) 등을 저장할 물리적인 서버
- MinIO: Artifact Store로서 이용 - 학습된 모델을 저장하는 model registry로써 이용하기 위한 스토리지 서버 (run_id 등도 여기서 가져옴)
흐름: minio로 되어 있는 artifact store에서 모델을 mlflow를 통해 로컬에 다운받고 -> 파라미터 값들을 작성해서 api 호출을 하면 -> 내 로컬에서 api로 전달된 값을 바탕으로 모델 inference를 하고 -> inference 결과값을 클라이언트에 반환해주는 방식으로 만들기
1. 모델 다운로드
# download_model.py
import os
from argparse import ArgumentParser
import mlflow
# set environments
os.environ["MLFLOW_S3_ENDPOINT_URL"] = "http://localhost:9000" # minIO 접속 url
os.environ["MLFLOW_TRACKING_URI"] = "http://localhost:5001" # mlflow 접속 url
os.environ["AWS_ACCESS_KEY_ID"] = "minio"
os.environ["AWS_SECRET_ACCESS_KEY"] = "miniostorage"
def download_model(args):
# download model artifacts
mlflow.artifacts.download_artifacts(artifact_uri=f"runs:/{args.run_id}/{args.model_name}", dst_path=".")
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument("--model-name", dest="model_name", type=str, default="sk_model")
parser.add_argument("--run-id", dest="run_id", type=str)
args = parser.parse_args()
download_model(args)
Model artifacts는 MLflow에 모델이 저장될 때 함께 저장된 메타데이터와 모델 자체의 binary 파일을 의미
- mlflow.artifacts.download_artifacts(artifact_uri=f"runs:/{args.run_id}/{args.model_name}", dst_path=".")
- artifact_uri: URI pointing to the artifacts (Exactly one of artifact_uri or run_id must be specified)
- run_id: ID of the MLflow Run containing the artifacts. (Exactly one of artifact_uri or run_id must be specified)
- artifact_path: For use with run_id) If specified, a path relative to the MLflow Run’s root directory containing the artifacts to download.
- dst_path: Path of the local filesystem destination directory to which to download the specified artifacts.
- traking_uri: The tracking URI to be used when downloading artifacts.
localhost:5001로 mlflow에 접속하여 run_id 확인하기
확인한 run_id를 바탕으로 python 스크립트 실행하기
python download_model.py --model-name sk_model --run-id 9ddb1882473046abaa17f874908194f1
스크립트 파일 실행 후 실험 이름으로 된 폴더가 생성된 것을 볼 수 있음 (위에서 현재 폴더에 다운로드 하도록 설정함)
폴더 안에는 모델, 환경설정 파일 등이 다운로드 됨
2. 서빙에 필요한 API 구현하기
2-1. data validation을 위한 schema 클래스 만들기
# schemas.py
from pydantic import BaseModel
class PredictIn(BaseModel):
mean_radius: float
mean_texture: float
mean_perimeter: float
mean_area: float
mean_smoothness: float
mean_compactness: float
mean_concavity: float
mean_concave_points: float
mean_symmetry: float
mean_fractal_dimension: float
radius_error: float
texture_error: float
perimeter_error: float
area_error: float
smoothness_error: float
compactness_error: float
concavity_error: float
concave_points_error: float
symmetry_error: float
fractal_dimension_error: float
worst_radius: float
worst_texture: float
worst_perimeter: float
worst_area: float
worst_smoothness: float
worst_compactness: float
worst_concavity: float
worst_concave_points: float
worst_symmetry: float
worst_fractal_dimension: float
class PredictOut(BaseModel):
target: int
2-2. API 구현을 위한 app.py 스크립트 파일 만들기
# app.py
import mlflow
import pandas as pd
from fastapi import FastAPI
from schemas import PredictIn, PredictOut
def get_model():
model = mlflow.sklearn.load_model(model_uri="./sk_model")
return model
MODEL = get_model()
# create a FastAPI instance
app = FastAPI()
@app.post("/predict", response_model=PredictOut)
def predict(data: PredictIn) -> PredictOut:
df = pd.DataFrame([data.dict()])
pred = MODEL.predict(df).item()
return PredictOut(target=pred)
2-3. 작성한 API 실행해보고, 데이터도 날려보기
uvicorn app:app --reload
swagger UI로 확인하기 & 데이터 날려보기 => predict 결과값을 잘 반환해줌
3. Model API를 dockerize하여 컨테이너로 띄우기
3-1. Dockerfile 작성하기
# Dockerfile
From amd64/python:3.9-slim
WORKDIR /usr/app
RUN pip install -U pip &&\
pip install mlflow==1.30.0 pandas scikit-learn "fastapi[all]"
COPY schemas.py schemas.py
COPY app.py app.py
COPY sk_model/ sk_model/
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--reload"]
3-2. Docker Compose 파일 작성하기
version: "3"
services:
api-with-model:
build:
context: .
dockerfile: Dockerfile
container_name: api-with-model
ports:
- 8000:8000
healthcheck:
test:
- curl -X POST http://localhost:8000/predict
- -H
- "Content-Type: application/json"
- -d
- '{"mean_radius": 13.9,"mean_texture": 23.1,"mean_perimeter": 70.34, "mean_area": 600.0,"mean_smoothness": 0.08102,"mean_compactness": 0.0532,"mean_concavity": 0.02993,"mean_concave_points": 0.0207,"mean_symmetry": 0.1622, "mean_fractal_dimension": 0.05711,"radius_error": 0.3311,"texture_error": 0.9106,"perimeter_error": 2.003,"area_error": 32.07,"smoothness_error": 0.003482,"compactness_error": 0.0193,"concavity_error": 0.0234,"concave_points_error": 0.006275,"symmetry_error": 0.01233,"fractal_dimension_error": 0.003133,"worst_radius": 16.32,"worst_texture": 27.93,"worst_perimeter": 105.5,"worst_area": 840.7,"worst_smoothness": 0.1033,"worst_compactness": 0.1711,"worst_concavity": 0.1673,"worst_concave_points": 0.0813,"worst_symmetry": 0.2344,"worst_fractal_dimension": 0.0761}'
interval: 10s
timeout: 5s
retries: 5
networks:
default:
name: mlops-network
external: true
3-3. docker compose 실행 및 확인
docker compose up -d
docker ps -a로 컨테이너 잘 돌아가는 것까지 확인
curl 명령어로 shell 환경에서 결과 확인하기
curl -X POST http://localhost:8000/predict -H "Content-Type: application/json" -d '{"mean_radius": 13.9,"mean_texture": 23.1,"mean_perimeter": 70.34, "mean_area": 600.0,"mean_smoothness": 0.08102,"mean_compactness": 0.0532,"mean_concavity": 0.02993,"mean_concave_points": 0.0207,"mean_symmetry": 0.1622, "mean_fractal_dimension": 0.05711,"radius_error": 0.3311,"texture_error": 0.9106,"perimeter_error": 2.003,"area_error": 32.07,"smoothness_error": 0.003482,"compactness_error": 0.0193,"concavity_error": 0.0234,"concave_points_error": 0.006275,"symmetry_error": 0.01233,"fractal_dimension_error": 0.003133,"worst_radius": 16.32,"worst_texture": 27.93,"worst_perimeter": 105.5,"worst_area": 840.7,"worst_smoothness": 0.1033,"worst_compactness": 0.1711,"worst_concavity": 0.1673,"worst_concave_points": 0.0813,"worst_symmetry": 0.2344,"worst_fractal_dimension": 0.0761}'
'MLOps' 카테고리의 다른 글
BentoML 시작하기 & v0와 v1 비교 (v1.0 migration 이후) (0) | 2023.08.27 |
---|---|
5. FastAPI (0) | 2023.02.11 |
2. Model Development (0) | 2023.01.27 |