Chapter sebelumnya menutup dengan distribusi keyakinan Bayesian atas sebuah parameter: bukan satu angka konversi, melainkan rentang beserta derajat keyakinannya. Pada chapter ini kita membawa cara berpikir itu ke ranah yang lebih luas — uncertainty quantification, seni melaporkan ketidakpastian pada setiap keluaran analisis dan prediksi model. Sebuah prediksi “besok terjual 58 gelas” tanpa keterangan rentang hampir selalu terlalu percaya diri; manajer toko yang menyiapkan stok 58 gelas akan kehabisan barang di separuh hari. Kita mulai dari peta dua sumber ketidakpastian, membedakan interval kepercayaan dari interval prediksi, membaca predict_proba sebagai ketidakpastian model klasifikasi, lalu menutup dengan prediksi kuantil yang menghasilkan interval menyesuaikan data.

Dua Sumber Ketidakpastian: Epistemic dan Aleatoric #

Semua bentuk ketidakpastian bermuara ke dua sumber yang berbeda nasibnya. Ketidakpastian epistemic berasal dari ketidaktahuan kita — data masih sedikit, model belum melihat cukup contoh, fitur penting belum terukur. Ketidakpastian aleatoric berasal dari derau bawaan masalah itu sendiri — dua pelanggan dengan profil sama tetap bisa memilih menu berbeda, dua hari bersuhu sama tetap menghasilkan penjualan berbeda.

AspekEpistemicAleatoric
Asal usulketidaktahuan model/pengamatkeacakan bawaan proses
Contohprediksi wilayah yang jarang dikunjungi pelangganselisih penjualan antar hari yang sibuk
Bisa dikurangi?ya — tambah data, perbaiki model, ukur fitur barutidak — hanya bisa dilaporkan selebar apa adanya
Penanganan praktiskumpulkan data lagi sebelum memutuskansiapkan buffer stok, rancang skenario terburuk

Pembedaan ini penting karena keduanya menuntut tindakan yang berlawanan. Ketidakpastian epistemic yang dominan berarti jawabannya adalah mengumpulkan data atau menunggu — memaksa model memberi angka pasti hanya mengarang. Ketidakpastian aleatoric yang dominan berarti tidak ada data tambahan yang bisa menolong; yang dibutuhkan adalah keputusan yang tahan terhadap sebaran, misalnya menyimpan stok untuk persentil ke-90 permintaan, bukan rata-ratanya.

Interval Kepercayaan vs Interval Prediksi #

Dua istilah ini sering tertukar padahal menjawab pertanyaan berbeda. Interval kepercayaan (confidence interval) menyatakan ketidakpastian kita tentang parameter — misalnya rata-rata penjualan harian sejati; konsep ini sudah kita dalami pada chapter Interval Kepercayaan . Interval prediksi (prediction interval) menyatakan rentang yang memuat satu observasi baru dengan tingkat keyakinan tertentu. Parameter tidak berubah-ubah sehingga intervalnya menyempit seiring data; observasi baru selalu membawa derau segar sehingga intervalnya tetap lebar.

Kita bandingkan keduanya pada 12 hari data penjualan Toko Kopi Kita:

python
import numpy as np
from scipy import stats

# 12 hari penjualan gelas kopi (data beku, deterministik)
penjualan = np.array([46, 52, 44, 58, 49, 41, 55, 47, 51, 43, 57, 48])
n = len(penjualan)
rerata = penjualan.mean()
simpangan = penjualan.std(ddof=1)
galat_baku = simpangan / np.sqrt(n)
t = stats.t.ppf(0.975, df=n - 1)

ci_rerata = rerata - t * galat_baku, rerata + t * galat_baku
pi_baru = (rerata - t * simpangan * np.sqrt(1 + 1 / n),
           rerata + t * simpangan * np.sqrt(1 + 1 / n))

print(f"Rata-rata 12 hari          : {rerata:.2f} gelas")
print(f"Simpangan baku sampel      : {simpangan:.2f}")
print(f"Interval kepercayaan 95%   : {ci_rerata[0]:.2f} - {ci_rerata[1]:.2f} gelas")
print(f"Interval prediksi 95%      : {pi_baru[0]:.2f} - {pi_baru[1]:.2f} gelas")
print(f"Lebar CI : {ci_rerata[1] - ci_rerata[0]:.2f} | Lebar PI : {pi_baru[1] - pi_baru[0]:.2f}")

Output yang Dihasilkan:

text
Rata-rata 12 hari          : 49.25 gelas
Simpangan baku sampel      : 5.50
Interval kepercayaan 95%   : 45.76 - 52.74 gelas
Interval prediksi 95%      : 36.66 - 61.84 gelas
Lebar CI : 6.98 | Lebar PI : 25.18

Mari kita telaah baris-baris pentingnya:

  1. Baris 12 (t = stats.t.ppf(0.975, df=n - 1)): kita meminta nilai t sehingga 97,5% luas distribusi-t berada di kirinya; dipakai untuk kedua sisi interval sehingga total cakupan 95%. Distribusi-t (bukan normal) dipilih karena simpangan baku pun ikut diestimasi dari sampel kecil.
  2. Baris 14-15 (ci_rerata): galat baku membagi simpangan dengan sqrt(n), sehingga interval kepercayaan rata-rata hanya selebar 6,98 gelas — makin banyak hari teramati, makin tajam dugaan kita tentang rata-rata sejati.
  3. Baris 16-17 (pi_baru): untuk satu hari baru, derau harian tidak menipis oleh jumlah data, jadi simpangan dipakai utuh dikali faktor sqrt(1 + 1/n) (faktor kecil yang mengakui estimasi rerata juga bisa meleset). Hasilnya 25,18 gelas — sekitar 3,6 kali lebar interval kepercayaan.

Salah membaca jenis interval berujung pada keputusan stok yang keliru: memakai 45,76-52,74 (interval parameter!) sebagai rentang penjualan besok membuat toko kehabisan kopi hampir setiap hari di atas rata-rata. Untuk keputusan operasional harian, interval prediksi-lah yang relevan.

predict_proba: Ketidakpastian pada Klasifikasi #

Pada klasifikasi, ketidakpastian model tersaji sebagai probabilitas lewat predict_proba — kemampuan yang sudah kita pakai sejak chapter-chapter machine learning pertama. Angka ini memadukan dua sumber ketidakpastian: model yang belum belajar cukup (epistemic) dan batas keputusan yang memang melintasi wilayah abu-abu (aleatoric). Kita latih model kecil status member dari frekuensi kunjungan 24 pelanggan:

python
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression

# 24 pelanggan: frekuensi kunjungan per bulan vs status member
frekuensi = np.array([0.5, 0.8, 1.0, 1.2, 1.5, 1.8, 2.0, 2.2, 2.5, 2.8, 3.0, 3.2,
                      3.5, 3.8, 4.0, 4.2, 4.5, 4.8, 5.0, 5.2, 5.5, 5.8, 6.0, 6.5])
member = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
                   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

model = LogisticRegression().fit(frekuensi.reshape(-1, 1), member)

pelanggan_baru = np.array([[1.0], [3.4], [6.0]])
peluang = model.predict_proba(pelanggan_baru)

hasil = pd.DataFrame({
    "kunjungan_bulan": pelanggan_baru.ravel(),
    "P(bukan member)": peluang[:, 0].round(3),
    "P(member)": peluang[:, 1].round(3),
    "prediksi": model.predict(pelanggan_baru),
})
print(hasil.to_string(index=False))

Output yang Dihasilkan:

text
 kunjungan_bulan  P(bukan member)  P(member)  prediksi
             1.0            0.985      0.015         0
             3.4            0.489      0.511         1
             6.0            0.010      0.990         1

Bedah hasilnya:

  1. Pelanggan 1,0 kunjungan: probabilitas 0,985/0,015 — nyaris pasti bukan member. Model sanggup yakin karena banyak contoh serupa di data latih.
  2. Pelanggan 3,4 kunjungan: 0,489 lawan 0,511 — praktis lempar koin. Label “member” menang tipis, tetapi keputusan berbasis angka ini sebaiknya ditunda atau ditanyakan langsung ke pelanggan; di sinilah ketidakpastian aleatoric wilayah perbatasan muncul.
  3. Pelanggan 6,0 kunjungan: 0,990 — model kembali sangat yakin. Perhatikan polanya: probabilitas ekstrem pada wilayah yang dikenalnya, probabilitas tengah pada perbatasan kelas.

Prediksi Kuantil: Interval yang Menyesuaikan Data #

Interval prediksi pada bagian sebelumnya berbentuk simetris dan selebar itu terus — padahal dunia nyata sering tidak seimbang: penjualan kopi saat cuaca sedang stabil perilakunya, saat panas terik keragamannya melebar. Prediksi kuantil menjawab dengan melatih model memperkirakan persentil tertentu dari target — konsep persentil yang sudah kita kenal di chapter Persentil dan Kuartil . Dua model dipakai sebagai batas: model persentil ke-10 sebagai batas bawah dan ke-90 sebagai batas atas, sehingga keduanya memuat 80% observasi.

Kita pakai GradientBoostingRegressor dengan loss="quantile" pada 40 hari data suhu dan penjualan:

python
import numpy as np
import pandas as pd
from sklearn.ensemble import GradientBoostingRegressor

rng = np.random.default_rng(42)

# 40 hari penjualan: gelas terjual naik dengan suhu, derau melebar saat panas
suhu = rng.uniform(22, 32, 40)
derau = rng.normal(0, 3, 40) + 1.1 * (suhu - 22)
gelas = 40 + 3.5 * (suhu - 25) + derau

def model_kuantil(alpha):
    return GradientBoostingRegressor(
        loss="quantile", alpha=alpha, n_estimators=100, random_state=42
    )

bawah = model_kuantil(0.1).fit(suhu.reshape(-1, 1), gelas)
tengah = model_kuantil(0.5).fit(suhu.reshape(-1, 1), gelas)
atas = model_kuantil(0.9).fit(suhu.reshape(-1, 1), gelas)

suhu_baru = np.array([[24.0], [28.0], [31.5]])
hasil = pd.DataFrame({
    "suhu": suhu_baru.ravel(),
    "batas_bawah_q10": bawah.predict(suhu_baru).round(1),
    "tengah_q50": tengah.predict(suhu_baru).round(1),
    "batas_atas_q90": atas.predict(suhu_baru).round(1),
})
hasil["lebar_interval"] = (hasil["batas_atas_q90"] - hasil["batas_bawah_q10"]).round(1)
print("Interval prediksi 80% (q10 sampai q90) pada tiga suhu:")
print(hasil.to_string(index=False))

tercakup = (gelas >= bawah.predict(suhu.reshape(-1, 1))) & (
    gelas <= atas.predict(suhu.reshape(-1, 1))
)
print(f"\nCakupan empiris interval pada 40 hari data: {tercakup.mean():.2f}")

Output yang Dihasilkan:

text
Interval prediksi 80% (q10 sampai q90) pada tiga suhu:
 suhu  batas_bawah_q10  tengah_q50  batas_atas_q90  lebar_interval
 24.0             38.5        40.7            47.4             8.9
 28.0             55.1        56.4            61.5             6.4
 31.5             59.3        70.6            70.9            11.6

Cakupan empiris interval pada 40 hari data: 0.80

Mari kita baca hasilnya:

  1. Baris 24-27 (tiga model terpisah): satu model per persentil — alpha=0.1, 0.5, 0.9 — masing-masing meminimalkan galat kuantil, bukan galat kuadrat rata-rata. Model alpha=0.5 memperkirakan median, lebih tahan terhadap pencilan daripada rata-rata.
  2. Lebar interval yang berubah-ubah: 6,4 gelas di suhu 28 (penjualan paling stabil) membengkak menjadi 11,6 gelas di suhu 31,5 — di wilayah panas, keragaman permintaan melebar sehingga interval ikut melapang. Interval simetris statis tidak bisa menangkap perilaku ini.
  3. Cakupan empiris 0,80: dari 40 hari data, 80% nilai nyata jatuh di antara kedua batas — persis target interval 80% (q10 ke q90). Memeriksa cakupan empiris seperti ini adalah cara cepat menilai apakah interval yang dilaporkan model bisa dipercaya.

Rangkuman #

  • Ketidakpastian epistemic (ketidaktahuan model) bisa dikurangi dengan data; ketidakpastian aleatoric (derau bawaan) hanya bisa dilaporkan — keduanya menuntut tindakan yang berbeda.
  • Interval kepercayaan menyasar parameter dan menyempit dengan sqrt(n); interval prediksi menyasar satu observasi baru dan tetap lebar — 6,98 lawan 25,18 gelas pada contoh 12 hari penjualan kita.
  • predict_proba melaporkan ketidakpastian model klasifikasi: probabilitas dekat 0,5 menandai wilayah perbatasan yang layak ditunda keputusannya, asalkan model terkalibrasi.
  • Prediksi kuantil (loss="quantile" pada GradientBoostingRegressor) menghasilkan interval adaptif yang melebar-menyesempit mengikuti keragaman lokal data, dengan cakupan empiris yang bisa diperiksa langsung.

Sejauh ini seluruh analisis kita diam-diam mengandaikan dunia berhenti bergerak: model yang dilatih hari ini diasumsikan masih sahih bulan depan. Kenyataannya perilaku pelanggan, harga, dan musim terus bergeser — prediksi yang yakin hari ini bisa diam-diam menjadi keliru tanpa kita sadari. Bagaimana mendeteksi pergeseran itu sebelum merugikan? Itulah tugas chapter berikutnya: Drift Detection .

Referensi: