Alarm pemantauan minggu keempat telah berbunyi: proporsi prediksi churn melonjak ke 0,65, padahal kode model tidak berubah sebaris pun. Penjelasan yang paling sering benar adalah data masukannya yang berubah — pelanggan yang datang bulan ini bukan lagi pelanggan yang dikenal model saat pelatihan. Pergeseran semacam ini disebut data drift, dan tugas chapter ini adalah sisi operasionalnya: membandingkan distribusi fitur terkini terhadap periode acuan, menetapkan ambang yang sederhana, lalu menurunkan status pemantauan menjadi keputusan — lanjut pantau, evaluasi ulang, atau jeda prediksi. Pendalaman statistiknya, termasuk pembedaan data drift dan concept drift, sudah kita bahas pada chapter Drift Detection ; di sini kita fokus pada meja kerja tim operasional.

Kerja Forensik Sisi Operasional #

Ketika alarm proporsi prediksi berbunyi, tim menjalankan urutan pemeriksaan yang tetap. Pertama, ambil distribusi fitur pada periode acuan — masa ketika model dilatih dan performanya terukur sehat. Kedua, ambil distribusi fitur yang sama pada periode terkini. Ketiga, bandingkan keduanya per fitur dengan ambang perubahan relatif; bila rata-rata bergeser terlalu jauh, fitur itu ditandai DRIFT. Keempat — dan inilah yang membedakan babak operasional dari sekadar analisis — status tersebut diterjemahkan menjadi keputusan dengan pemilik yang jelas.

Mengapa mean dan simpangan baku saja sudah cukup sebagai lapisan pertama? Karena keduanya murah dihitung, terbaca semua orang di tim, dan menangkap sebagian besar pergeseran yang berarti dalam praktik. Uji statistik yang lebih peka tetap punya tempatnya untuk kasus yang meragukan — pokok bahasan chapter Drift Detection — tetapi keputusan jeda atau retraining sebaiknya bisa diambil dari tabel yang dimengerti pengelola kedai, bukan hanya oleh statistikawan.

Membandingkan Distribusi Fitur terhadap Periode Acuan #

Kasus kita: tiga puluh transaksi dari periode acuan melawan dua belas transaksi minggu terkini, dua fitur yang sama dengan model churn. Data terkini memperlihatkan pola yang masuk akal secara bisnis — harga menu naik awal bulan, dan yang masih rajin datang memang pelanggan paling setia.

python
import numpy as np
import pandas as pd

rng = np.random.default_rng(42)

fitur_acuan = pd.DataFrame({
    "periode": "acuan",
    "kunjungan": rng.integers(1, 15, 30),
    "belanja": rng.integers(50, 350, 30),
})
fitur_terkini = pd.DataFrame({
    "periode": "terkini",
    "kunjungan": rng.integers(1, 8, 12),
    "belanja": rng.integers(180, 450, 12),
})
fitur = pd.concat([fitur_acuan, fitur_terkini], ignore_index=True)

ringkas = fitur.groupby("periode").agg(
    rata_kunjungan=("kunjungan", "mean"),
    std_kunjungan=("kunjungan", "std"),
    rata_belanja=("belanja", "mean"),
    std_belanja=("belanja", "std"),
).round(1)
print(ringkas.to_string())
print()

ambang_persen = 10.0
baris = []
for fitur_nama in ["kunjungan", "belanja"]:
    a = fitur.loc[fitur["periode"] == "acuan", fitur_nama]
    b = fitur.loc[fitur["periode"] == "terkini", fitur_nama]
    perubahan = (b.mean() - a.mean()) / a.mean() * 100
    baris.append({
        "fitur": fitur_nama,
        "mean_acuan": round(a.mean(), 1),
        "mean_terkini": round(b.mean(), 1),
        "std_acuan": round(a.std(), 1),
        "std_terkini": round(b.std(), 1),
        "perubahan_persen": round(perubahan, 1),
        "status": "DRIFT" if abs(perubahan) > ambang_persen else "stabil",
    })
tabel_drift = pd.DataFrame(baris)
print(tabel_drift.to_string(index=False))
print()

jumlah_drift = int((tabel_drift["status"] == "DRIFT").sum())
if jumlah_drift == 0:
    keputusan = "LANJUTKAN PEMANTAUAN: distribusi masih mirip data latih"
elif jumlah_drift == 1:
    keputusan = "KUMPULKAN LABEL TERBARU & JADWALKAN EVALUASI ULANG"
else:
    keputusan = "JEDA PREDIKSI OTOMATIS & MINTA TINJAUAN TIM"
print(f"fitur berstatus DRIFT: {jumlah_drift}")
print("keputusan:", keputusan)

Output yang Dihasilkan:

text
         rata_kunjungan  std_kunjungan  rata_belanja  std_belanja
periode                                                          
acuan               8.2            3.7         201.0         86.4
terkini             4.3            2.1         312.7         69.5

    fitur  mean_acuan  mean_terkini  std_acuan  std_terkini  perubahan_persen status
kunjungan         8.2           4.3        3.7          2.1             -47.4  DRIFT
  belanja       201.0         312.7       86.4         69.5              55.6  DRIFT

fitur berstatus DRIFT: 2
keputusan: JEDA PREDIKSI OTOMATIS & MINTA TINJAUAN TIM

Mari kita telaah bagian-bagian pentingnya:

  1. Baris 6-16 (dua potret masa): kedua DataFrame memakai generator acak yang sama dari seed 42; rentangnya sengaja berbeda — kunjungan terkini dibatasi 1-7 kali dan belanja 180-450 — meniru data kedai yang berubah perilaku. concat menyatukannya menjadi satu tabel dengan kolom penanda periode.
  2. Baris 18-24 (tabel pemantauan ringkas): groupby("periode") plus agg menghasilkan persis tabel yang dikenal dari chapter Drift Detection — mean dan simpangan baku tiap fitur per periode. Dari sini saja mata sudah menangkap: rata-rata belanja 201 ribu menjadi 313 ribu.
  3. Baris 27-43 (pembanding berambang): untuk tiap fitur, perubahan dihitung relatif terhadap rata-rata acuan ((b - a) / a * 100), lalu dibandingkan dengan ambang 10% yang berlaku untuk nilai absolut — pergeseran turun pun dihitung. Kunjungan turun 47,4% dan belanja naik 55,6%, keduanya jauh melampaui ambang.
  4. Baris 46-54 (status menjadi keputusan): jumlah fitur berstatus DRIFT menentukan jalur tindakan — nol berarti cukup dipantau, satu berarti kumpulkan label dan evaluasi, dua atau lebih berarti prediksi otomatis ditunda sampai tim sepakat.

Makna bisnisnya jelas terbaca: pelanggan terkini datang lebih jarang (rata-rata 4,3 kali sebulan dari 8,2) tetapi berbelanja jauh lebih besar per kunjungan. Prediksi churn dari model lama — yang belajar “jarang datang berarti berisiko” — menjadi tidak bisa dipercaya pada populasi baru ini; menjeda prediksi otomatis lebih aman daripada melanjutkan sambil berharap.

Dari Status ke Keputusan dan Penanggung Jawabnya #

Aturan keputusan pada blok di atas sengaja sederhana, tetapi tabel tindakan di baliknya perlu ditulis dan disepakati sebelum alarm berbunyi — bukan sesudahnya. Versi kami untuk kedai:

Sinyal pemantauanTindakanSiapa memutuskan
Semua fitur stabil, proporsi prediksi normallanjutkan pemantauan rutinotomatis
Satu fitur DRIFT, proporsi prediksi masih wajarkumpulkan label terbaru, evaluasi model pada golden setdata scientist
Dua fitur atau lebih DRIFT, atau proporsi keluar rentangjeda prediksi otomatis, proses manual sementaradata scientist + pengelola kedai
Akurasi golden set turun di bawah ambang layananjadwalkan pelatihan ulang (chapter berikutnya)data scientist

Kolom terakhir adalah bagian yang paling sering dilupakan: keputusan “jeda” mempengaruhi orang yang memakai hasil prediksi setiap hari, jadi pemilik proses bisnis wajib duduk di meja putus. Alarm yang tidak jalan di atas kertas — siapa melakukan apa — hanyalah angka berwarna.

Rangkuman #

  • Sisi operasional deteksi perubahan berupa empat langkah tetap: distribusi acuan, distribusi terkini, pembanding berambang per fitur, lalu penerjemahan status menjadi keputusan berpemilik.
  • Mean dan simpangan baku per periode adalah lapisan pertama yang murah dan terbaca semua orang; uji statistik lanjutan menunggu di chapter Drift Detection untuk kasus yang meragukan.
  • Pada kasus kita, kunjungan turun 47,4% dan belanja naik 55,6% — dua fitur DRIFT sekaligus, sehingga keputusannya jeda prediksi otomatis dan tinjauan tim.
  • Tabel tindakan — sinyal, tindakan, penanggung jawab — wajib disepakati sebelum alarm berbunyi; cuplikan kecil diperlakukan sebagai alasan menyelidik, bukan vonis.

Prediksi otomatis dijeda, penyebabnya ditemukan, dan langkah berikutnya sudah jelas: model harus belajar dari perilaku pelanggan yang baru. Namun mengganti model produksi bukan pekerjaan semalam — ada prosedur aman berisi juara bertahan, kandidat penantang, dan jalan pulang. Kita susun pada chapter berikutnya: Memperbarui Model .

Referensi: