본문으로 건너뛰기

088 MLflow로 실험 추적하기

키워드: MLflow, 실험 추적, experiment tracking

개요

MLflow는 머신러닝 실험을 추적하고 관리하는 오픈소스 플랫폼입니다. FLAML AutoML 실험을 MLflow로 추적하면 모델 비교, 재현성 확보, 협업이 용이해집니다.

실습 환경

  • Python 버전: 3.11 권장
  • 필요 패키지: flaml[automl], mlflow
pip install flaml[automl] mlflow pandas numpy

MLflow 기초

import mlflow
import numpy as np
import pandas as pd

# 088 MLflow 개념
concepts = {
'개념': ['Experiment', 'Run', 'Parameter', 'Metric', 'Artifact'],
'설명': [
'관련 실험들의 컨테이너',
'개별 실험 실행',
'모델 설정값',
'성능 지표',
'모델 파일, 그래프 등'
],
'예시': [
'churn_prediction',
'lgbm_trial_01',
'n_estimators=100',
'accuracy=0.85',
'model.pkl, feature_importance.png'
]
}

print("MLflow 핵심 개념:")
print(pd.DataFrame(concepts).to_string(index=False))

MLflow 설정

# 088 로컬 MLflow 설정
mlflow.set_tracking_uri("sqlite:///mlflow.db") # 로컬 DB
mlflow.set_experiment("flaml_automl_experiment")

print(f"추적 URI: {mlflow.get_tracking_uri()}")
print(f"실험: flaml_automl_experiment")

데이터 준비

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

# 088 데이터 생성
np.random.seed(42)
X, y = make_classification(n_samples=2000, n_features=20,
n_informative=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)

print(f"학습 데이터: {X_train.shape}")
print(f"테스트 데이터: {X_test.shape}")

FLAML + MLflow 기본 연동

from flaml import AutoML
from sklearn.metrics import accuracy_score, roc_auc_score, f1_score

# 088 MLflow run으로 FLAML 실험 추적
with mlflow.start_run(run_name="flaml_basic"):

# 파라미터 로깅
params = {
"time_budget": 60,
"metric": "accuracy",
"estimator_list": "lgbm,xgboost,rf",
"seed": 42
}
mlflow.log_params(params)

# FLAML 학습
automl = AutoML()
automl.fit(
X_train, y_train,
task="classification",
metric="accuracy",
time_budget=60,
estimator_list=['lgbm', 'xgboost', 'rf'],
seed=42,
verbose=1
)

# 예측 및 평가
y_pred = automl.predict(X_test)
y_proba = automl.predict_proba(X_test)[:, 1]

# 메트릭 로깅
metrics = {
"test_accuracy": accuracy_score(y_test, y_pred),
"test_roc_auc": roc_auc_score(y_test, y_proba),
"test_f1": f1_score(y_test, y_pred),
"best_loss": automl.best_loss,
"n_trials": len(automl.config_history)
}
mlflow.log_metrics(metrics)

# 결과 로깅
mlflow.log_param("best_estimator", automl.best_estimator)
mlflow.log_param("best_config", str(automl.best_config))

# 모델 저장
mlflow.sklearn.log_model(automl, "model")

print(f"\n=== MLflow 로깅 완료 ===")
print(f"Run ID: {mlflow.active_run().info.run_id}")
for name, value in metrics.items():
print(f" {name}: {value:.4f}")

자동 로깅 활성화

# 088 MLflow 자동 로깅 (scikit-learn 호환 모델)
mlflow.autolog()

with mlflow.start_run(run_name="flaml_autolog"):
automl_auto = AutoML()
automl_auto.fit(
X_train, y_train,
task="classification",
time_budget=30,
verbose=0
)

print("자동 로깅으로 실험 추적됨")

# 088 자동 로깅 비활성화 (필요시)
mlflow.autolog(disable=True)

여러 실험 비교

# 088 다양한 설정으로 실험
experiments = [
{"time_budget": 30, "estimator_list": ['lgbm'], "name": "lgbm_only"},
{"time_budget": 30, "estimator_list": ['xgboost'], "name": "xgb_only"},
{"time_budget": 30, "estimator_list": ['rf'], "name": "rf_only"},
{"time_budget": 60, "estimator_list": ['lgbm', 'xgboost', 'rf'], "name": "ensemble"},
]

for exp_config in experiments:
with mlflow.start_run(run_name=exp_config["name"]):
# 파라미터 로깅
mlflow.log_params({
"time_budget": exp_config["time_budget"],
"estimator_list": str(exp_config["estimator_list"])
})

# 학습
automl_exp = AutoML()
automl_exp.fit(
X_train, y_train,
task="classification",
time_budget=exp_config["time_budget"],
estimator_list=exp_config["estimator_list"],
verbose=0
)

# 평가
y_pred = automl_exp.predict(X_test)
y_proba = automl_exp.predict_proba(X_test)[:, 1]

mlflow.log_metrics({
"accuracy": accuracy_score(y_test, y_pred),
"roc_auc": roc_auc_score(y_test, y_proba)
})
mlflow.log_param("best_estimator", automl_exp.best_estimator)

print(f"{exp_config['name']}: {automl_exp.best_estimator}, "
f"AUC={roc_auc_score(y_test, y_proba):.4f}")

아티팩트 저장

import matplotlib.pyplot as plt
import json

with mlflow.start_run(run_name="with_artifacts"):
# FLAML 학습
automl_art = AutoML()
automl_art.fit(X_train, y_train, task="classification",
time_budget=30, verbose=0)

y_pred = automl_art.predict(X_test)
y_proba = automl_art.predict_proba(X_test)[:, 1]

# 메트릭 로깅
mlflow.log_metrics({
"accuracy": accuracy_score(y_test, y_pred),
"roc_auc": roc_auc_score(y_test, y_proba)
})

# 1. 특성 중요도 그래프
if hasattr(automl_art.model.estimator, 'feature_importances_'):
importance = automl_art.model.estimator.feature_importances_
plt.figure(figsize=(10, 6))
plt.barh(range(len(importance)), importance)
plt.xlabel('Importance')
plt.title('Feature Importance')
plt.savefig('feature_importance.png', dpi=100, bbox_inches='tight')
mlflow.log_artifact('feature_importance.png')
plt.close()

# 2. 학습 이력 저장
history = {str(k): str(v) for k, v in automl_art.config_history.items()}
with open('training_history.json', 'w') as f:
json.dump(history, f, indent=2)
mlflow.log_artifact('training_history.json')

# 3. 최적 설정 저장
best_config = {
'best_estimator': automl_art.best_estimator,
'best_config': str(automl_art.best_config),
'best_loss': automl_art.best_loss
}
with open('best_config.json', 'w') as f:
json.dump(best_config, f, indent=2)
mlflow.log_artifact('best_config.json')

print("아티팩트 저장 완료")

모델 레지스트리

# 088 모델 등록 (프로덕션 배포용)
from mlflow.tracking import MlflowClient

client = MlflowClient()

# 088 최신 run에서 모델 등록
with mlflow.start_run(run_name="model_registry_demo"):
automl_reg = AutoML()
automl_reg.fit(X_train, y_train, task="classification",
time_budget=30, verbose=0)

y_pred = automl_reg.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
mlflow.log_metric("accuracy", accuracy)

# 모델 로깅 및 등록
model_uri = mlflow.sklearn.log_model(
automl_reg,
"model",
registered_model_name="flaml_classifier"
)

print(f"모델 등록됨: flaml_classifier")
print(f"모델 URI: {model_uri.model_uri}")

실험 결과 조회

# 088 실험 결과 조회
experiment = mlflow.get_experiment_by_name("flaml_automl_experiment")

if experiment:
runs = mlflow.search_runs(
experiment_ids=[experiment.experiment_id],
order_by=["metrics.accuracy DESC"]
)

print("\n=== 실험 결과 (정확도 순) ===")
if len(runs) > 0:
display_cols = ['run_id', 'metrics.accuracy', 'params.best_estimator']
available_cols = [c for c in display_cols if c in runs.columns]
print(runs[available_cols].head(10).to_string())

MLflow UI 실행 방법

ui_instructions = """
=== MLflow UI 실행 방법 ===

1. 터미널에서 실행:
mlflow ui --backend-store-uri sqlite:///mlflow.db

2. 브라우저에서 접속:
http://127.0.0.1:5000

3. UI에서 가능한 작업:
- 실험 비교 (차트, 테이블)
- 파라미터/메트릭 필터링
- 아티팩트 다운로드
- 모델 버전 관리

4. 원격 서버 설정 (팀 협업용):
mlflow server \\
--backend-store-uri postgresql://user:pass@host/db \\
--default-artifact-root s3://bucket/mlflow
"""

print(ui_instructions)

커스텀 MLflow 래퍼

class FLAMLMLflowTracker:
"""FLAML + MLflow 통합 래퍼"""

def __init__(self, experiment_name="flaml_experiment"):
mlflow.set_experiment(experiment_name)
self.automl = None

def train_and_log(self, X_train, y_train, X_test, y_test,
run_name="flaml_run", **flaml_params):
"""학습 및 MLflow 로깅"""

with mlflow.start_run(run_name=run_name):
# 파라미터 로깅
mlflow.log_params(flaml_params)

# FLAML 학습
self.automl = AutoML()
self.automl.fit(X_train, y_train, **flaml_params)

# 평가
y_pred = self.automl.predict(X_test)
y_proba = self.automl.predict_proba(X_test)[:, 1]

# 메트릭 로깅
metrics = {
"accuracy": accuracy_score(y_test, y_pred),
"roc_auc": roc_auc_score(y_test, y_proba),
"f1": f1_score(y_test, y_pred)
}
mlflow.log_metrics(metrics)

# 결과 로깅
mlflow.log_param("best_estimator", self.automl.best_estimator)

# 모델 저장
mlflow.sklearn.log_model(self.automl, "model")

print(f"Run 완료: {run_name}")
return metrics

# 088 래퍼 사용
tracker = FLAMLMLflowTracker("flaml_wrapper_demo")
results = tracker.train_and_log(
X_train, y_train, X_test, y_test,
run_name="wrapper_test",
task="classification",
time_budget=30,
verbose=0
)
print(f"결과: {results}")

정리

  • MLflow: 실험 추적, 모델 관리 플랫폼
  • 연동: mlflow.start_run()으로 FLAML 실험 추적
  • 로깅: 파라미터, 메트릭, 아티팩트 저장
  • UI: 웹 인터페이스로 실험 비교
  • 레지스트리: 모델 버전 관리 및 배포

다음 글 예고

다음 글에서는 모델 저장과 불러오기를 알아봅니다. FLAML 모델을 다양한 방식으로 저장하고 로드하는 방법을 다룹니다.


FLAML AutoML 마스터 시리즈 #088