반응형

mlfow Document: https://mlflow.org/docs/latest/index.html

mlfow git repo: https://github.com/mlflow/mlflow.git

 

MLOps는 왜 해야할까?

 

"연구실 밖으로 나온 모델"

참고: https://www.youtube.com/watch?v=DRIEKB9smBY&t=4624s

Step1. 다른 사람들이 모델을 사용할 수 있게 하고 싶어 ⇒ API를 이용하자!

Step2. 이용자가 많아져서 로드 밸런스, 노드 스케일링이 필요하네? ⇒ Software Engineer 에게 Help하자!

Step3. ML 프로젝트에서 Data Scientist 와 Software Engineer의 목표가 다를 수 있다!

  • Data Scientist: 다양한 실험을 통해 더 좋은 성능을 가진 모델을 개발 및 데이터 분석하는 것이 목표
  • Software Engineer: 안정적이고 확장 가능한 시스템을 구축하고 유지 관리, 성능 최적화하는 것이 목표

⇒ MLOps 를 사용하자! 데이터 사이언티스트와 소프트웨어 엔지니어에게 협업 환경을 제공하여 실험 추적, 모델 관리 등 머신러닝의 수명 주기 및 운영을 간단하게 수행할 수 있게 해준다.

 

MLflow란?

참고: https://www.databricks.com/kr/product/managed-mlflow

source: https://www.databricks.com/blog/2020/04/15/databricks-extends-mlflow-model-registry-with-enterprise-features.html

  1. MLflow Tracking: 실험에서 사용된 데이터를 기록하고 조회할 수 있다. (UI 제공)
    • 저장 가능한 데이터: parameters, code version, metrics, model environments dependencies, model artifacts(ex, image, parquet files)
    • Tags: 실험에 임의의 tag를 달아 필터를 걸어 찾아볼 수 있다.
  2. MLflow Models: 다양한 ML 라이브러리로 훈련된 모델을 패키징하기 위한 표준 형식
    • Flavor: 모델 아티팩트를 저장하고 로드하기 위한 표준 형식⇒ 라이브러리에 관계없이 동일한 인터페이스를 통해서 모델 로드할 수 있다.
    • ex) “python_function” Flaver는 python 함수로 모델을 저장하고 로드할 때 사용됨
    • tensorflow와 pytorch 모델 coversion test를 했던 이전 블로그 글 (어려웠던 경험)
  3. MLflow Model Registry: 중앙 모델 저장소
    • 참고: versioning, stage transitions, annotations와 같은 metadata도 포함하여 저장
  4. MLflow Projects: 코드를 실행하는데 사용되는 Environment를 지정할 수 있다. (conda, docker 컨테이너 등)
  5. MLflow Recipes

 

MLflow 어떻게 사용할까?

MLFlow로 모델 Lifecycle 관리

아래 작성한 예시 Code (API vs MLflow) : https://github.com/jaxgxxnxee/Mlflow-test/tree/master

Docker Compose 튜토리얼

 

Docker Compose 튜토리얼

도커란 : 컨테이너를 쉽고 빠르게 배포/확장하고 관리를 자동화해주는 오픈소스 플랫폼 컨테이너: 컨테이너는 격리된 공간에서 프로세스가 동작하는 기술. VM과 유사하지만 격리 속성을 완화하

everyday-deeplearning.tistory.com

 

0. Install MLflow

$ pip instatll mlflow
$ mlflow server \
    --host 0.0.0.0 \
    --port 5000

 

1. 프로젝트 생성하기 (iris_model Folder)

프로젝트 환경 정의

: conda, pyenv, docker 가능

 

MLproject : 프로젝트 정의서

name: sklearn_iris_example

conda_env: conda.yaml

entry_points:
  main:
    parameters:
      random_state: {type: int, default: 0}  # 여기서 param을 조절하면서 테스트함
    command: "python iris_model.py {random_state}"

 

conda.yaml: conda환경을 사용하기 위해 miniconda 먼저 설치 해야함

name: sklearn_iris_example

channels:
  - defaults

dependencies:
  - python=3.7
  - numpy
  - pandas
  - scikit-learn
  - pip
  - pip:
    - mlflow

ref: https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#create-env-file-manually

 

모델 parmeter, metric 등 기록 대상 정의

iris_model.py

import mlflow
from mlflow.models.signature import infer_signature

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, recall_score, precision_score, f1_score
import json
import sys

## Load Dataset
random_state = int(sys.argv[1]) if len(sys.argv) > 1 else 0
iris_data = datasets.load_iris()
target_index = {i: target for i, target in enumerate(iris_data['target_names'])}
X, y = iris_data.data, iris_data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=random_state)

## Train Dataset
clf = LogisticRegression(max_iter=10000)  # api생성시는 문제가 없었지만, 여기서는 max_iter를 늘리지 않으면 에러가 남
clf.fit(X_train, y_train)
y_predict = clf.predict(X_test)

## Logging
mlflow.log_param("random_state", random_state)

mlflow.log_metric("ac_sc", accuracy_score(y_test, y_predict))
mlflow.log_metric("rc_sc", recall_score(y_test, y_predict, average="weighted"))
mlflow.log_metric("pr_sc", precision_score(y_test, y_predict, average="weighted"))
mlflow.log_metric("f1_sc", f1_score(y_test, y_predict, average='micro'))

signature = infer_signature(X_test, y_predict)  # 꼭 해야하는 것은 아닌듯?
mlflow.sklearn.log_model(clf, "iris_classification", signature=signature)

with open('../s3/target_index.json', 'w') as f:  # 실제 s3는 api_key, password 환경설정 해야함, 여기서는 local에서 접근할 수 있는 공유폴더에 저장함
    json.dump(target_index, f)

 

2. 모델 실행하기

$ mlflow run iris_model

** issue: sklearn package관련 data memory 에러가 있었다 → 한 번 더 실행하니 되더라 (깔끔한 방법 다시 찾아봐야할듯)

model folder tree

  • 참고: github에 올려둔 소스 바로 실행 가능하다고 함
    • $ mlflow run git@github.com:/{iris_model_path}.git

 

3. 훈련된 모델 Tracking하기

$ mlflow ui

UI

 

4. 모델 배포하기

$ mlflow models serve -m src/iris_model/mlruns/0/14b6f49e06ec4f029b87dbeeb7c36daf/artifacts/iris_classification -p 5001 -h 0.0.0.0  # host의 default는 127.0.0.1 이지만 다른 곳에서 접근하기 위해 0.0.0.0으로 변경함
  • default flavor: python_function

 

5. 모델 호출

  • **참고: pandas split을 꼭 사용해야 함
$ curl -X POST -H "Content-Type:application/json; format=pandas-split" --data '[{"columns": ["sepal length (cm)", "sepal width (cm)", "petal length (cm)", "petal width (cm)"], "data": [[5.1, 3.5, 1.4, 0.2]]}]' http://0.0.0.0:5002/invocations

result

 

 

Todo

 

활용 사례

MLflow를 이용한 머신러닝 프로젝트 관리. 박선준-PyCon Korea2021

반응형
반응형

도커란

: 컨테이너를 쉽고 빠르게 배포/확장하고 관리를 자동화해주는 오픈소스 플랫폼

 

컨테이너: 컨테이너는 격리된 공간에서 프로세스가 동작하는 기술. VM과 유사하지만 격리 속성을 완화하여 애플리케이션 간에 운영체제(OS)를 공유한다.

source: https://kubernetes.io/ko/docs/concepts/overview/

 

이미지컨테이너 실행에 필요한 파일과 설정 값 등을 포함하고 있는 것으로 상태 값을 가지지 않고 변하지 않습니다(Immutable). 컨테이너는 이미지를 실행한 상태라고 볼 수 있고 추가되거나 변하는 값은 컨테이너에 저장됩니다. 같은 이미지에서 여러 개의 컨테이너를 생성할 수 있고 컨테이너의 상태가 바뀌거나 컨테이너가 삭제되더라도 이미지는 변하지 않고 그대로 남아있습니다. 도커 이미지는 컨테이너를 실행하기 위한 모든 정보를 가지고 있기 때문에 보통 용량이 수백메가MB에 이릅니다.

hub: https://hub.docker.com/

  • 레이어 저장 방식: 컨테이너를 생성할 때도 레이어 방식을 사용하는데 기존의 이미지 레이어 위에 읽기/쓰기read-write 레이어를 추가합니다. 이미지 레이어를 그대로 사용하면서 컨테이너가 실행중에 생성하는 파일이나 변경된 내용은 읽기/쓰기 레이어에 저장되므로 여러개의 컨테이너를 생성해도 최소한의 용량만 사용합니다.

 

참고: 초보를 위한 도커 안내서

 

 

Docker 사용하기

1. docker container생성

DockerFile: 컨테이너 정의서

from  # image import

run  # linux bash command (build시 init!)

env  # linux 환경변수

expose  # port forwarding

entrypoint  # /bin/sh (bash file)

cmd  # bash arguments → pending 되는 command line을 적어야함(server로 사용하려면), 아니면 exit으로 바로 컨테이너 꺼짐

cp  # ex) {local_path} {container_path}

 

** 참고1: docker compose up -d —build 시 file이 변경된 부분부터 다시 실행됨 (file이 변경되도 다시 실행됨)

** 참고2: cmd에서 실행하고자하는 파일이 bash file일 경우는 실행 권한 필요: chmod +x {file_name}.sh

 

2. Container 여러개 생성 & 다른 Container 연결

docker-compose.yaml: 컨테이너s를 오케스트레이션

version: '1'

services:
  test-container:  # services 이름
    container_name: test-container
    hostname: test-container
    build:
      context: .
      dockerfile: DockerFile
    volumes:
      - ./src:/src  # code 싱크 맞추기(=copy) ex) {local_path}:{container_path}

  postgress:
    container_name: postgres
    hostname: postgres
    image: postgres:13  # docker image file 이미 있는 경우 (from hub.docker.com)
    environment:
      POSTGRES_PASSWORD: password
    ports:
      - 8080:8080  # conainer간의 port 연결 {local_port}:{container_port}

* 참고: yaml file 에서는 tab을 쓸 수 없음, “ 쌍따움표 쓸 수 없음

 

3. Docker 명령어

$ docker run

$ docker image ls -a

$ docker compose up -d --build  # -d: log background, --build: 새로 만들어 놓은 이미지로 변경 (해당 folder에서 실행하기)

$ docker compose down

$ docker logs {container_name}

$ docker container ps -a  # 전체 docker 작업 확인

$ docker compose ps -a  # docker-compoase.yaml 안에 있는 작업 확인

$ docker rm -f {container_name}

$ docker exec {service_name} {command}

$ docker exec {service_name} bash # ssh 연결 환경

$ docker volume prune

$ docker logs -tf {service_name}

 

작성한 예시 Docker Code : https://github.com/jaxgxxnxee/docker-test

반응형
반응형

Tensorflow serving 하기

TensorFlow Serving을 사용하면 동일한 서버 아키텍처와 API를 유지하면서 새로운 알고리즘과 실험을 쉽게 배포 할 수 있습니다. TensorFlow Serving은 TensorFlow 모델과의 즉각적인 통합을 제공하지만 다른 유형의 모델 및 데이터를 제공하도록 쉽게 확장 할 수 있습니다.(출처: tensorflow.org)

 

참조

Train and serve a TensorFlow model with TensorFlow Serving | TFX

TensorFlow Serving with Docker | TFX

모델 저장

# >> 추후 모델 업데이트를 위해 version별로 모델 저장함
## tensorflow version 2.3.1
model_path='models'
model_name='my_model'
model.save(f'{model_path}/{model_name}/1')

저장된 모델 확인

## model format check
for root, dirs, files in os.walk(os.path.join(model_path, model_name)):
    indent = '    ' * root.count(os.sep)
    print('{}{}/'.format(indent, os.path.basename(root)))
    for filename in files:
        print('{}{}'.format(indent + '    ', filename))

## output format ex)
# 1/
#             .DS_Store
#             saved_model.pb
#             variables/
#                 variables.data-00000-of-00001
#                 variables.index
#             assets/
## ex
$ export model_path='models'
$ export model_name='my_model'

## model input, output shape check
$ saved_model_cli show --dir ${model_path}/${model_name}/1 --tag_set serve \
                       --signature_def serving_default

Serving with Docker

TensorFlow Serving을 시작하는 가장 쉬운 방법 중 하나는 Docker를 사용하는 것 입니다. (출처: tensorflow.org)

Docker 설치하기

(on MacOS)

큐베플로우 설치 on MacOS

(others)

https://www.tensorflow.org/tfx/serving/docker#install_docker

## !!도커 설치가 선행되어야함!! ##

## tensorflow에서 제공하는 이미지 가장 최신버전으로 다운로드(현재 기준 2.3.0)
$ docker pull tensorflow/serving
# image 생성 체크
$ docker image ls
# image 삭제
$ docker image rm <IMAGE ID>
# ex
$ export container_name='serving_base'

## tensorflow/serving container 띄우기
$ docker run -d --name ${container_name} -it --rm \
        -p 8500:8500 \
        -p 8501:8501 \
        -v "$(pwd)/${model_path}/${model_name}:/${model_path}/${model_name}" \
        -e MODEL_NAME=${model_name} \
                tensorflow/serving &

# container 생성 체크
$ docker container ls

# container 삭제
# issue: Bind for x.x.x.x:port# failed: port is already allocated.
$ docker rm -f <NAMES>

docker container ls

모델 실행 (REST API)

rest api port: 8501

import json
import numpy
import requests
data = json.dumps({"signature_name": "serving_default",
                   "instances": x.numpy().tolist()})  # json dumps를 위해 list로 변경 (shape 확인 필수)
headers = {"content-type": "application/json"}
json_response = requests.post(f'http://localhost:8501/v1/{model_path}/{model_name}:predict',
                              data=data, headers=headers)
predictions = numpy.array(json.loads(json_response.text)["predictions"])
print(predictions)
반응형

+ Recent posts