Model yang sudah dilatih bernilai hanya bila dapat dipakai ulang di luar proses pelatihannya. Topik ini membahas serialisasi model, yaitu penulisan objek model beserta seluruh parameternya ke dalam berkas, dan pemuatan kembali objek tersebut di proses lain. Pembahasannya memakai pipeline scikit-learn pada dataset kanker payudara yang disimpan dengan joblib, lalu ditutup dengan kebiasaan pemberian versi pada artefak model agar model yang sedang disajikan selalu dapat dilacak.
Mengapa model perlu disimpan#
Model terlatih hanyalah objek Python di memori yang berisi parameter hasil pelatihan, misalnya koefisien regresi atau susunan pohon. Ketika proses pelatihan berakhir, objek itu hilang bersama memori prosesnya. Serialisasi memindahkan seluruh isi objek ke berkas sehingga model dapat dipindahkan ke proses lain, ke mesin lain, atau ke tahap penyajian yang berjalan berhari-hari setelah pelatihan selesai.
Pemisahan itu penting karena pelatihan dan penyajian memiliki ritme yang berbeda. Pelatihan mahal dan dilakukan jarang, sedangkan penyajian murah per prediksi dan berjalan terus-menerus, sering kali di komputer yang berbeda dari tempat pelatihan. Tanpa berkas model, setiap proses penyajian harus melatih ulang modelnya sebelum dapat menjawab satu prediksi pun.
Yang perlu disimpan juga bukan hanya modelnya. Tahap preprocessing seperti penskalaan menyimpan statistik dari data latih, misalnya rata-rata dan deviasi standar setiap fitur. Apabila statistik itu tidak ikut disimpan, penyajian akan menskalakan masukan dengan angka yang berbeda dari angka pelatihan, sehingga prediksi yang dihitungnya menyimpang diam-diam.
Menyimpan dan memuat dengan joblib#
joblib adalah pustaka serialisasi yang direkomendasikan scikit-learn untuk objek yang berisi array NumPy besar. Dua fungsinya cukup untuk seluruh pekerjaan, yaitu dump yang menulis objek ke berkas dan load yang membacanya kembali menjadi objek yang utuh. Skrip berikut melatih pipeline berisi StandardScaler dan LogisticRegression pada dataset kanker payudara, menyimpannya ke satu berkas, lalu memuatnya kembali dan membandingkan skornya.
"""Menyimpan model terlatih ke berkas dan memuatnya kembali dengan joblib."""
import os
from joblib import dump, load
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
# data latih: dataset kanker payudara bawaan scikit-learn
data = load_breast_cancer()
X_latih, X_uji, y_latih, y_uji = train_test_split(
data.data, data.target, test_size=0.25, random_state=42, stratify=data.target
)
# pipeline menyatukan penskalaan dan model agar tersimpan sebagai satu artefak
pipeline = Pipeline(
[
("skala", StandardScaler()),
("model", LogisticRegression(max_iter=5000)),
]
)
pipeline.fit(X_latih, y_latih)
# serialisasi: seluruh isi pipeline ditulis ke satu berkas di direktori kerja
NAMA_ARKIB = "model-kanker-v1.joblib"
dump(pipeline, NAMA_ARKIB)
# deserialisasi: objek beserta seluruh parameternya dimuat kembali dari berkas
model_baru = load(NAMA_ARKIB)
skor_asal = pipeline.score(X_uji, y_uji)
skor_muat = model_baru.score(X_uji, y_uji)
prediksi = model_baru.predict(X_uji[:1])
print(f"Berkas artefak : {NAMA_ARKIB}")
print(f"Ukuran berkas : {os.path.getsize(NAMA_ARKIB)} byte")
print(f"Langkah pipeline : {list(model_baru.named_steps)}")
print(f"Skor sebelum disimpan: {skor_asal:.4f}")
print(f"Skor sesudah dimuat : {skor_muat:.4f}")
print(f"Prediksi sampel baru : {prediksi[0]} ({data.target_names[prediksi[0]]})")Berkas artefak : model-kanker-v1.joblib
Ukuran berkas : 2286 byte
Langkah pipeline : ['skala', 'model']
Skor sebelum disimpan: 0.9860
Skor sesudah dimuat : 0.9860
Prediksi sampel baru : 1 (benign)Kedua skor terbaca sama persis, yaitu 0.9860 sebelum dan sesudah dimuat, karena yang dipindahkan ke berkas adalah seluruh parameter hasil pelatihan dan bukan resep untuk melatih ulang. Skor 0.9860 berarti 141 dari 143 contoh data uji diklasifikasikan benar oleh model yang telah dimuat. Ukuran berkasnya hanya 2286 byte karena modelnya kecil, sedangkan pipeline yang dimuat masih mengenali kedua langkahnya, yaitu skala dan model, sehingga penskalaan tetap dijalankan pada prediksi sampel baru.
Isi berkas joblib bukan teks yang dapat dibaca, melainkan citra biner dari objek beserta seluruh parameternya. Berkas semacam ini hanya sah dibuka melalui joblib.load, karena isinya tidak dapat disunting maupun diperiksa seperti berkas teks. Untuk model berukuran besar, dump juga menerima argumen compress yang memampatkan isi berkas dengan mengorbankan waktu simpan dan muat yang sedikit lebih lama.
Memberi versi pada artefak model#
Berkas model adalah produk yang terus berubah setiap kali model dilatih ulang. Apabila setiap pelatihan menimpa berkas yang sama, tidak ada cara untuk mengetahui versi mana yang sedang disajikan, dan tidak ada cara untuk kembali ke versi sebelumnya ketika versi baru ternyata lebih buruk. Kebiasaan yang menjaga kejernihannya adalah memberi nomor versi atau tanggal pada nama berkas, tidak pernah menimpa artefak lama, dan menyertakan catatan metadata di sampingnya.
| Catatan pada artefak | Contoh |
|---|---|
| Nama berkas dengan versi | model-kanker-v3.joblib |
| Dataset dan pemisahan yang dipakai | breast cancer, random_state=42 |
| Skor data uji saat pelatihan | 0.9860 |
| Versi pustaka saat pelatihan | scikit-learn 1.5.2 |
Dengan kebiasaan itu, menaikkan penyajian dari v3 ke v4 menjadi keputusan yang sadar setelah v4 diuji, dan penurunan kembali ke v3 dimungkinkan karena berkasnya masih ada. Catatan metadata menjawab pertanyaan yang hampir selalu muncul saat inspeksi, misalnya dataset apa yang melatih versi ini dan angka ujinya berapa. Pencatatan sekecil apa pun lebih baik daripada ingatan, karena ingatan tentang versi model cepat tertukar.
Tempat penyimpanan catatannya fleksibel, tetapi harus menempel pada artefaknya. Berkas teks kecil dengan nama berpasangan seperti model-kanker-v3.txt sudah cukup untuk proyek kecil, sedangkan proyek yang lebih besar mencatatnya pada log pelatihan yang menyertai setiap pelatihan. Yang penting hanya satu, yaitu siapa pun yang menemukan berkas model juga dapat menemukan catatannya tanpa bertanya.
Kesalahan umum#
- Menyimpan estimator tanpa tahap preprocessing. Model yang dimuat kemudian menerima masukan mentah, padahal pelatihan memakai masukan yang sudah diskalakan, sehingga prediksinya menyimpang. Perbaikannya dengan menyimpan pipeline utuh sebagai satu artefak.
- Menimpa berkas artefak lama dengan nama yang sama. Versi yang sedang disajikan tidak dapat dilacak dan tidak dapat dikembalikan. Perbaikannya dengan nomor versi pada nama berkas dan larangan menimpa artefak yang sudah terpakai.
- Memuat artefak di lingkungan pustaka yang berbeda tanpa pemeriksaan. Bentuk internal objek scikit-learn dapat berubah antarversi. Perbaikannya dengan mencatat versi pustaka pada metadata dan menyamakannya saat memuat.
- Menyimpan artefak yang memuat kelas buatan sendiri tanpa kode definisinya. Berkas serialisasi hanya menyimpan rujukan kelas, bukan isi kelasnya, sehingga pemuatan gagal dengan error impor di lingkungan lain. Simpan hanya objek pustaka standar pada artefak, sedangkan kelas buatan sendiri diletakkan di dalam kode proyek.
- Memuat artefak tanpa pemeriksaan singkat. Berkas yang terpotong karena proses penyalinan gagal tetap ada, tetapi pemuatannya memunculkan error ketika penyajian sudah berjalan. Muat artefak versi baru dan jalankan satu prediksi percobaan sebelum penyajian diganti.
Ringkasan#
- Serialisasi memindahkan objek model beserta parameternya ke berkas sehingga pelatihan dan penyajian dapat berjalan terpisah.
joblib.dumpdanjoblib.loadmenyimpan serta memuat pipeline scikit-learn lengkap dengan statistik preprocessing-nya.- Skor model sebelum disimpan dan sesudah dimuat identik karena yang dipindahkan adalah parameternya, bukan pelatihan ulang.
- Pemberian versi pada nama berkas dan pencatatan metadata membuat model yang sedang disajikan dapat dilacak dan dikembalikan.
Referensi#
- Model persistence — scikit-learn — Panduan resmi menyimpan dan memuat model scikit-learn.
- Persistence — joblib
— Dokumentasi
joblib.dumpdanjoblib.loadbeserta catatan efisiensinya pada array NumPy. - sklearn.pipeline.Pipeline — scikit-learn — Dokumentasi pipeline yang menyatukan preprocessing dan model dalam satu objek.