093 모델 저장과 로드
키워드: save_model, load_model
개요
학습된 모델을 저장하고 다시 불러오는 것은 배포의 첫 단계입니다. PyCaret은 전처리 파이프라인과 모델을 함께 저장하여 재현성을 보장합니다.
실습 환경
- Python 버전: 3.11 권장
- 필요 패키지:
pycaret[full]>=3.0
save_model 기본
from pycaret.classification import *
from pycaret.datasets import get_data
# 093 데이터 로드
data = get_data('diabetes')
# 093 환경 설정
clf = setup(data, target='Class variable', session_id=42, verbose=False)
# 093 모델 생성
rf = create_model('rf')
# 093 모델 저장
save_model(rf, 'my_first_model')
# 093 my_first_model.pkl 파일 생성됨
print("모델 저장 완료!")
load_model
from pycaret.classification import *
# 093 모델 로드
loaded_model = load_model('my_first_model')
# 093 새 데이터에 예측
from pycaret.datasets import get_data
new_data = get_data('diabetes')
predictions = predict_model(loaded_model, data=new_data.head(10))
print(predictions)
finalize_model 후 저장
from pycaret.classification import *
from pycaret.datasets import get_data
data = get_data('diabetes')
clf = setup(data, target='Class variable', session_id=42, verbose=False)
# 093 모델 생성 및 튜닝
rf = create_model('rf')
tuned_rf = tune_model(rf)
# 093 전체 데이터로 재학습 (배포용)
final_model = finalize_model(tuned_rf)
# 093 최종 모델 저장
save_model(final_model, 'production_model')
저장 파일 구조
import pickle
# 093 PyCaret 저장 파일 내용 확인
with open('production_model.pkl', 'rb') as f:
saved_obj = pickle.load(f)
print(f"저장된 객체 타입: {type(saved_obj)}")
# 093 Pipeline 객체가 저장됨
# 093 - 전처리 단계들
# 093 - 최종 모델
저장 옵션
from pycaret.classification import *
clf = setup(data, target='Class variable', session_id=42, verbose=False)
rf = create_model('rf')
# 093 기본 저장 (pickle)
save_model(rf, 'model_pickle')
# 093 압축 저장
import joblib
final = finalize_model(rf)
pipeline = get_config('pipeline')
# 093 압축률 지정
joblib.dump(pipeline, 'model_compressed.joblib', compress=3)
# 093 로드
loaded = joblib.load('model_compressed.joblib')
버전 관리
from pycaret.classification import *
from datetime import datetime
import json
import os
clf = setup(data, target='Class variable', session_id=42, verbose=False)
rf = create_model('rf')
final = finalize_model(rf)
# 093 버전 정보 생성
version_info = {
'version': '1.0.0',
'created_at': datetime.now().isoformat(),
'model_type': 'RandomForestClassifier',
'pycaret_version': '3.0.0',
'metrics': {
'accuracy': 0.78,
'f1': 0.75
}
}
# 093 메타데이터 저장
model_name = f"model_v{version_info['version']}"
save_model(final, model_name)
with open(f'{model_name}_meta.json', 'w') as f:
json.dump(version_info, f, indent=2)
print(f"모델 저장: {model_name}.pkl")
print(f"메타데이터: {model_name}_meta.json")
모델 레지스트리 패턴
import os
import json
from datetime import datetime
class ModelRegistry:
"""간단한 모델 레지스트리"""
def __init__(self, base_path='./models'):
self.base_path = base_path
os.makedirs(base_path, exist_ok=True)
self.registry_file = os.path.join(base_path, 'registry.json')
self._load_registry()
def _load_registry(self):
if os.path.exists(self.registry_file):
with open(self.registry_file, 'r') as f:
self.registry = json.load(f)
else:
self.registry = {'models': []}
def _save_registry(self):
with open(self.registry_file, 'w') as f:
json.dump(self.registry, f, indent=2)
def register(self, model, name, metrics, tags=None):
"""모델 등록"""
version = len([m for m in self.registry['models'] if m['name'] == name]) + 1
model_id = f"{name}_v{version}"
# 모델 저장
model_path = os.path.join(self.base_path, f"{model_id}.pkl")
save_model(model, model_path.replace('.pkl', ''))
# 레지스트리 업데이트
entry = {
'id': model_id,
'name': name,
'version': version,
'path': model_path,
'metrics': metrics,
'tags': tags or [],
'created_at': datetime.now().isoformat(),
'stage': 'development'
}
self.registry['models'].append(entry)
self._save_registry()
return model_id
def get_model(self, model_id):
"""모델 로드"""
for m in self.registry['models']:
if m['id'] == model_id:
return load_model(m['path'].replace('.pkl', ''))
return None
def promote(self, model_id, stage):
"""스테이지 변경"""
for m in self.registry['models']:
if m['id'] == model_id:
m['stage'] = stage
self._save_registry()
def get_production_model(self, name):
"""프로덕션 모델 가져오기"""
for m in self.registry['models']:
if m['name'] == name and m['stage'] == 'production':
return load_model(m['path'].replace('.pkl', ''))
return None
def list_models(self):
"""모델 목록"""
return self.registry['models']
# 093 사용 예
registry = ModelRegistry('./my_models')
# 093 모델 등록
from pycaret.classification import *
clf = setup(data, target='Class variable', session_id=42, verbose=False)
rf = create_model('rf')
final = finalize_model(rf)
model_id = registry.register(
final,
name='diabetes_classifier',
metrics={'accuracy': 0.78, 'f1': 0.75},
tags=['random_forest', 'diabetes']
)
print(f"등록된 모델: {model_id}")
# 093 프로덕션 승격
registry.promote(model_id, 'production')
# 093 프로덕션 모델 로드
prod_model = registry.get_production_model('diabetes_classifier')
ONNX 형식 저장
# 093 ONNX: 플랫폼 간 호환 형식
# 093 pip install skl2onnx onnxruntime
try:
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType
import onnxruntime as rt
import numpy as np
from pycaret.classification import *
from pycaret.datasets import get_data
data = get_data('diabetes')
clf = setup(data, target='Class variable', session_id=42, verbose=False)
# sklearn 모델 가져오기
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_estimators=100, random_state=42)
X = get_config('X_train_transformed')
y = get_config('y_train_transformed')
rf.fit(X, y)
# ONNX 변환
initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))]
onnx_model = convert_sklearn(rf, initial_types=initial_type)
# 저장
with open('model.onnx', 'wb') as f:
f.write(onnx_model.SerializeToString())
# ONNX 런타임으로 추론
sess = rt.InferenceSession('model.onnx')
input_name = sess.get_inputs()[0].name
# 예측
X_test = get_config('X_test_transformed')
pred_onnx = sess.run(None, {input_name: X_test.values.astype(np.float32)})
print(f"ONNX 예측 완료: {pred_onnx[0][:5]}")
except ImportError:
print("ONNX 패키지 필요: pip install skl2onnx onnxruntime")
회귀 모델 저장
from pycaret.regression import *
from pycaret.datasets import get_data
# 093 회귀 데이터
data = get_data('boston')
reg = setup(data, target='medv', session_id=42, verbose=False)
# 093 모델 생성 및 저장
rf = create_model('rf')
final = finalize_model(rf)
save_model(final, 'boston_regressor')
# 093 로드 및 예측
loaded = load_model('boston_regressor')
predictions = predict_model(loaded, data=data.head(5))
print(predictions)
모델 검증 후 저장
from pycaret.classification import *
from pycaret.datasets import get_data
data = get_data('diabetes')
clf = setup(data, target='Class variable', session_id=42, verbose=False)
rf = create_model('rf')
results = pull()
# 093 성능 검증 후 저장
min_accuracy = 0.70
accuracy = results['Accuracy'].values[0]
if accuracy >= min_accuracy:
final = finalize_model(rf)
save_model(final, 'validated_model')
print(f"모델 저장됨 (정확도: {accuracy:.4f})")
else:
print(f"성능 미달 (정확도: {accuracy:.4f} < {min_accuracy})")
다중 모델 저장
from pycaret.classification import *
from pycaret.datasets import get_data
import os
data = get_data('diabetes')
clf = setup(data, target='Class variable', session_id=42, verbose=False)
# 093 여러 모델 생성 및 저장
models_to_save = ['rf', 'xgboost', 'lightgbm']
save_dir = './saved_models'
os.makedirs(save_dir, exist_ok=True)
for model_id in models_to_save:
model = create_model(model_id, verbose=False)
final = finalize_model(model)
save_path = os.path.join(save_dir, f'{model_id}_model')
save_model(final, save_path)
print(f"저장: {save_path}.pkl")
정리
- save_model: 파이프라인 + 모델 함께 저장
- load_model: 저장된 모델 로드
- finalize_model: 배포 전 전체 데이터 재학습
- 버전 관리: 메타데이터와 함께 저장
- ONNX: 플랫폼 간 호환성
- 검증 후 저장: 품질 보장
다음 글 예고
다음 글에서는 FastAPI로 모델 배포를 다룹니다.
PyCaret 머신러닝 마스터 시리즈 #093