MLOps

[MLOps] 14. 모델 파일에 MinIO 반영 및 실행

mlslly 2024. 4. 30. 08:04

* 프로그래머스의 마키나락스 MLOPS 강의를 참고하여 작성함

 

이번 포스팅에서는, 모델 실행 파일에 MinIO에 저장하는 내용을 반영하고 실행해 볼 예정이다.

MinIO로부터 데이터를 다운로드 및 로드하고 이를 활용해서 모델을 실행할 예정. 

 

이전까지 업데이트된 train.py 코드는 아래 내용을 참고

https://ysryuu.tistory.com/18

 

[MLOps] 11. 교차검증 (Cross-validation)

앞서 HPO를 통해 찾은 파라미터가 최적의 값인지 알아보는 방법은 무엇일까? 하이퍼파라미터 최적화의 대표적인 툴인 Optuna 활용 예시는 아래 실습 포스팅을 참고. https://ysryuu.tistory.com/16 [MLOps] 9.

ysryuu.tistory.com

 

반영할 부분

데이터를 다운로드하고, 로드하는 부분을 추가하도록 하겠다. 

 

1. 데이터 다운로드 

from minio import Minio

'''
'''

def download_data():
    bucket_name = 'raw-data'
    object_name = 'iris'

    # minio 클라이언트 
    url = '0.0.0.0:9000'
    access_key = 'ysminio'
    secret_key = 'ysstorage*'
    client = Minio(url, access_key=access_key, secret_key=secret_key, secure=False )

    # 데이터 다운로드 
    object_stat = client.stat_object(bucket_name, object_name)
    data_version_id = object_stat.version_id
    client.fget_object(bucket_name, object_name, file_path='download_data.csv')
    
    return data_version_id # 데이터 버전 아이디 반환

 

 

2. 데이터 로드 

항상 최신 데이터를 얻을 수 있도록 데이터를 다운로드 받기 

import pandas as pd

'''
'''

def load_data():
    data_version_id = download_data()
    df = pd.read_csv('download_data.csv')
    X,y = df.drop(columns=['target']), df['target']
    data_dict = {'data':X, 'target':y, 'version_id':data_version_id }
    return data_dict

 

최종 코드 

<optuna_train_best_minio.py 파일 내용>

import uuid
import mlflow
import optuna 
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from minio import Minio
import pandas as pd

UNIQUE_PREFIX = str(uuid.uuid4())[:8]

BUCKET_NAME = 'raw-data'
OBJECT_NAME = 'iris'

def download_data():

    # minio 클라이언트 
    url = '0.0.0.0:9000'
    access_key = 'ysminio'
    secret_key = 'ysstorage*'
    client = Minio(url, access_key=access_key, secret_key=secret_key, secure=False )

    # 데이터 다운로드 
    object_stat = client.stat_object(BUCKET_NAME, OBJECT_NAME)
    data_version_id = object_stat.version_id
    client.fget_object(BUCKET_NAME, OBJECT_NAME, file_path='download_data.csv')
    return data_version_id


def load_data():
    data_version_id = download_data()
    df = pd.read_csv('download_data.csv')
    X,y = df.drop(columns=['target']), df['target']
    data_dict = {'data':X, 'target':y, 'version_id':data_version_id }
    return data_dict

def objective(trial) :
    # suggest new parameter
    trial.suggest_int('n_estimators',100,1000, step=100)
    trial.suggest_int('max_depth', 3,10)

    run_name = f'{UNIQUE_PREFIX}-{trial.number}'
    with mlflow.start_run(run_name=run_name):

        # load data
        data_dict = load_data()
        mlflow.log_param('bucket_name', BUCKET_NAME)
        mlflow.log_param('object_name', OBJECT_NAME)
        mlflow.log_param('version_id', data_dict['version_id'])
        X, y = data_dict['data'], data_dict['target']

        X_train, X_valid, y_train, y_valid = train_test_split(X,y,test_size=0.3, random_state=2024)

        # train model

        clf = RandomForestClassifier(n_estimators=trial.params['n_estimators'], max_depth=trial.params['max_depth'], random_state=2024)
        clf.fit(X_train, y_train)

        # evaluate data

        y_pred = clf.predict(X_valid)
        acc_score = accuracy_score(y_valid, y_pred)
        
        # log metrics
        mlflow.log_metrics({'accuracy': acc_score})
    
    return acc_score


def train_best_model(params) : 

    run_name = f'{UNIQUE_PREFIX}-best-model'
    with mlflow.start_run(run_name=run_name): # logging
        
        #log parameter
        mlflow.log_params(params)
        
        # load data
        data_dict = load_data()
        mlflow.log_param('bucket_name', BUCKET_NAME)
        mlflow.log_param('object_name', OBJECT_NAME)
        mlflow.log_param('version_id', data_dict['version_id'])
        X, y = data_dict['data'], data_dict['target']


        # train model
        clf = RandomForestClassifier(n_estimators=params['n_estimators'], max_depth=params['max_depth'], random_state=2024)
        clf.fit(X, y) 
        return clf





if __name__ == '__main__' : 

    # set mlflow
    mlflow.set_tracking_uri('http://0.0.0.0:5001')
    mlflow.set_experiment('hpo-tutorial')

    # study
    sampler = optuna.samplers.RandomSampler(seed=2024)
    study = optuna.create_study(sampler=sampler, study_name = 'hpo-tutorial', direction='maximize')

    # optimize
    study.optimize(objective, n_trials=5)

    best_params = study.best_params
    best_clf = train_best_model(best_params)

 

MinIO 데이터 반영한 파일 MLflow로 로깅 하기 

1. MLflow 실행하기 

새 터미널을 실행하여 (MinIO 실행 유지) MLflow를 실행하기. MLflow 시작 방법은 아래 참고

https://ysryuu.tistory.com/6 

 

[MLOps] 4. MLflow 시작하기 (feat.도커)

1. 로컬에서 MLflow 시작하기 1) 터미널에 아래 코드로 설치함 pip3 install mlflow 2) 호스트에 자기 자신의 IP를 할당하라고 명령 $ mlflow server --host 0.0.0.0 혹시 나처럼 'ModuleNotFoundError: No module named 'pkg_reso

ysryuu.tistory.com

 

나는 로컬에서 mlflow를 실행해주었다 .

그리고 나서 http://0.0.0.0:5000 주소로 들어가면 MLflow가 실행되는 것을 확인 가능하다 

$ mlflow server --host 0.0.0.0

 

 

2. MinIO 실행하기  

 

MinIO를 시작하는 방법은 아래 포스팅 참고

아래처럼 또 다른 새 터미널에서 MinIO를 실행해서 계정만들고 파일 업로드 하였다.

docker run -p 9000:9000 -p 9001:9001 \
	-e MINIO_ROOT_USER=minio \
	-e MINIO_ROOT_PASSWORD=storage \
	minio/minio \
	server /data/minio --console-address :9001

python3 upload_data.py

 

 

 

3. 파일 실행하기 

$ python3 optuna_train_best_minio.py

 

hpo-tutorial에 로깅된 것을 확인 가능하다