본 포스트는 Datacamp의 지원을 받아 작성하였습니다.
https://www.datacamp.com/donates
https://www.datacamp.com/category/artificial-intelligence
import mlflow
# Create new Experiment
# 실험 생성
mlflow.create_experiment("My Experiment")
# Tag new experiment
# 나중에 검색하기 편함
mlflow.set_experiment_tag("scikit-learn","lr")
# Set the experiment
# 현재 환경의 기본 실험으로 설정
mlflow.set_experiment("My Experiment")
사용자가 API를 통해 메트릭과 매개변수를 추적할 수 있도록 하는 MLflow의 구성요소.
데이터나 아티팩트가 MLflow Tracking에 저장될 때 "로깅"이라는 용어를 사용한다.
import mlflow
mlflow.set_experiment("LR Experiment")
mlflow.start_run()
<!----요 사이의 모든 작업들이 "로깅" 됨 ----!>
lr = LogisticRegression(n_jobs=1)
lr.fit(X, y)
score = lr.score(X, y)
mlflow.log_metric("score", score)
mlflow.log_param("n_jobs", 1)
mlflow.log_artifact("train_code.py")
mlflow.end_run()
mlflow ui #localhost 5000포트에서 확인할 수 있음
mlflow는 각 실행(run)에 대한 로깅을 좋은 ui를 통해 제공하지만 이 각각의 실행 정보에 대한 계산 등의 지원을 해주지 않음.
이 실행 정보를 mlflow를 통해 우리가 직접 조사할 수 있게 쿼리를 할 수 있다.
import mlflow
f1_score_filter = "metrics.f1_score > 0.60"
#인수로 전달하기 쉽도록 필터 문자열을 변수로 저장하면 좋음
mlflow.search_runs(
experiment_names = ["Insurance Experiment"],
filter_string = f1_score_filter,
order_by = ["metrics.precision_score DESC"]
)

이런 pandas dataframe 형태로 출력된다. (기본적으로 mlflow의 search_runs의 return 값은 pandas 출력으로 나옴)
import mlflow.sklearn
from sklearn.linear_model import LinearRegression
mlflow.sklearn.autolog()
#scikit-learn Flavor를 사용하여 autolog를 하는 것
lr = LinearRegression()
lr.fit(X, y) #이 시점에서 모델 메트릭이 자동으로 기록됨
autolog를 한번 쓰면 아티팩트도 자동으로 디렉토리 내 기록이 된다.
디렉토리 구조는 모델 폴더 하에 4가지 파일로 되어있음.
MLmodel : 이것도 yaml 파일이긴 함. 모델에 대한 중요한 정보를 정의하는 flavors 정보가 들어있음.

model.pkl : 모델 피클파일
python_env.yaml
requirements.txt
모델 API를 통해 유저가 특정 플레이버를 사용하여 MLflow 모델을 저장, 기록하고 로드할 수 있다.
#모델을 로컬 파일 시스템에 저장
mlflow.sklearn.save_model(model, path)
#모델을 아티팩트로써 로깅
mlflow.sklearn.log_model(model, artifact_path)
#모델을 로컬 파일 시스템 혹은 로깅한 데이터로부터 로드
mlflow.sklearn.load_model(model_uri)
MLflow Tracking을 통해 저장한 모델을 불러오려면 형식을 지켜야함.
runs:/<mlflow_run_id>/run-relative/path/to/model
# last active run 메소드를 사용하면 가장 최근에 실행한 실험의 run id를 가져올 수 있다. 얘를 load_model에 넣으면 저장한 모델을 불러올 수 있음
run = mlflow.last_active_run()
run_id = run.info.run_id
MLflow의 model은 강력한 기능을 제공하지만 모든 모델을 커버하는 데는 한계가 있음
ex) NLP - Tokenizer가 필요. 분류모델엔 Label Encoder가 필요...
다행히 MLflow는 이런 사례들을 위해 pyfunc(python_function) 이라는 이름의 Flavor가 있다.
# Log the pyfunc model
mlflow.pyfunc.log_model(
artifact_path="lr_pyfunc",
# Set model to use CustomPredict Class
python_model=CustomPredict(),
artifacts={"lr_model": "lr_model"}
)
run = mlflow.last_active_run()
run_id = run.info.run_id
# Load the model in python_function format
loaded_model = mlflow.pyfunc.load_model(f"runs:/{run_id}/lr_pyfunc")
MLflow는 모델을 REST api로 전달한다.
# Serve 명령하기
# MLflow는 모델을 로드하고 웹 서버를 시작하며 포트 5000에서 수신을 시작
mlflow models serve -m runs:/{run_id}/artifacts/model
Serve된 모델에 데이터를 보내서 예측을 할 때는 curl 명령을 사용한다.

모델이 예측을 마치면 MLflow는 예측 목록이 포함된 응답을 반환한다.
{"predictions": [1, 0]}
MLflow 모델 레지스트리는
# Import MLflow Client from MLflow module
from mlflow import MlflowClient
# Create an instance of MLflow Client Class name client
client = MlflowClient()
# Create new model
client.create_registered_model("Insurance")
어떤 장점이 있길래 굳이 모델을 레지스트리까지 만들어서 하는건지?
거의 필수적이다.
# Log model
mlflow.sklearn.log_model(lr, "model", registered_model_name="Unicorn")
이런 식으로 MLflow Tracking에 모델을 기록할 때(학습 도중에) 등록하려는 모델의 이름을 전달할 수 있음
"None", "Staging", "Production", "Archived"
모델이 학습과 평가 단계에 있으면 staging 상태가 됨.
from mlflow import MlflowClient
client = MlflowClient()
client.transition_model_version_stage(
name="unicorn",
version=3,
stage="staging"
)
이렇게 코드로 지정하거나 mlflow UI에서 바꿀수있음
모델 레지스트리로부터 모델을 로드하여 배포할 수 있음.(FLAVOR.load_model이나 serve 명령을 통해)
import mlflow.sklearn
#모델 이름과 스테이지를 선언하여 가져올 수 있음
model = mlflow.sklearn.load_model("models:/Unicorn/Staging")
MLflow Projects는 재현 가능한 방식으로 ML코드를 구성하고 실행할 수 있는 방법을 제공함으로써 ML 라이프사이클을 단순화함.
프로젝트는 본질적으로 ML 코드가 포함된 파일의 디렉토리임. -> github에 업로드하기 용이하다.
"""
# Set name of the Project
name: insurance_model
# Set the environment
python_env: python_env.yaml
entry_points:
# Create an entry point
main:
# Create a command
command: 'python3.9 train_model.py'
"""
MLproject 라는 파일이 필수적으로 포함되어있고, 일종의 yaml 파일임.
mlflow.projects.run(
uri='./', #코드가 실행되는 디렉토리와 동일함
entry_point='main',
experiment_name='Salary Model'
)
run 메소드로 프로젝트를 실행할 수 있다.
project 내 세팅한 dependency, python env, main 함수 등을 반영하여 자동으로 실행해준다.
MLproject 내부의 entry_points > main 하에 1개 이상의 패러미터를 세팅해둘 수 있음.
패러미터의 데이터 타입을 지정해줄 수 있고 파이썬 데이터 포맷 중 하나를 따름.
"""
# Set name of the Project
name: insurance_model
# Set the environment
python_env: python_env.yaml
entry_points:
# Create an entry point
main:
parameters:
n_jobs_param:
type: int
default: 1
fit_intercept_param:
type: bool
default: True
# Create a command
command: "python3.9 train_model.py {n_jobs_param} {fit_intercept_param}"
"""
이렇게 세팅하면 된다.
run method도 아래와 같이 parameter를 인수로 전달하면 된다
mlflow.projects.run(
uri='./', #코드가 실행되는 디렉토리와 동일함
entry_point='main',
experiment_name='Salary Model',
parameters={
'n_jobs_param': 2,
'fit_intercept_param': False
)
하나의 워크플로로 묶어서 run 메소드를 여러개 실행할 수 있음. 예를들어, 학습을 위한 run 메소드가 끝나면 결과 모델을 다음 run에 패러미터로 줄 수가 있음.
# Set run method to model_engineering
model_engineering = mlflow.projects.run(
uri='./',
# Set entry point to model_engineering
entry_point='model_engineering',
experiment_name='Insurance',
# Set the parameters for n_jobs and fit_intercept
parameters={
'n_jobs': 2,
'fit_intercept': False
},
env_manager='local'
)
# Set Run ID of model training to be passed to Model Evaluation step
model_engineering_run_id = model_engineering.run_id
print(model_engineering_run_id)
Insurance라는 모델에 패러미터를 설정해서 실행을 시키고 run_id를 조회함
# Set the MLflow Projects run method
model_evaluation = mlflow.projects.run(
uri="./",
# Set the entry point to model_evaluation
entry_point="model_evaluation",
# Set the parameter run_id to the run_id output of previous step
parameters={
"run_id": model_engineering_run_id,
},
env_manager="local"
)
print(model_evaluation.get_status())
run_id로 모델을 조회해서 불러온 뒤 그 모델로 평가를 진행함. 마무리로 상태확인까지.