Server yang sehat bukan berarti model yang sehat. Latensi P95 rendah, error rate nol, memori stabil — semua itu bisa sempurna sementara prediksi yang dilayani sudah meleset sejak minggu lalu. Monitoring kinerja model memisahkan dua hal yang sering dicampur: kesehatan infrastruktur (yang dijawab metrik sistem) dan kesehatan keputusan (yang hanya bisa dijawab bila label kebenaran tersedia). Chapter ini fokus pada yang kedua — membangun monitor akurasi jendela waktu yang menghadapi kenyataan paling menyulitkan: label tiba terlambat.
Infrastruktur vs Kualitas #
Metrik infrastruktur sudah kita bangun di chapter Monitoring Model Produksi — latensi, error rate, distribusi prediksi — dan sumber latensinya dibedah di Optimasi Latensi . Metrik kualitas berbeda secara fundamental: ia membutuhkan label ground truth yang tidak tersedia pada saat prediksi dibuat. Konsekuensinya adalah ground truth delay — jeda antara prediksi dibuat dan kebenarannya diketahui:
- Sistem rekomendasi: keputusan beli pengguna terlihat berhari-hari kemudian.
- Deteksi fraud: sebagian laporan penipuan baru masuk setelah siklus tagihan.
- Diagnosa medis: hasil pemeriksaan penentu tiba berminggu-minggu kemudian.
Selama jeda itu, kualitas model tidak bisa dihitung langsung; yang tersedia hanyalah proksi tanpa label — distribusi prediksi dan skor keyakinan (materi chapter Monitoring Model Produksi ) serta deteksi drift dari chapter Data dan Model Drift .
Metrik, Sumber Data, dan Ambang #
| Metrik | Sumber data | Ambang umum |
|---|---|---|
| akurasi jendela (berlabel) | prediksi + label terlambat | turun > 5% dari baseline |
| latensi P95 | pengukuran tiap request | > 100-200 ms sesuai SLA |
| error rate infrastruktur | log server | > 1% |
| distribusi kelas prediksi | prediksi tersimpan | geser proporsi > 0.15 |
| skor keyakinan rata-rata | output model | turun tajam dari baseline |
| metrik bisnis (konversi, retensi) | analitik produk | turun > segmen pembanding |
Metrik bisnis menempati posisi khusus: ia paling lambat bergerak tetapi paling penting — turunnya konversi adalah gejala yang dirasakan pengguna, bukan hanya dilihat tim. Metrik teknis berfungsi sebagai peringatan dini yang lebih cepat.
Contoh Teruji: Monitor Akurasi dengan Label Terlambat #
Berkas monitor_akurasi.py mensimulasikan tujuh jendela arus prediksi. Label setiap jendela tiba saat jendela berikutnya berjalan — akurasi jendela t baru bisa dihitung pada jendela t+1. Dua jendela di tengah sengaja diburukkan, dan alert hanya boleh berbunyi setelah dua pelanggaran berturut-turut:
"""Monitoring kinerja model: akurasi jendela waktu + alert ambang.
Arus prediksi dibagi per jendela (300 request). Label ground truth
baru tiba satu jendela kemudian — akurasi jendela t dihitung saat
jendela t+1 berjalan. Alert hanya terkirim bila akurasi berada di
bawah ambang selama dua jendela berturut-turut (penangkal flapping).
"""
import numpy as np
N_PER_JENDELA = 300
AMBANG_AKURASI = 0.90
PELANGGARAN_PERLU = 2 # berapa jendela berturut-turut sebelum alert
# peluang prediksi benar per jendela — dua jendela buruk di tengah
P_BENAR = [0.95, 0.94, 0.96, 0.93, 0.72, 0.75, 0.95]
def main():
rng = np.random.default_rng(42)
label_tunda = None # (nomor jendela, jumlah prediksi benar)
pelanggaran = 0
alert_terkirim = False
riwayat = []
print(f"ambang akurasi : {AMBANG_AKURASI}")
print(f"jendela berturut-turut sebelum alert : {PELANGGARAN_PERLU}")
print(f"request per jendela : {N_PER_JENDELA}\n")
for t, p_benar in enumerate(P_BENAR, start=1):
jumlah_benar = rng.binomial(N_PER_JENDELA, p_benar)
print(f"jendela {t}: {N_PER_JENDELA} prediksi baru dibuat")
if label_tunda is not None:
j, benar_j = label_tunda
akurasi = benar_j / N_PER_JENDELA
if akurasi >= AMBANG_AKURASI:
status = "OK"
pelanggaran = 0
else:
status = "DI BAWAH AMBANG"
pelanggaran += 1
riwayat.append((j, akurasi))
print(f" label jendela {j} tiba -> akurasi {akurasi:.3f} "
f"[{status}] (pelanggaran beruntun: {pelanggaran})")
if (pelanggaran >= PELANGGARAN_PERLU
and not alert_terkirim):
alert_terkirim = True
print(f" ALERT: akurasi < {AMBANG_AKURASI} selama "
f"{pelanggaran} jendela -> periksa drift, "
"siapkan evaluasi ulang")
label_tunda = (t, jumlah_benar)
# label jendela terakhir tiba setelah arus berhenti
j, benar_j = label_tunda
akurasi = benar_j / N_PER_JENDELA
riwayat.append((j, akurasi))
status = "OK" if akurasi >= AMBANG_AKURASI else "DI BAWAH AMBANG"
print(f" label jendela {j} tiba -> akurasi {akurasi:.3f} [{status}]")
print("\n== ringkasan riwayat akurasi ==")
for j, akurasi in riwayat:
tanda = "#" * int(akurasi * 20)
print(f"jendela {j}: {akurasi:.3f} {tanda}")
if alert_terkirim:
print("status akhir: alert terkirim — perlu tindak lanjut")
else:
print("status akhir: sehat, tidak ada alert")
if __name__ == "__main__":
main()Output yang Dihasilkan:
ambang akurasi : 0.9
jendela berturut-turut sebelum alert : 2
request per jendela : 300
jendela 1: 300 prediksi baru dibuat
jendela 2: 300 prediksi baru dibuat
label jendela 1 tiba -> akurasi 0.940 [OK] (pelanggaran beruntun: 0)
jendela 3: 300 prediksi baru dibuat
label jendela 2 tiba -> akurasi 0.943 [OK] (pelanggaran beruntun: 0)
jendela 4: 300 prediksi baru dibuat
label jendela 3 tiba -> akurasi 0.947 [OK] (pelanggaran beruntun: 0)
jendela 5: 300 prediksi baru dibuat
label jendela 4 tiba -> akurasi 0.923 [OK] (pelanggaran beruntun: 0)
jendela 6: 300 prediksi baru dibuat
label jendela 5 tiba -> akurasi 0.757 [DI BAWAH AMBANG] (pelanggaran beruntun: 1)
jendela 7: 300 prediksi baru dibuat
label jendela 6 tiba -> akurasi 0.760 [DI BAWAH AMBANG] (pelanggaran beruntun: 2)
ALERT: akurasi < 0.9 selama 2 jendela -> periksa drift, siapkan evaluasi ulang
label jendela 7 tiba -> akurasi 0.953 [OK]
== ringkasan riwayat akurasi ==
jendela 1: 0.940 ##################
jendela 2: 0.943 ##################
jendela 3: 0.947 ##################
jendela 4: 0.923 ##################
jendela 5: 0.757 ###############
jendela 6: 0.760 ###############
jendela 7: 0.953 ###################
status akhir: alert terkirim — perlu tindak lanjutMari kita telaah kode di atas baris per baris:
- Baris 11-13 (tiga konstanta kebijakan): seluruh perilaku monitor ditentukan tiga angka — ambang akurasi 0.90, dua jendela berturut-turut sebelum alert, dan 300 request per jendela. Monitoring yang sehat selalu bisa menjawab: berapa ambangnya, dan apa yang terjadi saat terlampaui.
- Baris 16-17 (
P_BENAR): peluang benar per jendela sebagai data — jendela 5 dan 6 bernilai 0.72 dan 0.75, dua jendela bermasalah berturut-turut.rng.binomialmengubah peluang menjadi jumlah benar nyata, lengkap dengan derau sampel. - Baris 21 (
label_tunda): kunci simulasi label terlambat. Setiap jendela menyimpan jumlah benarnya, tetapi baru dievaluasi ketika jendela berikutnya berjalan — struktur yang sama dengan sistem produksi yang menghitung ulang metrik saat batch label tiba. - Baris 33-44 (evaluasi + pelanggaran beruntun): akurasi jendela sebelumnya dihitung dan dibandingkan ambang.
pelanggarandireset ke nol setiap akurasi sehat — hanya pelanggaran berturut-turut yang terakumulasi. Inilah penangkal flapping: satu jendela buruk karena variasi normal tidak cukup untuk membangunkan siapa pun. - Baris 45-51 (alert sekali): bendera
alert_terkirimmemastikan alert tercetak sekali pada pencapaian kondisi, bukan berulang setiap jendela setelahnya. Alert yang berbunyi terus-menerus akan diabaikan — fenomena kelelahan alarm yang sama seperti notifikasi yang selalu kita skip. - Baris 53-67 (riwayat + ringkasan): riwayat akurasi dicetak dengan batang sederhana; dua jendela buruk terlihat jelas lebih pendek. Status akhir menyebutkan alert terkirim dan tindak lanjutnya.
Perhatikan kronologi pada keluaran: jendela 5 buruk (0.757) tetapi alert belum berbunyi — pelanggaran beruntun baru satu. Label jendela 6 tiba (0.760), pelanggaran mencapai dua, barulah ALERT tercetak. Lalu label jendela 7 tiba dengan akurasi 0.953 dan status kembali sehat. Monitor tidak bereaksi berlebihan, tetapi juga tidak membiarkan dua jendela buruk lewat tanpa kabar.
Akurasi yang terpantau memberi kita bukti berjalan bahwa model berkualitas — tetapi bukti sesaat tidak cukup untuk menjawab pertanyaan yang datang dari luar tim: “model yang membuat keputusan enam bulan lalu itu dibangun dari apa, oleh siapa, dan masihkah catatannya utuh?” Chapter berikutnya, Reproducibility dan Audit , membangun jejak yang tidak bisa diubah tanpa bekas.