Tabel perbandingan pada chapter Membandingkan Model sudah jujur, tetapi keputusan akhir tidak bisa diserahkan kepada satu baris tabel. Selisih rata-rata yang tipis, kandidat dengan keunggulan di metrik yang berbeda, dan pertimbangan di luar angka — biaya, kemudahan penjelasan, risiko — semuanya menuntut sebuah kerangka keputusan. Pada chapter penutup Section ini kita susun kerangka itu sebagai kriteria berlapis, terapkannya pada tiga kandidat churn Toko Kopi Kita, lalu tuntaskan dengan dua langkah yang sering dilewatkan: melatih ulang model terpilih pada seluruh data dan mendokumentasikan alasan pilihannya. Chapter ini ditutup rangkuman alur tiga belas chapter evaluasi, dari pembagian data pertama sampai keputusan model final.
Empat Dimensi yang Ditimbang Berbarengan #
Chapter Memilih Model pada Section Dasar Machine Learning memakai empat pertimbangan — interpretabilitas, ukuran data, kecepatan, akurasi — untuk menyaring keluarga model di awal proyek. Di ujung proses evaluasi, pertimbangan yang sama kembali muncul dengan wujud yang jauh lebih konkret, karena kini angka-angkanya sudah ada di tangan. Kita susun ulang menjadi empat dimensi penilaian:
| Dimensi | Pertanyaan kunci | Pada kasus churn kita |
|---|---|---|
| Performa | Apakah metrik utamanya memenuhi syarat minimal bisnis? | Recall minimal 0,75 — menangkap sedikitnya 3 dari 4 pelanggan yang akan pergi |
| Interpretabilitas | Bisakah alasan tiap prediksi dijelaskan ke pengelola kafe? | Koefisien regresi logistik dan aturan pohon terbaca langsung; gabungan 100 pohon tidak |
| Biaya | Berapa biaya melatih, melayani prediksi, dan merawatnya? | Regresi logistik dilatih dalam hitungan milidetik; 100 pohon memakan puluhan kali lipat waktu pada data yang sama |
| Risiko | Seberapa stabil antar lipatan dan adilkah antar kelompok pelanggan? | RandomForest paling bervariasi (simpangan 0,113); performa per kelompok pelanggan belum ikut diperiksa pada perbandingan sebelumnya |
Empat dimensi itu jarang berpihak pada kandidat yang sama, dan justru di situlah letak pekerjaan kita: menyusun urutan prioritas yang bisa dipertanggungjawabkan, sehingga keputusan tidak bergantung pada selera. Cara memeriksa keadilan antar kelompok sudah kita pegang dari chapter Analisis Kesalahan Model ; sisanya adalah urutan menyaringnya — itulah kriteria keputusan berlapis.
Kriteria Keputusan Berlapis #
Kriteria berlapis bekerja seperti saringan berurutan, dan urutannya bukan selera: lapisan pertama adalah syarat minimal performa yang diturunkan dari biaya bisnis, lapisan kedua menyaring yang bertahan dengan kesederhanaan dan biaya, lapisan ketiga menjadi pemecah seri. Tabel berikut merinci ketiganya:
| Lapisan | Saringan | Dasar pertimbangan |
|---|---|---|
| 1 — Syarat minimal | Recall CV ≥ 0,75 | Biaya kehilangan pelanggan melampaui biaya program retensi |
| 2 — Kesederhanaan dan biaya | Bila selisih rerata lebih kecil daripada simpangan, pilih yang paling sederhana | Keunggulan yang belum meyakinkan tidak layak dibayar dengan kompleksitas |
| 3 — Pemecah seri | Interpretabilitas, kemudahan monitoring | Model yang bisa dijelaskan lebih mudah dirawat |
Satu keputusan masih perlu diambil sebelum kode dijalankan: metrik penentunya. Chapter sebelumnya membandingkan kandidat dengan akurasi sebagai bahasa umum; untuk memutuskan, lensa berganti ke recall, karena yang menentukan nasib program retensi adalah pelanggan yang berhasil diselamatkan. Kode berikut menjalankan lapisan pertama secara eksplisit:
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
rng = np.random.default_rng(42)
n = 60
kunjungan = rng.integers(1, 15, n)
belanja = rng.integers(50, 350, n)
skor = 0.8 * (8 - kunjungan) + 0.02 * (belanja - 180) + rng.normal(0, 3, n)
churn = (skor > np.quantile(skor, 0.6)).astype(int)
X = np.column_stack([kunjungan, belanja])
kandidat = {
"LogisticRegression": LogisticRegression(max_iter=1000),
"DecisionTree (max_depth=3)": DecisionTreeClassifier(max_depth=3, random_state=42),
"RandomForest (100 pohon)": RandomForestClassifier(n_estimators=100, random_state=42),
}
syarat_recall = 0.75 # minimal tangkap 3 dari 4 pelanggan yang akan pergi
baris = []
for nama, model in kandidat.items():
s = cross_val_score(model, X, churn, cv=5, scoring="recall")
baris.append({"model": nama,
"rerata_recall": f"{s.mean():.3f}",
"simpangan": f"{s.std():.3f}",
"lolos_syarat": s.mean() >= syarat_recall})
tabel = pd.DataFrame(baris)
print(tabel.to_string(index=False))
print()
print("kandidat lolos lapisan 1:", tabel.loc[tabel["lolos_syarat"], "model"].tolist())Output yang Dihasilkan:
model rerata_recall simpangan lolos_syarat
LogisticRegression 0.790 0.128 True
DecisionTree (max_depth=3) 0.700 0.179 False
RandomForest (100 pohon) 0.710 0.156 False
kandidat lolos lapisan 1: ['LogisticRegression']Mari kita telaah bagian-bagian pentingnya:
- Baris 22 (
syarat_recall = 0.75): ambang bisnis ditulis sebagai variabel bernama, bukan sebagai angka yang tersembunyi di dalam perbandingan — pembaca kode tahu syarat ini datang dari luar kode. - Baris 26-30 (pengukuran):
cross_val_scoredenganscoring="recall"menghasilkan lima skor recall pada lipatan yang sama seperti chapter sebelumnya; kolomlolos_syaratmenguji rata-ratanya terhadap ambang. - Baris 35 (penyaringan):
tabel.loc[tabel["lolos_syarat"], "model"]mengambil nama kandidat yang lolos — satu baris kode menjadi protokol keputusan yang bisa diaudit.
Hasilnya tegas: hanya LogisticRegression yang lolos (recall rata-rata 0,790), sementara DecisionTree (0,700) dan RandomForest (0,710) tersaring di lapisan pertama. Recall 1,000 milik DecisionTree pada satu split di chapter sebelumnya kini terbaca apa adanya — sempurna pada satu undian, rata-rata hanya 0,700 pada lima undian bergilir. Karena hanya satu kandidat bertahan, lapisan kedua dan ketiga tidak perlu bekerja; bila dua kandidat lolos, keduanya akan dibandingkan kesederhanaannya, dan interpretabilitas menentukan bila masih seimbang. Perhatikan pula bahwa keputusan ini konsisten di semua dimensi: kandidat yang lolos kebetulan juga yang paling sederhana dan termurah dilatih. Pada data 60 baris, pola seperti ini lazim — kompleksitas baru mulai terbayar ketika data bertambah besar.
Finalisasi: Melatih Ulang pada Seluruh Data #
Yang kita pilih sebenarnya bukan sebuah objek model, melainkan sebuah prosedur: jenis model beserta hyperparameter dan cara menyiapkan datanya. Model-model per lipatan yang dilatih cross-validation adalah alat ukur yang dibuang begitu pengukuran selesai. Model final dilatih dari awal pada seluruh 60 baris — data latih dan data uji digabung kembali — karena setiap baris adalah informasi berharga dan fase evaluasi sudah rampung.
Konsekuensi finalisasi ini perlu diucapkan jujur: model final tidak lagi memiliki data uji yang bersih, karena seluruh baris sudah dipakai untuk melatihnya. Estimasi performa yang kita laporkan tetap berasal dari cross-validation (recall 0,790 ± 0,128), bukan dari menilai model final pada data yang ikut membentuknya.
import numpy as np
from sklearn.linear_model import LogisticRegression
rng = np.random.default_rng(42)
n = 60
kunjungan = rng.integers(1, 15, n)
belanja = rng.integers(50, 350, n)
skor = 0.8 * (8 - kunjungan) + 0.02 * (belanja - 180) + rng.normal(0, 3, n)
churn = (skor > np.quantile(skor, 0.6)).astype(int)
X = np.column_stack([kunjungan, belanja])
model_final = LogisticRegression(max_iter=1000).fit(X, churn)
print("koefisien kunjungan :", round(float(model_final.coef_[0][0]), 3))
print("koefisien belanja :", round(float(model_final.coef_[0][1]), 3))
print("intersep :", round(float(model_final.intercept_[0]), 3))
print()
pelanggan_baru = np.array([
[2, 300], # jarang datang, belanja besar
[12, 90], # rajin datang, belanja kecil
[7, 180], # di tengah-tengah
])
peluang_churn = model_final.predict_proba(pelanggan_baru)[:, 1]
for fitur, p in zip(pelanggan_baru, peluang_churn):
print(f"kunjungan={fitur[0]:>2}, belanja={fitur[1]:>3} -> peluang churn {p:.3f}")Output yang Dihasilkan:
koefisien kunjungan : -0.68
koefisien belanja : 0.012
intersep : 2.101
kunjungan= 2, belanja=300 -> peluang churn 0.989
kunjungan=12, belanja= 90 -> peluang churn 0.007
kunjungan= 7, belanja=180 -> peluang churn 0.395Mari kita telaah bagian-bagian pentingnya:
- Baris 12 (
model_final = ...): tidak adatrain_test_split— seluruh data dipakai melatih model final; inilah satu-satunya momen dalam siklus ini ketika kita melatih pada semua baris. - Baris 14-16 (koefisien dan intersep): tiga angka ini adalah seluruh isi model. Koefisien kunjungan -0,68 berarti setiap tambahan satu kunjungan per bulan menurunkan peluang berhenti; koefisien belanja +0,012 berarti pelanggan dengan belanja bulanan besar sedikit lebih condong berhenti — pada data ini, tipe pelanggan yang berbelanja besar namun jarang datang memang lebih sering pergi.
- Baris 19-27 (prediksi pelanggan baru):
predict_probamengembalikan peluang tiap kelas, dan indeks[:, 1]mengambil peluang kelas churn. Pelanggan dengan kunjungan 2 dan belanja 300 mencatat peluang 0,989 — kandidat utama program retensi; pelanggan rajin dengan belanja kecil nyaris aman (0,007); pelanggan di tengah (0,395) menunggu informasi lain sebelum ditindak.
Koefisien yang terbaca itulah buah dari dimensi interpretabilitas: kepada pengelola kafe kita bisa menjelaskan, “pelanggan yang jarang datang adalah yang paling berisiko, apa pun besar belanjanya”, lengkap dengan angkanya. Prediksi yang berbentuk peluang juga memberi tim keleluasaan menetapkan ambang tindakan sendiri — misalnya menindaklanjuti semua pelanggan di atas 0,8 — sesuai pembahasan ambang keputusan pada chapter Precision, Recall, dan F1-Score .
Mendokumentasikan Pilihan Model #
Keputusan yang tidak didokumentasikan akan ditanya ulang — oleh rekan tim, oleh auditor, atau oleh kita sendiri enam bulan kemudian. Dokumentasi minimal berbentuk kartu model: kandidat yang diadu, protokol evaluasi, hasilnya, alasan keputusan, dan keterbatasan yang diketahui.
Kartu Model — Churn Pelanggan Toko Kopi Kita
------------------------------------------------------------
Tanggal disetujui : 2026-01-15
Data : 60 pelanggan; fitur kunjungan & belanja; 24 churn
Kandidat yang diadu : LogisticRegression, DecisionTree (max_depth=3),
RandomForest (100 pohon)
Protokol evaluasi : 5-fold cross-validation (StratifiedKFold),
random_state=42, metrik utama recall
Hasil : LogisticRegression 0.790 ± 0.128 (lolos syarat
0.750); DecisionTree 0.700; RandomForest 0.710
Keputusan : LogisticRegression — satu-satunya yang lolos syarat
minimal; paling sederhana dan termurah dilatih
Model final : dilatih ulang pada seluruh 60 baris
Keterbatasan : performa per kelompok pelanggan belum diperiksa;
ambang tindakan ditetapkan terpisah dari modelKartu satu halaman ini menyimpan seluruh keputusan penting: mengapa metriknya recall, dari mana angka 0,750 berasal, apa hasil tiap kandidat, dan apa yang belum diperiksa. Baris keterbatasan sama pentingnya dengan baris hasil — baris itulah yang menjadi daftar pemeriksaan berikutnya. Untuk proyek yang lebih besar, pencatatan semacam ini biasa diotomatisasi dengan alat pelacakan eksperimen seperti MLflow.
Alur Evaluasi dari Split hingga Pemilihan #
Section ini dibuka dengan satu pertanyaan: bagaimana membagi data agar kepercayaan pada model punya dasar yang jujur. Tiga belas chapter kemudian, jawabannya tersusun menjadi tiga tahap yang saling menopang:
| Tahap | Chapter di dalamnya | Yang kita dapatkan |
|---|---|---|
| Fondasi pengukuran | Pembagian data latih-uji, metrik regresi, metrik klasifikasi, confusion matrix, precision/recall/F1, ROC dan AUC | Bahasa untuk membaca performa model apa pun |
| Protokol validasi yang jujur | Cross-validation, stratified sampling, hyperparameter tuning, data imbalanced, analisis kesalahan | Prosedur yang tidak menipu dirinya sendiri |
| Keputusan | Membandingkan model, memilih model terbaik | Dari angka menuju keputusan yang dipertanggungjawabkan |
Ketiga tahap itu membentuk satu kebiasaan kerja: ukur dengan metrik yang sesuai biaya kesalahan, validasi dengan prosedur yang menghormati data, lalu putuskan dengan kriteria yang ditetapkan lebih dulu. Mulai dari cara membagi data pada chapter pertama sampai kartu model pada halaman ini, seluruh peralatan Section ini bekerja untuk satu tujuan — memastikan model yang kita terjunkan layak dipercaya, dan kepercayaan itu bisa dijelaskan kepada orang lain.
Rangkuman #
- Keputusan akhir menimbang empat dimensi sekaligus — performa, interpretabilitas, biaya, risiko — dan keempatnya jarang berpihak pada kandidat yang sama.
- Kriteria berlapis menyaring berurutan: syarat performa minimal dari biaya bisnis, kesederhanaan dan biaya di antara yang lolos, interpretabilitas sebagai pemecah seri.
- Pada kasus kita hanya LogisticRegression lolos syarat recall 0,75; kandidat yang lolos sekaligus paling sederhana dan termurah — pola yang lazim pada data kecil.
- Finalisasi berarti melatih ulang prosedur terpilih pada seluruh data; estimasi performa yang jujur tetap berasal dari cross-validation, bukan dari model final.
- Kartu model mendokumentasikan kandidat, protokol, hasil, keputusan, dan keterbatasan — keputusan yang tidak didokumentasikan akan ditanya ulang.
Evaluasi dan validasi model kini tuntas: kita tahu membagi data, memilih metrik, memvalidasi tanpa menipu diri sendiri, dan memutuskan dengan kriteria yang jelas. Perjalanan berikutnya menghadapi data yang melanggar asumsi paling dasar yang selama ini kita pakai — bahwa setiap baris berdiri sendiri. Pada data deret waktu, urutan justru membawa makna: penjualan hari ini bergantung pada kemarin, dan pembagian data acak akan merusak urutan itu. Section Analisis Deret Waktu dimulai dari sana.