학습된 모델을 Model.dill로 저장
모델저장소
학습이 완료된 모델을 저장
실험관리 + 파일
MLflow에서 기본적으로 지원해주지 않기 때문에 추가적으로 opensource를 사용
MLflow 아키텍처
1. Backend Store (Remote host)
수치 데이터와 MLflow서버의 정보들을 체계적으로 관리하기 위한 DB
저장항목
1. 메타데이터
2. 모델에 관한 정보
3. 학습 중 생기는 정보
2. Artifact Store (S3 remote host)
학습된 모델을 저장하는 Model Registry로써 이용하기 위한 스토리지서버
Artifact Store를 이용하면 기본적인 파일 시스템 보다 체계적으로 관리 할 수 있으며 외부에 있는 스토리지 서버도 사용
할 수 있다는 장점
모델저장소 구축
1. backend store 구축
2. Artifact store 구축
3. mlflow 실행
Docker-compose.yaml
depends_on:
mlflow-server서비스가 실행되기 전에 실행되어야 하는 서비스 목록과 조건
healthcheck:
서비스가 정상적으로 실행중인지 확인하기 위한 명령어
test:사용할명령어
interval:확인하는 주기
timeout:응답하지 않을 경우 대기할 시간, 해당시간이 지나면 서비스가 동작하지 않는다고 판단
retries: 재시도 횟수
mlflow-backend-store
postgresql을 사용
environment:
AWS_ACCESS_KEY_ID: minio
AWS_SECRET_ACCESS_KEY: miniostorage
MLFLOW_S3_ENDPOINT_URL: http://mlflow-artifact-store:9000
command:
- /bin/sh
- -c
- |
mc config host add mlflowminio http://mlflow-artifact-store:9000 minio miniostorage &&
mc mb --ignore-existing mlflowminio/mlflow
mlflow server \
--backend-store-uri postgresql://mlflowuser:mlflowpassword@mlflow-backend-store/mlflowdatabase \
--default-artifact-root s3://mlflow \
--host 0.0.0.0
통신할 수 있는 정보들 AWS
S3앤드포인트 artifact에 접근가능 저장소
커맨드명령어
1. minio에 mlflow에서 사용할 bucket생성 config
2. mlflow bucket 생성
3. mlflow server 실행
-backend store 접속 정보
-artifact store 접속 정보
mlflow-server:
build:
context: .
dockerfile: Dockerfile
depends_on:
mlflow-artifact-store:
condition: service_healthy
mlflow-backend-store:
condition: service_healthy
depends_on을 통해 artifact, backend모두 healthy한 후에 mlflow 서버를 사용
docker compose up --build를 통해 구축완료
minio가 실행중이라면 중단해야함
이제 모델을 저장을 하려고 함
실제로 사용할 베스트모델만 저장
clf.fit(X, y)
#
# save model
#
mlflow.sklearn.log_model(sk_model=clf, artifact_path="my_model")
return clf
sk_model = 학습된 모델
minio에 모델을 저장하기 때문에 앤드포인트 주소를 주어야 함
os.environ["MLFLOW_S3_ENDPOINT_URL"] = "http://0.0.0.0:9000"
os.environ["MLFLOW_TRACKING_URI"] = "http://0.0.0.0:5001"
os.environ["AWS_ACCESS_KEY_ID"] = "minio"
os.environ["AWS_SECRET_ACCESS_KEY"] = "miniostorage"
글로벌 변수로 주소를 줌
모델이 로드되기 위한 정보들이 저장이 됨
모델 불러오기
load_skearn_model을 통해 clf로 리턴
pytunc_model도 리턴
def load_sklearn_model(run_id, model_name):
clf = mlflow.sklearn.load_model(f"runs:/{run_id}/{model_name}")
return clf
def load_pyfunc_model(run_id, model_name):
clf = mlflow.pyfunc.load_model(f"runs:/{run_id}/{model_name}")
return clf
if __name__ == "__main__":
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument("--run-id", type=str)
parser.add_argument("--model-name", type=str, default="my_model")
args = parser.parse_args()
#
# load data
#
data_dict = load_data()
X = data_dict["data"]
#
# load model
#
sklearn_clf = load_sklearn_model(args.run_id, args.model_name)
sklearn_pred = sklearn_clf.predict(X)
print("sklearn")
print(sklearn_clf)
print(sklearn_pred)
pyfunc_clf = load_pyfunc_model(args.run_id, args.model_name)
pyfunc_pred = pyfunc_clf.predict(X)
print("pyfunc")
print(pyfunc_clf)
print(pyfunc_pred)
python section1_load_model.py --run-id 9c067f37a61246ee9bd7b4ff36c7f2df
run_id를 파싱 하게 할 수 있기 위해 다음과 같이 모델id를 줌
sklearn
RandomForestClassifier(max_depth=8, n_estimators=600, random_state=2024)
[1 2 1 0 1 1 0 1 2 2 2 2 0 0 2 2 2 2 2 1 1 2 2 0 0 1 2 1 0 2 0 1 0 2 1 1 2
2 0 1 1 1 2 1 1 2 2 2 0 1 0 0 2 0 0 1 0 2 1 1 1 2 2 1 1 1 0 2 0 2 1 1 2 0
1 2 0 1 2 1 0 2 1 0 1 2 1 2 1 0 0 2 2 0 0 2 0 1 0 1]
pyfunc
mlflow.pyfunc.loaded_model:
artifact_path: my_model
flavor: mlflow.sklearn
run_id: 9c067f37a61246ee9bd7b4ff36c7f2df
[1 2 1 0 1 1 0 1 2 2 2 2 0 0 2 2 2 2 2 1 1 2 2 0 0 1 2 1 0 2 0 1 0 2 1 1 2
2 0 1 1 1 2 1 1 2 2 2 0 1 0 0 2 0 0 1 0 2 1 1 1 2 2 1 1 1 0 2 0 2 1 1 2 0
1 2 0 1 2 1 0 2 1 0 1 2 1 2 1 0 0 2 2 0 0 2 0 1 0 1]
커스텀 모델 작성
싸이킷런 등 대중적인 모델은 네이티브하게 저장이 가능하지만 그외에 모델은 어려움
다음과 같이 Preprocess, Postprocess까지 가지고 와야 함
pyfunc로 가능
mlflow.pyfunc.log_model(
artifact_path="my_model",
data_path="model.dill",
loader_module="loader",
code_path=["loader.py"],
)
어떤이름, 저장경로, code_path 모델 파이썬 파일, 어떻게하면 파이썬 파일을 가져올 수 있는지
clf.fit(X, y)
#
# my custom model
#
my_model = MyModel(clf)
with open("model.dill", "wb") as f:
dill.dump(my_model, f)
with open("loader.py", "w") as f:
f.write(
textwrap.dedent(
"""
이어서.
f.write(
textwrap.dedent(
"""
import os
import dill
def _load_pyfunc(path):
if os.path.isdir(path):
path = os.path.join(path, "model.dill")
with open(path, "rb") as f:
return dill.load(f)
"""
다음과 같이 코드를 읽은 후 모델을 찾고 로드할 수 있다.
'Tech Stack > MLflow' 카테고리의 다른 글
MLOps - FastAPI 서빙 (0) | 2024.03.04 |
---|---|
MLOps - 배치서빙 (0) | 2024.02.29 |
MLOps - 데이터 (0) | 2024.02.27 |
MLOps - 교차검증 (0) | 2024.02.23 |
MLOps - HPO 반영 (0) | 2024.02.22 |