Deployment dimulai jauh sebelum server menyala: dari memisahkan hasil pelatihan menjadi artefak yang bisa dipindahkan, diaudit, dan dimuat ulang tanpa menjalankan ulang pelatihan. Skrip src/latih_model.py mempraktikkan pemisahan tersebut dengan menulis tiga berkas — bobot (model.pt), konfigurasi (config.json), dan metrik (metrik.json) — ke direktori sementara /tmp/dl_deploy_demo. Konsep pembagian artefak inilah yang dibahas pada chapter Menyimpan Model untuk Produksi ; bobot saja tidak cukup karena arsitektur dan aturan preprocessing harus menyertainya.

Konfigurasi sebagai Kontrak #

Proyek ini tidak menyimpan konstanta penting tersebar di dalam kode; seluruh ketentuan hidup di config/config.json:

json config/config.json
{
  "nama_model": "mlp-digit-mini",
  "versi": "1.0.0",
  "arsitektur": {
    "fitur": 64,
    "sembunyi": [32, 16],
    "kelas": 10
  },
  "preprocessing": {
    "normalisasi": 16.0,
    "rentang_masukan": [0.0, 16.0]
  },
  "ambang_keyakinan": 0.9,
  "metadata": {
    "dataset": "sklearn.datasets.load_digits (1797 gambar 8x8)",
    "pelatihan": {
      "benih": 42,
      "epoch": 40,
      "batch": 32,
      "optimizer": "Adam",
      "learning_rate": 0.001
    },
    "perangkat": "cpu",
    "pembuat": "proyek deployment-model-deep-learning"
  }
}

Berkas ini menjadi kontrak tiga pihak sekaligus: fungsi bangun_model membangun arsitektur MLP 64-32-16-10 dari blok arsitektur, endpoint API di Bagian 2 memvalidasi masukan memakai rentang_masukan, dan ambang ambang_keyakinan menentukan kapan respons prediksi ditandai kurang meyakinkan. Mengubah satu nilai di konfigurasi otomatis mengubah perilaku seluruh tahap tanpa menyentuh kode — konstanta tidak lagi tersembunyi di dalam logika program, dan itulah sebabnya struktur proyek ini memakai folder config/, bukan data/.

Pelatihan dan Penulisan Artefak #

Sebelum pelatihan, fungsi siapkan_data menyiapkan dataset dengan benih tetap:

python src/latih_model.py — fungsi siapkan_data
def siapkan_data():
    """Dataset digits terbagi latih/validasi dengan benih tetap."""
    data = load_digits()
    X = data.data.astype("float32") / 16.0   # normalisasi 0..16 -> 0..1
    y = data.target.astype("int64")
    X_latih, X_val, y_latih, y_val = train_test_split(
        X, y, test_size=0.25, random_state=BENIH, stratify=y)
    return (X_latih, y_latih), (X_val, y_val)

Dua detail menentukan keandalan artefak. Pembagian random_state=42 dengan stratify=y menjaga 450 sampel validasi tetap berimbang sepuluh kelasnya setiap kali skrip dijalankan, sehingga akurasi validasi bisa dibandingkan antar eksekusi. Normalisasi / 16.0 bukan angka bebas — nilainya sama dengan preprocessing.normalisasi di config.json, dan konsistensi ini yang nanti diulang oleh endpoint /predict di Bagian 2; layanan yang preprocessing-nya tidak sama dengan pelatihan akan menghasilkan prediksi meleset.

Fungsi latih_dan_simpan kemudian menjalankan pelatihan standar (Adam, learning rate dari konfigurasi, 40 epoch) lalu menulis ketiga artefak:

python src/latih_model.py — penulisan artefak
model.eval()

metrik = {
    "akurasi_latih": round(float(akurasi_latih), 4),
    "akurasi_validasi": round(float(akurasi_val), 4),
    "jumlah_parameter": sum(p.numel() for p in model.parameters()),
}

direktori.mkdir(parents=True, exist_ok=True)
torch.save(model.state_dict(), direktori / "model.pt")
shutil.copyfile(JALUR_KONFIG, direktori / "config.json")
(direktori / "metrik.json").write_text(
    json.dumps(metrik, indent=2) + "\n", encoding="utf-8")

Tiga keputusan pada potongan ini patut dibedah. model.eval() dipanggil sebelum evaluasi agar perilaku layer cocok dengan mode inferensi. torch.save(model.state_dict(), ...) hanya menyimpan bobot, bukan seluruh objek — arsitektur dibangun ulang dari config.json oleh pemuat, pola yang direkomendasikan chapter Penyimpanan dan Pemuatan Model . Terakhir, metrik.json ikut disimpan sehingga endpoint /health nanti bisa melaporkan akurasi validasi tanpa menghitung ulang.

Jalankan dari folder proyek:

bash
python3 src/latih_model.py

Output yang Dihasilkan:

text
== pelatihan model digit mini ==
arsitektur      : 64 -> 32 -> 16 -> 10 (MLP + ReLU)
data latih      : 1347 gambar
data validasi   : 450 gambar
epoch / batch   : 40 / 32
akurasi latih   : 0.9852
akurasi validasi: 0.9511
parameter       : 2778

== artefak di /tmp/dl_deploy_demo ==
model.pt    : 13757 byte
config.json : 556 byte
metrik.json : 88 byte
config.json disalin dari config/ bundle; versi 1.0.0, ambang keyakinan 0.9

Model sederhana 2778 parameter mencapai akurasi validasi 0.9511 (akurasi latih 0.9852 — selisih kecil yang menandakan belum terjadi overfitting berlebih). Angka ini menjadi tolok ukur: layanan yang kita bangun di bagian-bagian berikutnya wajib mempertahankan akurasi yang sama, karena tiap tahap deployment yang benar tidak boleh mengubah perilaku model.

Tiga artefak kini berdiri di /tmp/dl_deploy_demo. Bagian berikutnya memuatnya sekali ke dalam proses server lalu membuka dua endpoint: pemeriksaan kesehatan dan prediksi.