본문 바로가기
프로젝트 일지/분모자

MLflow - MLflow 개요 & Tracking 기초 (with python)

by 데브겸 2023. 3. 7.

 

공식 도큐먼트를 보고 싶으신 분은 여기로 

 

0. MLflow란?

머신러닝 라이프사이클을 관리해주는 플랫폼.

MLflow가 등장하기 이전에는 다음과 같은 어려움이 있었음

1) 실험 트래킹의 어려움: 개인의 로컬 환경이나 노트북에서 진행하다보니 어떤 데이터, 코드, 파라미터로 실험했는지 트래킹하기 어려움

2) 코드 재현성의 어려움: 환경 설정이나 라이브러리 의존성 등 코드 외에 사항들 때문에 재현이 어려움

3) 표준 패키징과 배포 방법의 부재: 각 개인, 팀마다 방법이 다 다름 

4) 모델 관리를 위한 중앙 저장소의 부재: 중앙 저장소 없이 협업을 하려니 너무너무 힘듦

 

MLflow는 아래의 컴포넌트들로 문제를 해결하려 함

1) MLflow Tracking

: 머신러닝 실험에서 사용, 발생한 파라미터, 코드 버전, 평가 결과, 아티팩트 등을 로깅해주는 API와 UI를 제공

 

2) MLflow Projects

: conda나 docker를 활용하여 모델들을 재실행(run)할 수 있도록 하는 코드 패키징 포맷 제공

- Dockerfile이나 Docker-compose.yaml와 비슷한 형태의 MLproject 파일에 프로젝트, 패키징에 필요한 정보를 적어 관리

 

3) MLFlow Models

: docker, spark나 클라우드의 ml 제품 들에 쉽게 배포할 수 있도록하는 패키징 포맷 제공

 

4) MLFlow Registry

: 전체 라이프사이클을 관리해주는 (협업하게 도와주는) 중앙 모델 저장소

- 모델 저장소에서 모델이 저장될 때마다 버전을 기록하여 버전관리를 도와줌

- Registry에 모델을 쉽게 올리고, 다운로드 받을 수 있어 협업을 용이하게 함

 

 

1. MLflow 설치하기

conda 가상 환경에서 하고 싶어서 'mlops'라는 가상환경 실행, mlflow 설치

$ conda activate mlops
$ pip install mlflow

 

 

2. MLflow 기본 기능 익히기 (Tracking)

참고

0. MLproject
MLflow는 MLproject라는 파일을 통해 전체 프로젝트에 대한 정보를 기록함. MLproject에 정보를 기록하면 MLflow가 project URI와 source version을 기억할 수 있음

1. Experiment (실험)
MLflow에서는 머신러닝 프로젝트의 단위를 'Experiment'로 설정. Experiment는 쉽게 말하자면 하나의 프로젝트와 비슷. 즉, '브랜드 로고 detection 실험', 'chatting translation 실험' 등 공통 평가 지표를 지니고 수행하는 프로세스.

2. Run (실행)
Experiment는 여러 Run으로 이루어질 수 있음. loss function, 모델 파라미터 등을 바꿔 실험을 여러 번 실행해보는 것 (즉, 하나의 실험은 여러 개의 실행을 가질 수 있음). MLflow에는 각 run에 대한 결과들이 각각 기록됨. '브랜드 로고 detection 실험의 파라미터 1번 세팅 실행, 2번 세팅 실행 등등'

 

2-1. MLproject

MLflow의 가장 기본적인 기능은 ML 실험에서의 모델, 평가, 파라미터 등을 로깅하는 것

이것이 어떻게 진행되는가를 MLflow 공식 문서에 있는 sklearn_elasticnet_wine 예제를 통해서 보겠음 (우선 로컬에 기록을 저장하는 방향으로 실습 진행)

git clone https://github.com/mlflow/mlflow
cd mlflow/examples/sklearn_logistic_regression

폴더 구성은 위와 같음

MLflow는 MLproject라는 파일을 통해 전체 프로젝트(이 경우 'sklearn_logistic_regression' 프로젝트)에 대한 메타 정보나 환경 등을 설정 (Dockerfile처럼 MLproject로 이름 고정)

# MLproject

name: sklearn_logistic_example

python_env: python_env.yaml

entry_points:
  main:
    command: "python train.py"

 

2-2. Tracking

그럼 우리는 mlflow로 무엇을 할 것이냐

# train.py

import numpy as np
from sklearn.linear_model import LogisticRegression

import mlflow
import mlflow.sklearn

if __name__ == "__main__":
    X = np.array([-2, -1, 0, 1, 2, 1]).reshape(-1, 1)
    y = np.array([0, 0, 1, 1, 1, 0])
    lr = LogisticRegression()
    lr.fit(X, y)
    score = lr.score(X, y)
    print("Score: %s" % score)
    mlflow.log_metric("score", score)
    mlflow.sklearn.log_model(lr, "model")

위 코드를 잘 보면 log_metric과 log_model 부분이 있음. 이를 통해 mlflow에 metricr과 model을 기록 (=트래킹)!!

 

mlflow에서 로깅할 수 있는 것들은 아래와 같다

 

  • mlflow.log_param(): logs a single key-value param in the currently active run. The key and value are both strings
    • log_params()로 여러 개의 파라미터를 한 번에 로깅 가능
  • mlflow.log_metric(): logs a single key-value metric. The value must always be a number. MLflow remembers the history of values for each metric. 
    • log_metrics()로 여러 개의 메트릭을 한 번에 로깅 가능
  • mlflow.set_tag(): sets a single key-value tag in the currently active run. The key and value are both strings.
    • set_tags()로 여러 개의 태그를 한 번에 로깅 가능
  • mlflow.log_artifact(): logs a local file or directory as an artifact, optionally taking an artifact_path to place it in within the run’s artifact URI. Run artifacts can be organized into directories, so you can place the artifact in a directory this way.
    • log_artifacts()로 주어진 모든 디렉토리의 것들을 아티팩트로 저장 가능

 

 

train.py 파일을 실행

python train.py

위를 보면 model이 run d623~에 저장되었다는 안내를 볼 수 있음

 

다시 한 번 ls를 해보면 mlruns라는 폴더가 새로 생긴 것을 확인할 수 있음. MLflow는 이 mlruns 폴더에 실행 내용을 기록함 

 

tree로 mlruns 폴더를 살펴보면 artifacts(model), metric, param 등이 기록된 것을 확인할 수 있음.

참고로 mlruns 바로 아래에 있는 0는 experiment ID이고, 그 아래 d623~은 run ID이다.

즉, 0이라는 실험에 대한 d623 실행의 기록을 tree 상으로 확인하는 셈이다.

 

참고: Model Artifact란?

Model artifacts are the output that results from training a model, and typically consist of trained parameters, a model definition that describes how to compute inferences, and other metadata. (출처: https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_ModelArtifacts.html)

 

 

 

2-3. 웹 대시보드에서 확인하기 

MLflow는 웹 대시보드 형태로 실험과 실행을 관리할 수 있음. 터미널 환경에서 ui로 접속하고 싶다면 아래 명령어 입력하기

# 터미널 하나 더 켜서 
mlflow ui

http://127.0.0.1:5000 으로 접속하면 아래와 같은 화면을 볼 수 있음

클릭하여 상세 페이지로 접속

아까 터미널 환경에서 떴던 run id d623~를 다시 확인할 수 있음. 그리고 그 아래에 프로젝트에 대한 상세한 정보를 확인할 수 있음

 

3. Automatic logging

그런데 예시처럼 내가 로깅할 것을 하나하나 다 수기로 작성해서 하면... 생각보다 귀찮은 작업이 될 것이다.

이를 해결해주는 것이 바로 autolog! 사용자가 명시하지 않아도 mlflow에서 자동으로 ml의 요소들을 로깅해준다

하지만 지원되는 프레임워크들이 한정적이라 잘 살펴보고 써야 한다는 것이 큰 단점...

2023.03 기준 지원 목록

pytorch의 경우 pytorch_lightning에서만 지원하고 있다는.... 크나큰 단점이 존재한다

 

 

여튼 mlflow examples에 있는 sklearn_autolog 예시로 autolog 기능을 알아보자.

 

cd example/sklearn_autolog/

 

sklearn_autolog는 폴더는 다음과 같이 구성되어 있다.

 

 

linear_regression.py는 autolog의 기본적인 사용법을 익힐 수 있는 예시 파일이다

pipeline.py는 sklearn에서 제공하는 pipeline에도 autolog를 적용할 수 있다는 것을 보여주는 예시 파일이다.

grid_search_cv.py는 gridsearch에서 또한 autolog를 적용할 수 있고, 이 때 어떤 것들이 logging 되는지 보여주기 위한 예시이다.

 

그럼 가장 기본이 되는 linear_regression.py부터 살펴보자

 

3-1. linear_regression.py

linear_regression.py의 코드는 아래와 같다

from pprint import pprint

import numpy as np
from sklearn.linear_model import LinearRegression

import mlflow
from utils import fetch_logged_data


def main():
    # enable autologging
    mlflow.sklearn.autolog()

    # prepare training data
    X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])
    y = np.dot(X, np.array([1, 2])) + 3

    # train a model
    model = LinearRegression()
    model.fit(X, y)
    run_id = mlflow.last_active_run().info.run_id
    print("Logged data and model in run {}".format(run_id))

    # show logged data
    for key, data in fetch_logged_data(run_id).items():
        print("\n---------- logged {} ----------".format(key))
        pprint(data)


if __name__ == "__main__":
    main()

 

위 코드가 일반 linear regression 코드와 다른 점은 두 부분

  • mlflows.sklearn.autolog() : autolog를 사용하기 위해 호출
    • autolog 기능을 사용하기 위해서 맨 처음에 작성해야 한다
    • logging information
      • parameters
      • training metrics (precision, recall, f1, accuracy, log loss, roc auc score, mse, rmse 등)
      • post training metrics (model.score, metic APIs degined in the sklearn.metrics module)
      • tags (모델의 패키지와 클래스 이름)
      • artifacts (run에 대한 메타 데이터와 모델 파일)

 

  • run_id = mlflow.last_active_run().info.run_id: 가장 최근의 실행 정보를 가져오는 것
    • 위 예시 코드에서는 autolog의 결과물을 보여주기 위해 이용함

 

아래 코드로 스크립트 파일 실행

python linear_regression.py

출력된 결과물을 통해 param, metric, tag, artifact 들이 로깅된 것을 확인할 수 있음.

예시 코드에서는 mlflows.sklearn.autolog()외에는 명시적으로 지정해준 것이 없으나, mlflow의 autolog가 자동으로 로깅해준 것.

 

 

 

3-2. pipeline.py

pipeline.py의 코드는 아래와 같다

# pipeline.py

from pprint import pprint

import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline

import mlflow
from utils import fetch_logged_data


def main():
    # enable autologging
    mlflow.sklearn.autolog()

    # prepare training data
    X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])
    y = np.dot(X, np.array([1, 2])) + 3

    # train a model
    pipe = Pipeline([("scaler", StandardScaler()), ("lr", LinearRegression())])
    pipe.fit(X, y)
    run_id = mlflow.last_active_run().info.run_id
    print("Logged data and model in run: {}".format(run_id))

    # show logged data
    for key, data in fetch_logged_data(run_id).items():
        print("\n---------- logged {} ----------".format(key))
        pprint(data)


if __name__ == "__main__":
    main()

 

linear_regression.py 때와 마찬가지로 mlflow.sklearn.autolog()외에 따로 설정해준 것은 없음

 

python pipeline.py

 

하지만 스크립트 파일을 실행을 했을 때 pipeline에 등록되어 사용된 scaler와 lr 그리고 metrics, tags, artifacts 등이 자동으로 기록된 것을 확인할 수 있음.

 

linear_regression.py의 결과물과 다른 점은

  • params
    • lr / lr__copy_X / lr__fit_intercept / lr__n_jobs / lr__positive (lr 빼고는 다 있었지만 'lr__ ' 부분이 추가됨)
    • memory
    • scaler scaler__copy / scaler__with_mean / scaler__with_std / steps / verbose

sklearn 내에 다양한 메소드에 대해서 각기 다른 autolog를 수행한다는 것을 알 수 있음

 

 

3-3. gridsearch.py

gridsearch.py의 코드는 아래와 같다

 

from pprint import pprint

import pandas as pd
from sklearn import svm, datasets
from sklearn.model_selection import GridSearchCV

import mlflow
from utils import fetch_logged_data


def main():
    mlflow.sklearn.autolog()

    iris = datasets.load_iris()
    parameters = {"kernel": ("linear", "rbf"), "C": [1, 10]}
    svc = svm.SVC()
    clf = GridSearchCV(svc, parameters)

    clf.fit(iris.data, iris.target)
    run_id = mlflow.last_active_run().info.run_id

    # show data logged in the parent run
    print("========== parent run ==========")
    for key, data in fetch_logged_data(run_id).items():
        print("\n---------- logged {} ----------".format(key))
        pprint(data)

    # show data logged in the child runs
    filter_child_runs = "tags.mlflow.parentRunId = '{}'".format(run_id)
    runs = mlflow.search_runs(filter_string=filter_child_runs)
    param_cols = ["params.{}".format(p) for p in parameters.keys()]
    metric_cols = ["metrics.mean_test_score"]

    print("\n========== child runs ==========\n")
    pd.set_option("display.max_columns", None)  # prevent truncating columns
    print(runs[["run_id", *param_cols, *metric_cols]])


if __name__ == "__main__":
    main()

 

특이한 점은 아까 보이지 않았던 'parent run'과 'child run'이라는 개념이 새로 등장한 것

document를 찾아보니 parent run과 child run은 sklearn의 gridsearch에서만 나오는 개념인 것 같다

 

  • parent run에서는 파이프라인 전체에서의 파라미터나 class name, artifact / gridsearch에서 찾은 best parameter 등 이 기록되는 것 같고
  • child run에서는 gridsearch를 진행할 때 각각의 경우의 수에 대한 run들에 대한 정보들을 기록되는 것 같다
    • 각각의 child run도 어쨌거나 run이기 때문에 고유한 run id를 가지게 된다

 

python grid_search_cv.py

 

실행하면 아래와 같은 결과 화면이 출력된다

parent run에는 앞선 두 예시와 비슷하지만 best_estimator 관련한 것들을 logging 진행한다는 점에서 조금 다르게 결과가 출력

child run에서는 각각 어떤 param으로 돌렸는지와 metric이 얼마 나왔는지를 출력한다

 

 

 

tree로 확인해보니 독립된 run들이 쫘라락 기록된 것을 확인할 수 있다

 

독특한 것은 child run의 tag 중에 'mlflow.parentRunId'태그가 있는데,

run id가 4d62~인 child run의 parentRunId를 보면 8239~로 시작하는 parent run id가 기록되어 있는 것을 확인할 수 있다

 

mlflow ui에서는 아래 빨간색 박스와 같은 방식으로 위계를 표현한 것을 확인할 수 있다

 

 

 

'프로젝트 일지 > 분모자' 카테고리의 다른 글

MLflow - Tracking Servers  (0) 2023.07.23
FastAPI: 데이터베이스 연결의 이해  (0) 2023.06.23
MLflow - Tracking using CLI  (0) 2023.03.13