MLops #1 mlflow 설치 & 실습 #
#2025-08-21
1. mlflow 설치 및 docker 띄우기 #
$ export CR_PAT=* # *: github token 블라인드 처리
$ echo $CR_PAT | docker login ghcr.io -u yshghid --password-stdin
Login Succeeded
로그인햇으면 도커를 켠다음에 다음을 수행.
$ docker pull ghcr.io/mlflow/mlflow:v2.0.1
v2.0.1: Pulling from mlflow/mlflow
7a6db449b51b: Pull complete
e238bceb2957: Pull complete
ce77f44508b5: Pull complete
455a39ac3ab8: Pull complete
f8c2fbfe5046: Pull complete
60e3c6e8536b: Pull complete
Digest: sha256:1e1f28a6134e7e6c4b0d0a4f5f8647ff31c953ad53eb3bb5af4c51ae4e8dd14d
Status: Downloaded newer image for ghcr.io/mlflow/mlflow:v2.0.1
ghcr.io/mlflow/mlflow:v2.0.1
$ docker image ls | grep mlflow
ghcr.io/mlflow/mlflow v2.0.1 35853aa42ccd 2 years ago 905MB
확인해보면 제대로 떠있다!!
$ docker compose up
[+] Running 12/12
⠿ db Pulled 20.3s
⠿ da99ef17bcd1 Pull complete 4.2s
⠿ bc12642f0976 Pull complete 4.2s
⠿ 739cdd12ec77 Pull complete 4.3s
⠿ d7e901e4e4c1 Pull complete 4.4s
⠿ 19592870864a Pull complete 4.4s
⠿ bbd0027b9705 Pull complete 4.5s
⠿ 3da0df221558 Pull complete 8.2s
⠿ c055843e3f4c Pull complete 8.3s
⠿ 6682c79ed3b0 Pull complete 16.0s
⠿ 8583ecde4482 Pull complete 16.0s
⠿ c195b220f391 Pull complete 16.1s
[+] Running 3/3
⠿ Network learn-mlflow-main_default Created 0.1s Created 0.4s
⠿ Container mysql Created 0.4s
⠿ Container mlflow Created 0.1s
MLflow 서버를 띄웠고 경고창이 뜨는데
mlflow | The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8)
mlflow | <jemalloc>: MADV_DONTNEED does not work (memset will be used instead) (This is the expected behaviour if you are running under QEMU)
호스트 CPU는 ARM64이고 MLflow 공식 이미지는 AMD64여서 플랫폼 불일치 이슈가 있지만 문제되지는 않고 만약에 해결하고싶으면 docker-compose.yml에 아래와같이쓰면 댄다고함.
services:
mlflow:
image: ghcr.io/mlflow/mlflow:v2.0.1
platform: linux/amd64
docker ps 해보면
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bcb7b2832fb7 ghcr.io/mlflow/mlflow:v2.0.1 "/bin/sh -c 'pip ins…" 21 minutes ago Up 20 minutes 0.0.0.0:5001->5000/tcp mlflow
87ed94077621 mysql:8.0 "docker-entrypoint.s…" 21 minutes ago Up 20 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysql
떠있는걸볼수있고
확인후에 http://localhost:5001/ 접속하기
잘들어가있다!!
#
2. mlflow quick start #
튜토리얼 링크 - https://mlflow.org/docs/latest/getting-started/intro-quickstart/index.html
위에서 한 내용이 step1-2여서 step3부터 하면 댄다.
# Step 3 - Train a model and prepare metadata for logging
import mlflow
from mlflow.models import infer_signature
import pandas as pd
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
# Load the Iris dataset
X, y = datasets.load_iris(return_X_y=True)
# Split the data into training and test sets
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# Define the model hyperparameters
params = {
"solver": "lbfgs",
"max_iter": 1000,
"multi_class": "auto",
"random_state": 8888,
}
# Train the model
lr = LogisticRegression(**params)
lr.fit(X_train, y_train)
# Predict on the test set
y_pred = lr.predict(X_test)
# Calculate metrics
accuracy = accuracy_score(y_test, y_pred)
- step3는 그냥 사이킷런으로 기본적인 모델 만들기.
# Step 4 - Log the model and its metadata to MLflow
# Set our tracking server uri for logging
mlflow.set_tracking_uri(uri="http://127.0.0.1:8080")
# Create a new MLflow Experiment
mlflow.set_experiment("MLflow Quickstart")
# Start an MLflow run
with mlflow.start_run():
# Log the hyperparameters
mlflow.log_params(params)
# Log the loss metric
mlflow.log_metric("accuracy", accuracy)
# Infer the model signature
signature = infer_signature(X_train, lr.predict(X_train))
# Log the model, which inherits the parameters and metric
model_info = mlflow.sklearn.log_model(
sk_model=lr,
name="iris_model",
signature=signature,
input_example=X_train,
registered_model_name="tracking-quickstart",
)
# Set a tag that we can use to remind ourselves what this model was for
mlflow.set_logged_model_tags(
model_info.model_id, {"Training Info": "Basic LR model for iris data"}
)
- step4는 tracking uri를 설정하고 현재 experiment에 대한 name을 MLflow Quickstart로 정한다.
- model_info에 step3에서 만들었던 lr 모델을 보낸다.
# Load the model back for predictions as a generic Python Function model
loaded_model = mlflow.pyfunc.load_model(model_info.model_uri)
predictions = loaded_model.predict(X_test)
iris_feature_names = datasets.load_iris().feature_names
result = pd.DataFrame(X_test, columns=iris_feature_names)
result["actual_class"] = y_test
result["predicted_class"] = predictions
result[:4]
- model loading을 하고
- loading된 model을 가지고 test dataset을 사용해서 prediction을 한다.
#
3. mlflow experiments #
모델 inference를 하면 mlflow의 experiments에 뜬다. (ui에서 information을 볼수있다)
#
확인하는원리는?
- compose.yml을 보면
volumes:
- ./mlruns:/mlflow/mlruns
라고 돼있는데 local의 mlruns 디렉토리를 /mlflow/mlruns 도커 이미지 안에 매핑을 시키면 mlruns 디렉토리내 모든 파일들이 도커 이미지로 들어간다.
#
확인하는법은?
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d40c2085dd73 ghcr.io/mlflow/mlflow:v2.0.1 "/bin/sh -c 'pip ins…" About a minute ago Up About a minute 0.0.0.0:5001->5000/tcp mlflow
9da59e40a1f8 mysql:8.0 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:3306->3306/tcp, 33060/tcp mysql
$ docker exec -it d40c2085dd73 /bin/bash
root@d40c2085dd73:/#
- docker 안으로 들어가서 /mlflow/mlruns 들어가기.
root@d40c2085dd73:/# ls
bin boot dev etc home lib lib64 media mlflow mnt opt proc root run sbin srv sys tmp usr var
root@d40c2085dd73:/# cd /mlflow/mlruns
root@d40c2085dd73:/mlflow/mlruns#
여기서 python tutorial.py를 하면 실행된다.
root@d40c2085dd73:/mlflow/mlruns# python tutorial.py
<jemalloc>: MADV_DONTNEED does not work (memset will be used instead)
<jemalloc>: (This is the expected behaviour if you are running under QEMU)
2025/08/22 01:10:51 INFO mlflow.tracking.fluent: Experiment with name 'MLflow Quickstart' does not exist. Creating a new experiment.
/usr/local/lib/python3.10/site-packages/_distutils_hack/__init__.py:33: UserWarning: Setuptools is replacing distutils.
warnings.warn("Setuptools is replacing distutils.")
Successfully registered model 'tracking-quickstart'.
2025/08/22 01:11:01 INFO mlflow.tracking._model_registry.client: Waiting up to 300 seconds for model version to finish creation. Model name: tracking-quickstart, version 1
Created version '1' of model 'tracking-quickstart'.
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) actual_class predicted_class
0 6.1 2.8 4.7 1.2 1 1
1 5.7 3.8 1.7 0.3 0 0
2 7.7 2.6 6.9 2.3 2 2
3 6.0 2.9 4.5 1.5 1 1
- iris 데이터를 가지고 모델을 만들고
- mlflow가 tracking을 하고
- model을 만들어서 tracking-quickstart라는 이름으로 register를 함
- 그리고 result를 출력.
- tracking url은?
- compose.yml에 MLFLOW_TRACKING_URI=http://0.0.0.0:5000 로 돼있어서 자동으로 이쪽으로간다(공식 튜토리얼은 mlflow.set_tracking_uri(uri=“http://127.0.0.1:8080”)
#
tutorial.py에서 run하는부분 코드를 보면 이렇다
# Start an MLflow run
with mlflow.start_run():
# Log the hyperparameters
mlflow.log_params(params)
# Log the loss metric
mlflow.log_metric("accuracy", float(accuracy))
# Set a tag that we can use to remind ourselves what this run was for
mlflow.set_tag("Training Info", "Basic LR model for iris data")
# Infer the model signature
signature = infer_signature(X_train, lr.predict(X_train))
# Log the model
model_info = mlflow.sklearn.log_model(
sk_model=lr,
artifact_path="iris_model",
signature=signature,
input_example=X_train,
registered_model_name="tracking-quickstart",
)
# Load the model back for predictions as a generic Python Function model
loaded_model = mlflow.pyfunc.load_model(model_info.model_uri)
predictions = loaded_model.predict(X_test)
iris_feature_names = datasets.load_iris().feature_names
result = pd.DataFrame(X_test, columns=iris_feature_names)
result["actual_class"] = y_test
result["predicted_class"] = predictions
print(result[:4])
#
암튼 이렇게 Inference를 했고 UI(http://localhost:5001/)를보면
mlflow quickstart가 왼쪽에 생겻고 클릭하면 inference(prediction)한게 나온다.
해당 experiment를 확인해보면
- 모델에 대한 정보 environment conda, python environment, requirements.txt 등이 다 넘어왔고
- tagging이돼있음
- tracking quickstart 누르면
- register된 모델도 아래처럼 뜬다.
#
정리하면?
- mlflow를 docker pull해서 설치하고 inference해서 ui에서 어떻게 flow가 뜨는지랑 모델 register를 확인함.