joblib와 pickle을 이용한 모델 저장
학습자는 joblib와 pickle을 모두 사용해 학습된 파이프라인을 직렬화하고 다시 불러온 뒤, 예측이 동일한지 확인하여 저장과 복원이 성공했음을 검증합니다.
joblib와 pickle을 이용한 모델 저장은(는) CoddyKit의 무료 Machine Learning Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Machine Learning Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Machine Learning Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.
Why Model Persistence Matters
Training a machine learning model is expensive: it can take minutes to hours and consumes significant compute. Model persistence saves the fitted model to disk so you can reload it instantly for inference without retraining. This is the bridge between the data science notebook and a production system — the serialised model file is the deployable artefact that data engineers package and serve.
What Gets Saved in a Model File?
When you serialise a fitted sklearn model or pipeline, the file captures: all fitted parameters (e.g., scaler mean and variance, tree structure, logistic regression coefficients), hyperparameter settings, and the Python class definition reference. It does NOT include the training data. Loading the file reconstructs a Python object ready to call predict immediately.
Saving with joblib.dump
joblib is the recommended serialisation tool for sklearn objects. It handles large NumPy arrays efficiently using memory mapping and supports transparent compression. The standard workflow is: train the model, dump it to a .joblib file, then load it in a separate script or service for inference.
import joblib
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
X, y = load_breast_cancer(return_X_y=True)
pipe = Pipeline([
('scaler', StandardScaler()),
('clf', LogisticRegression(C=1.0, max_iter=300))
])
pipe.fit(X, y)
# Save
joblib.dump(pipe, '/tmp/cancer_model.joblib')
print('Model saved to /tmp/cancer_model.joblib')Loading with joblib.load
joblib.load deserialises the file and returns the exact fitted pipeline object. The loaded model has all of the same attributes — named_steps, fitted scaler parameters, classifier coefficients — as the original. You can immediately call predict, predict_proba, or score without any additional setup.
import joblib
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
# Load in a fresh context
model = joblib.load('/tmp/cancer_model.joblib')
predictions = model.predict(X_test[:5])
print('Predictions:', predictions)
print('Test accuracy:', model.score(X_test, y_test).round(4))Using pickle for Serialisation
Python's standard library pickle module also serialises sklearn objects. Open files in binary mode ('wb' for write, 'rb' for read). The pickle.HIGHEST_PROTOCOL constant uses the most efficient available protocol. For small models or scripting contexts, pickle is perfectly adequate.
import pickle
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True)
model = LogisticRegression().fit(X, y)
# Save
with open('/tmp/iris_model.pkl', 'wb') as f:
pickle.dump(model, f, protocol=pickle.HIGHEST_PROTOCOL)
# Load
with open('/tmp/iris_model.pkl', 'rb') as f:
loaded = pickle.load(f)
print('Score:', loaded.score(X, y).round(4))
print('Coefficients shape:', loaded.coef_.shape)Comparing joblib vs pickle File Sizes
For a large model like a RandomForest with 1000 trees, joblib's memory-mapped NumPy array storage is more efficient. The difference becomes especially pronounced when the model contains large parameter matrices. For small models (LogReg, SVM), the size difference is negligible.
import joblib
import pickle
import os
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
X, y = make_classification(n_samples=1000, n_features=20, random_state=0)
rf = RandomForestClassifier(n_estimators=100, random_state=0).fit(X, y)
# joblib
joblib.dump(rf, '/tmp/rf_model.joblib')
# pickle
with open('/tmp/rf_model.pkl', 'wb') as f:
pickle.dump(rf, f)
print(f'joblib size: {os.path.getsize("/tmp/rf_model.joblib"):,} bytes')
print(f'pickle size: {os.path.getsize("/tmp/rf_model.pkl"):,} bytes')Compression with joblib
Use joblib.dump(model, path, compress=3) to compress the file using zlib. Compression levels range from 1 (fast, larger) to 9 (slow, smallest). Level 3 is a practical default. For LZ4 compression (faster than zlib): compress=('lz4', 1). Load time slightly increases for compressed files but the network transfer and storage savings are often worth it.
import joblib
import os
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
X, y = make_classification(n_samples=1000, random_state=0)
rf = RandomForestClassifier(n_estimators=100, random_state=0).fit(X, y)
for level in [0, 3, 6, 9]:
path = f'/tmp/rf_compress_{level}.joblib'
joblib.dump(rf, path, compress=level)
size = os.path.getsize(path)
print(f'compress={level}: {size:,} bytes')Verifying Round-Trip Consistency
After loading, always verify that the loaded model produces identical predictions to the original. This guards against silent corruption, version mismatches, or incomplete file writes. Compare predictions with np.array_equal on the same input.
import joblib
import numpy as np
from sklearn.datasets import load_iris
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
X, y = load_iris(return_X_y=True)
pipe = Pipeline([('sc', StandardScaler()), ('lr', LogisticRegression())]).fit(X, y)
original_preds = pipe.predict(X)
joblib.dump(pipe, '/tmp/verify_pipe.joblib')
loaded = joblib.load('/tmp/verify_pipe.joblib')
loaded_preds = loaded.predict(X)
if np.array_equal(original_preds, loaded_preds):
print('Round-trip PASSED: predictions are identical.')
else:
diff = (original_preds != loaded_preds).sum()
print(f'Round-trip FAILED: {diff} different predictions!')Version Pinning and Metadata
A model pickled with scikit-learn 1.2 may not load cleanly in scikit-learn 1.5 due to internal changes. Always store a metadata file alongside the model that records: sklearn version, Python version, training date, dataset version, and key metrics. This is your model card — the governance document that explains what the model is and how it was produced.
import json
import sklearn
import sys
from datetime import datetime
metadata = {
'model_file': 'cancer_model.joblib',
'sklearn_version': sklearn.__version__,
'python_version': sys.version.split()[0],
'training_date': datetime.utcnow().isoformat(),
'dataset': 'breast_cancer',
'test_accuracy': 0.9789,
'features': 30,
'algorithm': 'LogisticRegression'
}
with open('/tmp/cancer_model_metadata.json', 'w') as f:
json.dump(metadata, f, indent=2)
print(json.dumps(metadata, indent=2))Security: Never Load Untrusted Pickle Files
Critical security warning: both pickle and joblib can execute arbitrary Python code when loading. Never load a model file from an untrusted source — it could be a malicious payload disguised as a model. For models shared across organisations, consider safer formats: ONNX (Open Neural Network Exchange) is a standardised, inspectable format supported by most frameworks.
File Naming Conventions
Good naming conventions embed key information into the filename: algorithm, dataset, date, and metric. This makes the model registry self-documenting and prevents accidentally loading the wrong model version in production.
from datetime import date
from sklearn.metrics import accuracy_score
import joblib
# Example naming convention
dataset = 'breast_cancer'
algorithm = 'logreg'
test_acc = 0.9789
today = date.today().strftime('%Y%m%d')
filename = f'{dataset}_{algorithm}_{today}_acc{int(test_acc*100)}.joblib'
print('Model filename:', filename)
# e.g.: breast_cancer_logreg_20260620_acc97.joblib
# Load the model we saved earlier (demo)
model = joblib.load('/tmp/cancer_model.joblib')
print('Loaded OK')Quick Check
Test your understanding of model serialisation with joblib and pickle from this lesson.
Lesson Recap
In this lesson you learned: joblib.dump and joblib.load serialise and restore fitted sklearn models efficiently, pickle works too but joblib is preferred for models with large NumPy arrays due to memory mapping, and always store a metadata file alongside the model recording library versions, training date, and key metrics for governance. Next up we design a versioning naming convention and metadata sidecar to track multiple model versions in a model registry.
자주 묻는 질문
“joblib와 pickle을 이용한 모델 저장” 강의는 무료인가요?
네 — “joblib와 pickle을 이용한 모델 저장” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Machine Learning Academy 강의 전체를 잠금 해제할 수 있습니다. Machine Learning Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“joblib와 pickle을 이용한 모델 저장”에서 뭘 배우나요?
학습자는 joblib와 pickle을 모두 사용해 학습된 파이프라인을 직렬화하고 다시 불러온 뒤, 예측이 동일한지 확인하여 저장과 복원이 성공했음을 검증합니다. 브라우저에서 직접 실행하는 실습 코드로 Machine Learning Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Machine Learning Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Machine Learning Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“joblib와 pickle을 이용한 모델 저장” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Machine Learning Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Machine Learning Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- joblib와 pickle을 이용한 모델 저장
- 모델 버전 관리: 파일 이름과 메타데이터가 중요한 이유
- FastAPI 엔드포인트로 예측 제공하기
- 예측 모니터링: 입력과 출력 기록하기