Model yang telah dilatih hanya hidup di memori: begitu proses Python berakhir, seluruh bobot yang dipelajarinya hilang dan pelatihan harus diulang dari awal. Topik ini membahas cara menyimpan model ke berkas dengan joblib, memuatnya kembali di proses mana pun, dan mengunci versi pustaka agar artefaknya tetap dapat dipercaya. Pembahasan ditutup dengan alasan menyimpan pipeline utuh daripada model telanjang, disertai bukti numerik bahwa prediksi sebelum dan sesudah pemuatan identik.
Menyimpan dan memuat artefak model#
Pustaka joblib yang menyertai instalasi scikit-learn menyediakan dua fungsi inti untuk persistensi, yaitu menyimpan objek dari memori ke berkas dan memuatnya kembali. joblib.dump menulis objek Python ke berkas, sedangkan joblib.load membacanya kembali menjadi objek yang setara. scikit-learn merekomendasikan joblib daripada pickle untuk model yang membawa array numpy besar karena mekanisme penyimpanannya lebih efisien bagi data semacam itu, dan pemakaiannya cukup dengan satu argumen objek serta satu argumen jalur berkas.
Model sebaiknya tidak disimpan sendirian. Berkas yang baik memuat objek model beserta metadata, misalnya versi scikit-learn saat penyimpanan dan penanda waktu (timestamp), yaitu catatan kapan penyimpanan itu dilakukan. Metadata semacam ini menjadi alat pemeriksaan pertama ketika artefak diunduh ulang berbulan-bulan kemudian. Program berikut melatih pipeline, yaitu rantai praproses dan model dalam satu objek, pada dataset iris, menyimpannya ke /tmp/model-latihan.joblib, lalu memuatnya kembali dan membandingkan prediksinya.
import time
import joblib
from sklearn import __version__ as versi_sklearn
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
# pipeline utuh: praproses dan model dirangkai sebelum disimpan
pipeline = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
iris.data, iris.target, test_size=0.25, stratify=iris.target, random_state=42
)
pipeline.fit(X_train, y_train)
# artefak memuat model beserta metadata versi dan waktu penyimpanan
artefak = {
"model": pipeline,
"sklearn_version": versi_sklearn,
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
}
joblib.dump(artefak, "/tmp/model-latihan.joblib")
# memuat kembali artefak, seolah dilakukan oleh proses atau hari yang lain
muatan = joblib.load("/tmp/model-latihan.joblib")
model_muat = muatan["model"]
print("kunci artefak :", list(muatan.keys()))
print("sklearn saat simpan:", muatan["sklearn_version"])
print("jenis objek model :", type(model_muat).__name__)
print("akurasi sebelum :", round(pipeline.score(X_test, y_test), 3))
print("akurasi sesudah :", round(model_muat.score(X_test, y_test), 3))
print("prediksi identik :", (pipeline.predict(X_test) == model_muat.predict(X_test)).all())kunci artefak : ['model', 'sklearn_version', 'timestamp']
sklearn saat simpan: 1.5.2
jenis objek model : Pipeline
akurasi sebelum : 0.921
akurasi sesudah : 0.921
prediksi identik : TrueKeluaran menegaskan tiga hal sekaligus. Kunci artefak terdiri atas model beserta dua entri metadata yang dicatat pada saat penyimpanan. Jenis objek yang dimuat adalah Pipeline, yang berarti seluruh rantai praproses ikut tersimpan, bukan modelnya saja. Akurasi 0.921 tetap sama sebelum dan sesudah pemuatan, dan perbandingan prediksi per baris menghasilkan True. Identitas ini bukan kebetulan, melainkan konsekuensi dari penyimpanan seluruh keadaan objek, termasuk koefisien model dan statistik scaler-nya.
Keberadaan artefak juga dapat diperiksa dari terminal. Perintah berikut menampilkan berkas tersebut dan ukurannya dalam byte.
# membuktikan artefak model tersimpan di /tmp
ls /tmp/model-latihan.joblib
# menampilkan ukuran artefak dalam byte
stat -c "%s byte" /tmp/model-latihan.joblib/tmp/model-latihan.joblib
1637 byteUkuran 1637 byte mencerminkan model iris yang kecil. Angka tersebut bergantung pada model dan versi pustaka yang digunakan, sehingga mesin lain boleh saja menampilkan nilai yang berbeda. Alur lengkap dari pelatihan sampai pemuatan kembali dirangkum pada diagram berikut.
Penguncian versi pustaka#
Model yang disimpan dengan scikit-learn 1.5.2 tidak dijamin terbaca oleh versi lain. joblib menyimpan struktur internal objek estimator, sedangkan versi scikit-learn yang lebih baru boleh mengubah nama atribut, perilaku parameter bawaan, atau tata letak internal kelas itu sendiri. scikit-learn menyediakan peringatan InconsistentVersionWarning yang muncul ketika model dimuat oleh versi yang berbeda dari versi penyimpannya, tetapi peringatan itu tidak menghentikan pemuatan, sehingga pemeriksaan versi tetap menjadi tanggung jawab penulis program.
Penguncian versi (version pinning), yaitu pembatasan proyek pada versi pustaka tertentu, dilakukan dari dua arah. Dari arah artefak, versi dicatat bersama model sebagaimana dict pada bagian “Menyimpan dan memuat artefak model”. Dari arah lingkungan, versi dicatat pada berkas kebutuhan proyek seperti requirements.txt. Kode berikut mencetak versi lingkungan yang layak dicatat.
import sys
import joblib
import numpy
import sklearn
print("python :", sys.version.split()[0])
print("scikit-learn :", sklearn.__version__)
print("numpy :", numpy.__version__)
print("joblib :", joblib.__version__)python : 3.12.16
scikit-learn : 1.5.2
numpy : 2.1.3
joblib : 1.5.3Menyimpan pipeline utuh, bukan model telanjang#
Pipeline yang tersimpan pada contoh pertama bukan sekadar pilihan gaya, melainkan syarat kebenaran prediksi. Statistik praproses, misalnya rata-rata dan simpangan baku yang dipelajari StandardScaler, tersimpan di dalam objek scaler yang menjadi bagian pipeline. Apabila hanya objek LogisticRegression yang disimpan, pihak yang memuat model harus menyalin angka-angka scaler secara manual dan mengimplementasikan transformasinya sendiri. Selisih kecil pada proses salin-menyalin itu menggeser prediksi secara diam-diam tanpa error apa pun, sehingga kesalahannya justru sulit ditemukan. Menyimpan pipeline utuh membuat transformasi ikut terbawa bersama model, dan pemanggil cukup mengirim data mentah dengan bentuk yang benar.
Baris “jenis objek model : Pipeline” pada keluaran bagian pertama menegaskan perilaku ini. Objek yang dimuat menjalankan scaling lalu regresi logistik dalam satu pemanggilan predict, sama persis seperti objek aslinya. Pola yang sama berlaku untuk pipeline yang berisi ColumnTransformer maupun langkah lain, sepanjang seluruh komponennya berasal dari scikit-learn dan dapat diserialisasi.
Kesalahan umum#
Kesalahan pertama adalah menyimpan model tanpa metadata versi, lalu memuatnya kembali di lingkungan yang telah diperbarui. Gejalanya beragam, mulai dari peringatan InconsistentVersionWarning yang diabaikan sampai perilaku prediksi yang berubah tanpa pesan. Perbaikannya sudah terlihat pada contoh di atas, yaitu menyimpan versi pustaka bersama artefak dan menguncinya pada berkas kebutuhan proyek.
Kesalahan kedua adalah menyimpan model telanjang tanpa praprosesnya. Prediksi tetap keluar, tetapi datanya tidak ditransformasi dengan statistik yang sama seperti saat pelatihan, sehingga hasilnya menyimpang tanpa sinyal. Menyimpan objek pipeline utuh menghapus seluruh ruang kesalahan tersebut karena transformasi dan model bergerak sebagai satu kesatuan.
Kesalahan ketiga adalah memuat artefak lalu langsung memakainya tanpa verifikasi. Kebiasaan yang berguna adalah membandingkan prediksi atau akurasi sebelum dan sesudah pemuatan pada beberapa sampel, sebagaimana dilakukan program pertama. Pemeriksaan singkat itu menutup celah antara “berkas berhasil dibuka” dan “model yang benar telah dimuat”.
Ringkasan#
- joblib.dump menyimpan objek model ke berkas dan joblib.load memuatnya kembali, dan keduanya lebih efisien daripada pickle untuk array numpy besar.
- Artefak sebaiknya berupa dict berisi model, versi scikit-learn, dan penanda waktu, karena model tidak dijamin kompatibel antarversi pustaka.
- Pipeline utuh disimpan sebagai satu objek agar statistik praproses ikut terbawa dan inferensi cukup mengirim data mentah.
- Setiap pemuatan diverifikasi dengan membandingkan prediksi atau akurasi sebelum dan sesudahnya.
Referensi#
- Model persistence — scikit-learn documentation — Panduan resmi penyimpanan dan pemuatan model scikit-learn beserta peringatan kompatibilitas versinya.
- joblib documentation — joblib — Rujukan fungsi joblib.dump dan joblib.load yang digunakan pada seluruh contoh topik ini.
- sklearn.pipeline.Pipeline — scikit-learn documentation — Rujukan objek pipeline utuh yang disimpan sebagai satu artefak.
- sklearn.datasets.load_iris — scikit-learn documentation — Dataset iris yang digunakan pada contoh penyimpanan model.