MLops #1 mlflow 설치 & 실습

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/ 접속하기

image

잘들어가있다!!

#

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/)를보면

image

mlflow quickstart가 왼쪽에 생겻고 클릭하면 inference(prediction)한게 나온다.

해당 experiment를 확인해보면

image
  • 모델에 대한 정보 environment conda, python environment, requirements.txt 등이 다 넘어왔고
  • tagging이돼있음
  • tracking quickstart 누르면
    • register된 모델도 아래처럼 뜬다.
image

#

정리하면?

  • mlflow를 docker pull해서 설치하고 inference해서 ui에서 어떻게 flow가 뜨는지랑 모델 register를 확인함.

#