공식 도큐먼트를 보고 싶으신 분은 여기로
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의 요소들을 로깅해준다
하지만 지원되는 프레임워크들이 한정적이라 잘 살펴보고 써야 한다는 것이 큰 단점...
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 |