Teorema Bayes

Pembaruan keyakinan dan rumus termasyhurnya.

Daftar isi

Teorema Bayes membalik arah probabilitas bersyarat, yaitu dari peluang bukti apabila hipotesis benar menuju peluang hipotesis apabila bukti teramati. Topik ini membahas bentuk rumusnya, pengaruh dasar frekuensi (base rate) terhadap penafsiran hasil tes, serta penerapannya pada filter spam Naive Bayes. Setelah topik ini dipahami, hasil tes positif dari alat uji yang akurat dapat ditafsirkan dengan benar karena dasar frekuensinya ikut dihitung, dan filter spam dapat dibangun dari hitungan frekuensi kata yang sederhana.

Membalik arah probabilitas bersyarat#

Topik Aturan Probabilitas menghitung P(A∣B)P(A \mid B) dari kejadian yang sudah diketahui, sedangkan banyak persoalan nyata memerlukan arah yang berlawanan. Pada penyaring spam, frekuensi korpus dengan mudah memberikan P(kata kunci∣spam)P(\text{kata kunci} \mid \text{spam}), yaitu seberapa sering kata tersebut muncul pada pesan spam, tetapi yang dibutuhkan penyaring adalah P(spam∣kata kunci)P(\text{spam} \mid \text{kata kunci}). Kedua nilai tersebut tidak sama, dan perbedaannya dapat sangat besar. Peluang jalan menjadi basah apabila hujan jauh lebih besar daripada peluang hujan apabila jalan basah, sebab jalan dapat basah karena sebab lain. Menghitung langsung P(spam∣kata kunci)P(\text{spam} \mid \text{kata kunci}) dari data memang mungkin, tetapi bukti yang jarang muncul menyisakan sedikit sampel, sehingga hitungannya tidak stabil. Teorema Bayes menyelesaikan persoalan ini dengan menggunakan nilai yang mudah diketahui untuk menghitung nilai yang sulit diukur.

Teorema Bayes#

Titik awalnya adalah definisi probabilitas bersyarat yang diterapkan dari dua arah. Irisan kejadian yang sama dapat ditulis sebagai P(H∩E)=P(H∣E) P(E)P(H \cap E) = P(H \mid E)\, P(E) maupun P(H∩E)=P(E∣H) P(H)P(H \cap E) = P(E \mid H)\, P(H). Menyamakan kedua bentuk tersebut lalu membaginya dengan P(E)P(E) menghasilkan rumus yang dicari.

P(H∣E)=P(E∣H) P(H)P(E) P(H \mid E) = \frac{P(E \mid H)\, P(H)}{P(E)}

Setiap suku memiliki nama tetap. Nilai P(H)P(H) adalah prior, yaitu keyakinan atas hipotesis HH sebelum bukti diperhitungkan. Nilai P(E∣H)P(E \mid H) adalah likelihood, yaitu seberapa mungkin bukti EE muncul apabila HH benar, sedangkan P(E)P(E) berfungsi sebagai penyebut penormal yang menjumlahkan kemungkinan bukti muncul dari seluruh hipotesis. Hasil akhir P(H∣E)P(H \mid E) disebut posterior, yaitu keyakinan yang sudah diperbarui oleh bukti. Diagram berikut merangkum alur pembaruannya.

Keyakinan awalprior P(H)Bukti dari dataP(E | H)Keyakinan baruposterior P(H | E)P(H | E) = P(E | H) × P(H) ÷ P(E)
Alur pembaruan keyakinan dari prior menuju posterior melalui teorema Bayes

Pembilang P(E∣H)×P(H)P(E \mid H) \times P(H) menimbang seberapa besar hipotesis menjelaskan bukti, sedangkan penyebut memastikan posterior seluruh hipotesis berjumlah satu. Rumus ini berlaku berulang kali, karena posterior dari satu pengamatan dapat menjadi prior bagi pengamatan berikutnya.

Dasar frekuensi dan hasil tes#

Pertimbangkan tes penyakit langka dengan sensitivitas 0,990{,}99, yaitu P(positif∣sakit)P(\text{positif} \mid \text{sakit}), dan laju positif palsu 0,050{,}05, yaitu P(positif∣sehat)P(\text{positif} \mid \text{sehat}). Dasar frekuensinya adalah P(sakit)=0,01P(\text{sakit}) = 0{,}01, sehingga peluang sakit bagi orang yang mendapat hasil positif dihitung sebagai berikut.

P(sakit∣positif)=0,99×0,010,99×0,01+0,05×0,99≈0,167 P(\text{sakit} \mid \text{positif}) = \frac{0{,}99 \times 0{,}01}{0{,}99 \times 0{,}01 + 0{,}05 \times 0{,}99} \approx 0{,}167

Hasilnya sekitar 16,7 persen, jauh dari dugaan bahwa tes berakurasi tinggi pasti menghasilkan keyakinan yang tinggi. Penyebabnya adalah jumlah orang sehat yang jauh lebih banyak, sehingga sebagian kecil positif palsu tetap lebih besar daripada seluruh positif sejati. Skrip berikut menghitung nilai tersebut sekaligus menunjukkan pengaruh dasar frekuensi terhadap posterior.

python tes-medis.py
"""Teorema Bayes pada hasil tes medis dengan nilai yang sudah diketahui."""
sensitivitas = 0.99        # P(tes positif | sakit)
dasar = 0.01               # dasar frekuensi: P(sakit)
positif_palsu = 0.05       # laju positif palsu: P(tes positif | sehat)

p_positif = sensitivitas * dasar + positif_palsu * (1 - dasar)
p_sakit_positif = sensitivitas * dasar / p_positif
print("P(tes positif)         :", round(p_positif, 4))
print("P(sakit | tes positif) :", round(p_sakit_positif, 4))
print()
for dasar_b in [0.001, 0.01, 0.1, 0.5]:
    posterior = sensitivitas * dasar_b / (sensitivitas * dasar_b + positif_palsu * (1 - dasar_b))
    print(f"dasar {dasar_b:>6} -> posterior {posterior:.4f}")
text Keluaran
P(tes positif)         : 0.0594
P(sakit | tes positif) : 0.1667

dasar  0.001 -> posterior 0.0194
dasar   0.01 -> posterior 0.1667
dasar    0.1 -> posterior 0.6875
dasar    0.5 -> posterior 0.9519

Tabel keluaran menunjukkan bahwa rumusnya tetap, tetapi keyakinan akhir mengikuti dasar frekuensi. Pada penyakit yang hanya menyerang satu dari seribu orang, hasil positif hampir pasti positif palsu, sedangkan pada populasi yang separuhnya sakit, hasil positif hampir pasti benar. Simulasi populasi berikut menghitung ulang kasus dasar 0,010{,}01 tanpa rumus, cukup dengan penghitungan orang.

python Contoh: simulasi 100.000 orang dengan benih tetap
import numpy as np

rng = np.random.default_rng(42)
n = 100_000
sakit = rng.random(n) < 0.01                     # 1% populasi sakit
uji_sakit = rng.random(n) < 0.99                 # sensitivitas
uji_sehat = rng.random(n) < 0.05                 # laju positif palsu
positif = np.where(sakit, uji_sakit, uji_sehat)
print("perkiraan P(tes positif)         :", round(positif.mean(), 4))
print("perkiraan P(sakit | tes positif) :", round(sakit[positif].mean(), 4))
print("positif sejati dari orang sakit  :", int((positif & sakit).sum()))
print("positif palsu dari orang sehat   :", int((positif & ~sakit).sum()))
text Keluaran
perkiraan P(tes positif)         : 0.059
perkiraan P(sakit | tes positif) : 0.1752
positif sejati dari orang sakit  : 1033
positif palsu dari orang sehat   : 4864

Pada keluaran simulasi, dari 5897 orang yang mendapat hasil positif, hanya 1033 yang benar-benar sakit, sehingga perbandingannya kembali ke sekitar 17 persen. Kesesuaian angka rumus dan angka simulasi menegaskan bahwa teorema Bayes hanyalah penghitungan frekuensi yang ditulis ulang. Kecenderungan mengabaikan dasar frekuensi saat menilai hasil tes bahkan memiliki nama tersendiri, yaitu kesalahan dasar frekuensi (base rate fallacy).

Filter spam Naive Bayes#

Filter spam Naive Bayes menerapkan teorema Bayes dengan satu asumsi penyederhanaan, yaitu setiap kata muncul secara saling bebas dalam kelasnya (naive berarti naif). Asumsi tersebut jarang benar secara literal, tetapi cukup baik untuk klasifikasi dan membuat peluang sebuah pesan dihitung sebagai perkalian peluang kata per kata.

P(spam∣k1,…,kn)  ∝  P(spam)×∏i=1nP(ki∣spam) P(\text{spam} \mid k_1, \dots, k_n) \;\propto\; P(\text{spam}) \times \prod_{i=1}^{n} P(k_i \mid \text{spam})

Tanda ∝\propto menyatakan proporsionalitas, karena penyebut penormal yang sama berlaku untuk kelas spam dan bukan spam, sehingga cukup dengan membandingkan pembilangnya. Kata yang belum pernah muncul pada kelas tertentu diberi peluang kecil yang tidak nol melalui perataan satu (add-one smoothing), sehingga satu kata asing tidak meniadakan seluruh hasil kali. Skrip berikut melatih filter pada korpus delapan pesan dan menguji tiga pesan baru.

python naive-bayes-spam.py
"""Filter spam Naive Bayes pada korpus kecil dengan asumsi kemandirian kata."""
import numpy as np

korpus = [
    ("menang hadiah gratis klik sekarang", True),
    ("gratis undian hadiah menang", True),
    ("klik link gratis hadiah", True),
    ("gratis tempat parkir kantor", False),
    ("jadwal piket kantor minggu depan", False),
    ("notulen rapat kantor terlampir", False),
    ("jadwal rapat kantor hari senin", False),
    ("hasil rapat kantor bulan lalu", False),
]
spam = np.array([label for _, label in korpus])

def P(kata, label):
    """P(kata muncul | label) dengan perataan satu (add-one smoothing)."""
    baris = spam == label
    muncul = np.array([kata in teks for teks, _ in korpus])[baris].sum()
    return (muncul + 1) / (baris.sum() + 2)

def klasifikasi(teks_baru):
    kata_baru = teks_baru.split()
    skor_spam = np.prod([P(k, True) for k in kata_baru]) * spam.mean()
    skor_sehat = np.prod([P(k, False) for k in kata_baru]) * (1 - spam.mean())
    label = "spam" if skor_spam > skor_sehat else "bukan spam"
    posterior = round(float(skor_spam / (skor_spam + skor_sehat)), 4)
    return label, posterior

print(klasifikasi("menang hadiah gratis"))
print(klasifikasi("jadwal rapat kantor"))
print(klasifikasi("gratis tempat rapat kantor"))
text Keluaran
('spam', 0.9753)
('bukan spam', 0.0224)
('bukan spam', 0.0876)

Dua pesan pertama dinilai tegas sesuai pola korpusnya. Pesan ketiga justru menarik, karena memuat kata “gratis” tetapi tetap dinilai bukan spam dengan posterior 0,08760{,}0876. Tiga kata kantor mendominasi hasil kali likelihood-nya, sehingga satu kata pancingan tidak cukup membalik keputusan. Perilaku ini menunjukkan cara Naive Bayes menimbang bukti secara proporsional, bukan menghitung kata pemicu satu per satu.

Di mana hal ini ditemui dalam kode#

Klasifikasi Naive Bayes tersedia pada hampir semua library machine learning, dan filter spam penyedia surel merupakan penerapannya yang paling lama bertahan. Pola pembaruan yang sama muncul pada uji A/B, yaitu perbandingan konversi dua versi halaman yang dihitung sebagai posterior dan terus diperbarui setiap data baru masuk. Sistem deteksi anomali juga menggunakan teorema Bayes dengan hipotesis “normal” melawan “tidak wajar”, dan buktinya berupa ukuran seperti frekuensi permintaan per menit. Pada kasus-kasus tersebut, rumusnya selalu sama, sedangkan yang berubah hanyalah definisi bukti dan hipotesisnya.

Aspek paling berguna untuk kode sehari-hari adalah pembaruan bertahap. Apabila data masuk sedikit demi sedikit, posterior hari ini cukup disimpan dan dijadikan prior untuk batch berikutnya, sehingga rumus diterapkan berulang tanpa menyimpan seluruh data lama. Cara kerja ini menjelaskan mengapa banyak sistem pelaporan statistik hanya menyimpan hitungan agregat, sebab hitungan tersebut sudah memuat semua informasi yang dibutuhkan rumus Bayes. Penalaran probabilistik semacam ini menjadi fondasi bagi topik Variabel Acak dan Distribusi yang membahas model peluang secara lebih lengkap.

Ringkasan#

  • Teorema Bayes P(H∣E)=P(E∣H) P(H)P(E)P(H \mid E) = \frac{P(E \mid H)\, P(H)}{P(E)} mengubah peluang bukti terhadap hipotesis menjadi peluang hipotesis terhadap bukti.
  • Suku-sukunya bernama prior sebagai keyakinan awal, likelihood sebagai kesesuaian bukti, dan posterior sebagai keyakinan yang diperbarui, dengan P(E)P(E) sebagai penyebut penormal.
  • Dasar frekuensi menentukan hasil akhirnya, sehingga tes dengan sensitivitas tinggi tetap dapat menghasilkan posterior rendah apabila kejadian yang diuji jarang terjadi.
  • Filter spam Naive Bayes mengalikan likelihood per kata dengan asumsi kemandirian, menggunakan perataan satu untuk kata yang belum pernah terlihat, dan membandingkan skor antarkelas.

Referensi#