Mengevaluasi model secara jujur: cross-validation, metrik klasifikasi (accuracy, precision, recall, F1, AUC), metrik regresi, dan penerjemahan metrik teknis menjadi dampak bisnis — dilengkapi praktik evaluasi menyeluruh

Setelah di episode 10 kita membangun feature pipeline, pada episode ini kita menjawab pertanyaan paling penting dalam machine learning: "apakah model ini benar-benar baik?". Evaluasi yang keliru adalah sumber kesalahan paling mahal — model yang tampak hebat di notebook bisa gagal total di lapangan karena metrik yang dipilih tidak sesuai masalah.
Mengapa evaluasi layak dihabiskan banyak waktu? Karena semua keputusan mengalir darinya: apakah model lanjut ke produksi, apakah fitur dipertahankan, apakah threshold disetel ulang. Dan lebih dalam lagi: metrik teknis (accuracy, AUC) hanyalah perantara — yang benar-benar diinginkan bisnis adalah dampak (uang dihemat, churn turun). Episode ini membangun jembatan antara keduanya.
Train/test split sekali saja terlalu bergantung pada irisan data. Cross-validation menguji model pada beberapa lipatan data dan merata-ratakan hasilnya — estimasi performa yang jauh lebih stabil.
import pandas as pd
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
df = pd.read_csv("telco_churn.csv")
X = df.drop(columns=["churn"])
y = df["churn"]
pipe = Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(max_iter=1000)),
])
scores = cross_val_score(pipe, X, y, cv=5, scoring="accuracy")
print("accuracy per fold:", scores.round(3))
print("mean ± std:", round(scores.mean(), 3), "±", round(scores.std(), 3))cross_val_score secara internal melakukan preprocessing per-fold — menghindari data leakage. Mean memberi estimasi performa, std memberi kepercayaan: std kecil berarti model stabil terhadap variasi data.
Untuk data tidak seimbang, gunakan StratifiedKFold (default di cross_val_score untuk klasifikasi) — ia menjaga proporsi kelas di tiap lipatan. Untuk data time series, cross-validation biasa bocor ke masa depan — episode 15 akan memakai TimeSeriesSplit.
Accuracy sering menyesatkan. Untuk churn dengan 18% positive, model "selalu tidak churn" mendapat accuracy 82% — tanpa menangkap satu pun pelanggan berisiko. Metrik berikut memberi gambaran lebih jujur:
| Metrik | Menjawab | Kapan Penting |
|---|---|---|
| Precision | Dari yang diprediksi positif, berapa yang benar? | False positive mahal (misal spam) |
| Recall | Dari yang benar-benar positif, berapa yang tertangkap? | False negative mahal (misal fraud) |
| F1 | Keseimbangan precision & recall | Data tidak seimbang |
| AUC | Kemampuan memisahkan kelas di semua threshold | Perbandingan model secara umum |
from sklearn.metrics import classification_report, roc_auc_score
y_pred = pipe.predict(X_test)
y_proba = pipe.predict_proba(X_test)[:, 1]
print(classification_report(y_test, y_pred))
print("AUC:", round(roc_auc_score(y_test, y_proba), 3))Untuk model churn, tanyakan: apa konsekuensi salah prediksi? Jika tim retention hanya bisa menghubungi 1.000 customer/bulan, kita butuh precision tinggi (yang dihubungi benar-benar berisiko). Jika tiap customer churn yang terlewat = kehilangan besar, kita butuh recall tinggi (jangan sampai ada yang terlewat). Trade-off ini disetel lewat threshold — dan itulah metrik berikut.
Model memprediksi probabilitas; default threshold 0.5 tidak selalu optimal:
from sklearn.metrics import precision_recall_curve
precision, recall, thresholds = precision_recall_curve(y_test, y_proba)
proba_thr = thresholds[abs(precision - recall).argmin()]
print("threshold seimbang:", round(proba_thr, 3))
y_business = (y_proba > 0.7).astype(int) # contoh prioritas precisionMenurunkan threshold menaikkan recall (lebih banyak tertangkap) dan menurunkan precision; menaikkan threshold sebaliknya. Pilih titik yang paling cocok dengan biaya bisnis.
Important
Evaluasi selalu di test set yang belum pernah terlihat, atau lewat cross-validation. Mengulang-ulang tuning di test set sampai AUC naik adalah bentuk p-hacking (episode 3) — test set jadi bocor. Idealnya: tuning di validation fold, evaluasi final di test set yang hanya dijalankan sekali.
Untuk target numerik, metrik utamanya:
| Metrik | Arti | Catatan |
|---|---|---|
| MAE | Rata-rata selisih absolut | Unit asli, mudah dipahami |
| RMSE | Akar rata-rata kuadrat error | Memberatkan error besar |
| R² | Proporsi variansi yang dijelaskan | Skala 0-1, relatif terhadap baseline |
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import numpy as np
print("MAE :", round(mean_absolute_error(y_test, y_pred), 3))
print("RMSE:", round(mean_squared_error(y_test, y_pred, squared=False), 3))
print("R² :", round(r2_score(y_test, y_pred), 3))RMSE lebih sensitif ke outlier (kuadrat memperbesar error besar); MAE lebih tahan. Pilih sesuai pertanyaan bisnis: apakah satu kesalahan besar lebih berbahaya dari banyak kesalahan kecil?
Metrik teknis tidak bercerita ke bisnis. Jembatannya adalah simulasi dampak:
Contoh: model churn dengan threshold 0.7 (precision 0.65)
- Dari 10.000 customer/bulan, model menandai 1.200 sebagai berisiko
- 780 benar-benar churn → tim retention menghubungi 1.200
- Anggap 30% berhasil dicegah: 234 customer terselamatkan
- Nilai rata-rata customer: Rp 3 juta/tahun → dampak ≈ Rp 702 juta/tahunFormula inilah yang dipresentasikan ke stakeholder — bukan accuracy atau AUC. Ini mengubah pembicaraan dari "model 0.85" menjadi "potensi menghemat Rp 700 juta", dan inilah esensi data science berorientasi bisnis. Episode 17 akan memperdalam cara menyampaikannya.
| Pitfall | Dampak | Solusi |
|---|---|---|
| Accuracy untuk data tidak seimbang | Angka menipu | Precision/recall/F1/AUC |
| Tuning berulang di test set | Test bocor, evaluasi palsu | Validation set terpisah |
| Mengabaikan std cross-validation | Estimasi tidak stabil | Laporkan mean ± std |
| Threshold 0.5 selalu | Salah untuk kelas jarang | Tuning berbasis biaya |
| Hanya metrik teknis | Bisnis tidak tergerak | Terjemahkan ke dampak |
Inti yang harus dibawa pulang:
Di episode 12 selanjutnya kita akan membahas experiment tracking — mencatat setiap eksperimen model secara reproduktif dengan MLflow, supaya kalian tidak pernah kehilangan jejak model terbaik. Sampai jumpa di episode 12!