Model yang dilatih hanya berguna jika bisa dipakai kembali tanpa mengulang training. Melatih ulang model setiap kali aplikasi start itu boros; lebih buruk lagi, hasil training ulang bisa berbeda dari model yang sudah tervalidasi. Solusinya adalah serialization: menyimpan objek model terlatih ke file, lalu memuatnya kembali di lingkungan produksi. Pada chapter ini kita melakukan round-trip nyata dengan pickle, memahami risiko kompatibilitas versi, dan menerapkan pola metadata sidecar agar model tersimpan tidak menjadi kotak hitam.
Round-Trip Model dengan pickle #
Modul pickle dari standard library bisa menyerialisasi hampir semua objek Python, termasuk model scikit-learn. Kita latih model k-NN pada dataset iris, simpan, muat kembali, lalu buktikan keduanya memprediksi hal yang sama:
import pickle
import numpy as np
from sklearn.datasets import load_iris
from sklearn.neighbors import KNeighborsClassifier
iris = load_iris()
X, y = iris.data, iris.target
model = KNeighborsClassifier(n_neighbors=5).fit(X, y)
with open("model_iris.pkl", "wb") as berkas:
pickle.dump(model, berkas)
with open("model_iris.pkl", "rb") as berkas:
model_dimuat = pickle.load(berkas)
prediksi_asli = model.predict(X[:5])
prediksi_dimuat = model_dimuat.predict(X[:5])
print("Prediksi model asli :", prediksi_asli)
print("Prediksi model muat :", prediksi_dimuat)
print("Identik:", np.array_equal(prediksi_asli, prediksi_dimuat))Output yang Dihasilkan:
Prediksi model asli : [0 0 0 0 0]
Prediksi model muat : [0 0 0 0 0]
Identik: TrueMari kita bedah kode di atas:
- Baris 13 (
model = KNeighborsClassifier(...).fit(X, y)): model dilatih sekali di sesi ini; pada praktik nyata, training bisa memakan menit hingga jam. - Baris 15-16 (
pickle.dump(model, berkas)): seluruh isi objek model, termasuk data latih yang disimpan k-NN, ditulis ke filemodel_iris.pkldalam format biner. Mode"wb"wajib karena isinya biner, bukan teks. - Baris 18-19 (
pickle.load(berkas)): objek dibangun ulang dari file, siap dipakai tanpa memanggilfit()lagi. Prediksinya identik dengan model asli, dibuktikannp.array_equal()yang mengembalikanTrue.
Untuk model berukuran besar yang menampung array numpy banyak (misalnya random forest atau model dengan data latih besar), paket joblib yang terpasang bersama scikit-learn lebih efisien: joblib.dump(model, "model.joblib") dan joblib.load("model.joblib") memakai API yang sama tetapi menangani array besar lebih cepat dan hemat memori.
Bahaya Kompatibilitas Versi #
File pickle bukan format model portabel. File pickle adalah rekaman struktur objek Python secara harfiah; untuk dibuka, pemuat harus punya class yang sama persis di lokasi memori yang setara, dan versi scikit-learn yang berbeda bisa mengubah struktur internal model. Ketika model dibuat dengan scikit-learn 1.5 lalu dimuat di lingkungan scikit-learn 0.24, scikit-learn akan menampilkan InconsistentVersionWarning, dan pada kasus struktur yang jauh berbeda, pemuatan gagal dengan error AttributeError atau ModuleNotFoundError karena atribut atau module lama sudah tidak ada.
Konsekuensinya tegas: file .pkl hanya bisa dijamin tampil semestinya pada kombinasi Python dan scikit-learn yang sama dengan saat training. Pendekatan yang lebih portabel untuk pertukaran antar framework adalah format terbuka seperti ONNX, yang menyimpan komputasi model sebagai graf tanpa terikat struktur class Python; sayangnya tidak semua model scikit-learn didukung konversinya. Untuk kebutuhan section ini, aturan mainnya sederhana: simpan versi, jaga versi.
Pola Metadata Sidecar #
Karena file pickle tidak menyimpan konteks, kita buat sendiri konteksnya: file JSON kecil di samping file model yang mencatat versi library, daftar fitur, daftar kelas, dan tanggal training:
import json
import sklearn
metadata = {
"file_model": "model_iris.pkl",
"sklearn_version": sklearn.__version__,
"fitur": list(iris.feature_names),
"kelas": list(iris.target_names),
"tanggal_training": "2025-06-15",
}
with open("model_iris.json", "w") as berkas:
json.dump(metadata, berkas, indent=2)
print(json.dumps(metadata, indent=2))Output yang Dihasilkan:
{
"file_model": "model_iris.pkl",
"sklearn_version": "1.5.2",
"fitur": [
"sepal length (cm)",
"sepal width (cm)",
"petal length (cm)",
"petal width (cm)"
],
"kelas": [
"setosa",
"versicolor",
"virginica"
],
"tanggal_training": "2025-06-15"
}File JSON ini adalah sidecar: mudah dibaca manusia, mudah dibaca program, dan tidak terikat versi Python. Nilai "sklearn_version": "1.5.2" berasal dari atribut sklearn.__version__ pada mesin pelatih, jadi angka ini selalu jujur, bukan hasil ketikan manual. Daftar fitur menjadi kontrak input: skrip prediksi bisa memeriksa urutan dan nama kolom sebelum memanggil model.predict().
Skrip Load-and-Predict #
Gabungan keduanya menghasilkan skrip prediksi yang defensif dan bisa dijalankan utuh setiap kali dibutuhkan:
import json
import pickle
import numpy as np
import sklearn
with open("model_iris.json") as berkas:
metadata = json.load(berkas)
if metadata["sklearn_version"] != sklearn.__version__:
raise RuntimeError("Versi scikit-learn berbeda; latih ulang model")
with open("model_iris.pkl", "rb") as berkas:
model = pickle.load(berkas)
contoh_baru = np.array([[5.1, 3.5, 1.4, 0.2]])
prediksi = model.predict(contoh_baru)[0]
print(f"Prediksi untuk contoh baru: {metadata['kelas'][prediksi]}")Output yang Dihasilkan:
Prediksi untuk contoh baru: setosaSkrip ini memuat metadata lebih dulu, memeriksa versi scikit-learn sebelum menyentuh file pickle, lalu menerjemahkan angka prediksi (0) menjadi nama kelas (setosa) memakai metadata. Jika lingkungan produksi kelak memakai versi berbeda, RuntimeError gagal cepat alih-alih menghasilkan prediksi senyap yang salah.
Keamanan: Jangan Unpickle Sembarang File #
Memuat file pickle berarti mengeksekusi kode arbitrer yang tertanam di dalamnya. Serangan umumnya: file .pkl jahat yang dipalsukan sebagai “model pretrained” di forum atau repositori publik. Batasi pemuatan pickle hanya pada file yang kita buat sendiri atau dari sumber yang benar-benar dipercaya; untuk file dari pihak ketiga, verifikasi checksum atau muat di sandbox terisolasi.
Dengan model yang bisa disimpan, dimuat, dan diverifikasi, fondasi terakhir sudah siap: membawa model tersebut ke hadapan pengguna lewat endpoint HTTP, yang kita kerjakan pada chapter Pengenalan Deployment Model.