load_digits
dataset을 활용하여 다중 분류 모델을 먼저 간단하게 만들어본다.from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, accuracy_score
from sklearn.ensemble import RandomForestClassifier
## 1. 데이터 로드
digit = load_digits()
X = digit.data
y = digit.target
## 2. 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 20)
## 3. 모델 객체 생성
rf = RandomForestClassifier(
n_estimators = 10,
max_depth=4,
criterion = 'entropy',
random_state = 0
)
## 4. 학습 및 score 확인
rf.fit(X_train, y_train)
print(rf.score(X_train, y_train))
print(rf.score(X_test, y_test))
## 5. classification report 생성
y_pred = rf.predict(X_test)
report = classification_report(y_test, y_pred, output_dict=True)
pd.DataFrame(report)
---
0.9807692307692307
0.8867924528301887
1 2 3 accuracy macro avg weighted avg
precision 0.714286 1.000000 0.882353 0.886792 0.865546 0.895354
recall 0.833333 0.956522 0.833333 0.886792 0.874396 0.886792
f1-score 0.769231 0.977778 0.857143 0.886792 0.868050 0.889589
support 12.000000 23.000000 18.000000 0.886792 53.000000 53.000000
pip install mlflow
train_test_split
적용된 데이터에 대하여 RandomForestClassifier
를 적용하여 score 및 report를 생성한 후 관련 내용들을 MLflow에 기록할 수 있도록 하는 기본 코드를 작성해보았다.모델 저장
파트에서 log_model()
의 인자 중 artifact_path = "model"
로 통일한다.(이외 설정시 이후 모델 load시 코드가 까다로워질 수 있음)import mlflow
# 실험에 대한 제목 (대제목)
experiment_name = "digit_classification"
# 실험 모델 관련 하이퍼파라미터 정보(dict)
params = {
"n_estimators" : 50,
"max_depth" : 5,
"criterion" : 'gini',
"random_state" : 20
}
# 실험명 설정하여 MLflow 실험 시작
mlflow.set_experiment(experiment_name)
with mlflow.start_run(
run_name="RandomForest_model", # 실험에 대한 세부 제목(중제목)
tags={"type" : "classification", "dataset" : "digit"}, # 실험 관련 태그 설정
description="digit data classification" # 실험 관련 설명
):
# 모델 초기화 및 학습
model = RandomForestClassifier(**params)
model.fit(X_train, y_train)
# 예측 및 평가
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
report = classification_report(y_test, y_pred, output_dict=True)
# 기록의 편의성을 위해 report 내용 중 필요한 값들만 dict 형식으로 재생성
report_dict = {
"accuracy" : report['accuracy'],
**{f"macro_{i}":j for i,j in report['macro avg'].items()},
**{f"weighted_{i}":j for i,j in report['weighted avg'].items()},
}
# MLflow에 파라미터와 메트릭 기록
mlflow.log_metrics(report_dict)
mlflow.log_params(params)
# 모델 저장
mlflow.sklearn.log_model(
sk_model = model,
artifact_path = "model"
)
mlruns
라는 폴더가 자동으로 생성된다.2024/11/04 14:34:10 INFO mlflow.tracking.fluent: Experiment with name 'digit_classification' does not exist. Creating a new experiment.
2024/11/04 14:34:18 WARNING mlflow.models.model: Model logged without a signature and input example. Please set `input_example` parameter when logging the model to auto infer the model signature.
개발하는 위치에서 터미널을 연 후 mlflow ui
명령어를 치면 localhost:5000
주소로 mlflow UI를 확인할 수 있다.
mlflow ui
localhost:5000
에 접속해보면 우측 Experiment 섹션에 우리가 지정한 experiment_name
이 들어가 있는 것이 보이고, Run Name에는 우리가 mlflow.start_run
시 지정한 run_name
이 들어간 것을 확인할 수 있다.
RandomForest_model
을 클릭하여 들어가보면 해당 모델에 대한 파라미터, 태그, 설명 등 세부적인 정보들을 추가적으로 확인해볼 수 있다.
RandomForestClassifier
모델을 사용하였는데, 이 경우에는 mlflow.sklearn
패키지 아래에 있는 함수를 사용하여 모델에 대한 저장 및 로깅 작업을 수행하였다.mlflow.xgboost
패키지를 활용하여야 하는데, 아래는 XGBClassifier
를 활용한 모델 실험 코드이다.import mlflow
from xgboost import XGBClassifier
# 실험에 대한 제목 (대제목)
experiment_name = "digit_classification"
# xgboost 실험 모델 관련 하이퍼파라미터 정보(dict)
xgb_params = {
"n_estimators" : 10,
"max_depth" : 3,
"learning_rate" : 0.4,
"random_state" : 20
}
# 실험명 설정하여 MLflow 실험 시작
mlflow.set_experiment(experiment_name)
with mlflow.start_run(
run_name="XGBoost_model", # 실험에 대한 세부 제목(중제목)
tags={"type" : "classification", "dataset" : "digit", "model" : "XGBClassifier"}, # 실험 관련 태그 설정
description="digit data classification" # 실험 관련 설명
):
# 모델 초기화 및 학습
model = XGBClassifier(**xgb_params)
model.fit(X_train, y_train)
# 예측 및 평가
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
report = classification_report(y_test, y_pred, output_dict=True)
# 기록의 편의성을 위해 report 내용 중 필요한 값들만 dict 형식으로 재생성
report_dict = {
"accuracy" : report['accuracy'],
**{f"macro_{i}":j for i,j in report['macro avg'].items()},
**{f"weighted_{i}":j for i,j in report['weighted avg'].items()},
}
# MLflow에 파라미터와 메트릭 기록
mlflow.log_metrics(report_dict)
mlflow.log_params(xgb_params)
# 모델 저장
mlflow.xgboost.log_model(
xgb_model = model,
artifact_path = "model"
)
experiment_name
은 위에서 지정해준 변수의 값과 동일하다.experiment_info = mlflow.set_experiment(experiment_name)
## 특정 실험에 대한 정보를 dataframe 형태로 반환
runs_df = mlflow.search_runs(
experiment_ids=experiment_info.experiment_id
)
## 조건에 맞는 run_id를 찾아 변수에 저장
run_id = runs_df[runs_df['tags.mlflow.runName'] == 'RandomForest_model'].sort_values("start_time")['run_id'].values[0]
model_uri = f'runs:/{run_id}/model'
model_name = "RandomForest_normal"
## sklearn의 RandomForest 모델을 registry에 저장
with mlflow.start_run(run_id=run_id):
mlflow.register_model(
model_uri=model_uri,
name=model_name,
tags={"model_type": "sklearn", "type" : "classification"} # 모델에 대한 태그 설정
)
## 조건에 맞는 run_id를 찾아 변수에 저장
run_id = runs_df[runs_df['tags.mlflow.runName'] == 'XGBoost_model'].sort_values("start_time")['run_id'].values[0]
model_uri = f'runs:/{run_id}/model'
model_name = "XGBClassifier_normal"
## xgboost의 XGBoostClassifier 모델을 registry에 저장
with mlflow.start_run(run_id=run_id):
mlflow.register_model(
model_uri=model_uri,
name=model_name,
tags={"model_type": "xgboost", "type" : "classification"} # 모델에 대한 태그 설정
)
models
탭에 들어가면 저장된 모델을 확인활 수 있다.model_name = "RandomForest_normal"
saved_models = mlflow.search_registered_models(
filter_string=f"name = '{model_name}'",
)
dict(saved_models[0])
---
{'aliases': {},
'creation_timestamp': 1730733570407,
'description': None,
'last_updated_timestamp': 1730733570466,
'latest_versions': [<ModelVersion: aliases=[], creation_timestamp=1730733570417, current_stage='None', description=None, last_updated_timestamp=1730733570417, name='RandomForest_normal', run_id='b372d9cd245444bda727c0847f3927f5', run_link=None, source='file:///d:/%EC%BD%94%EB%93%9C%EC%9E%87/dev/ML_Lecture/11.MLflow/mlruns/595006786249354016/b372d9cd245444bda727c0847f3927f5/artifacts/model', status='READY', status_message=None, tags={'model_type': 'sklearn', 'type': 'classification'}, user_id=None, version=1>],
'name': 'RandomForest_normal',
'tags': {}}
sklearn
라이브러리의 모델이냐, xgboost
라이브러리의 모델이냐에 따라서 코드가 약간 다르다.model_uri = f"models:/{model_name}/latest
## 1) sklearn 모델
loaded_model = mlflow.sklearn.load_model(model_uri)
## 2) xgboost 모델
loaded_model = mlflow.xgboost.load_model(model_uri)
y_pred = loaded_model.predict(X_test)
classification_report(y_test, y_pred, output_dict=True)