TL;DR
Confusion matrix adalah tabel 2x2 yang ngebandingin tebakan model sama kenyataan, isinya true positive, false positive, true negative, dan false negative. Dari empat angka itu lahir akurasi, presisi, dan recall yang masing-masing jawab pertanyaan bisnis berbeda. Di data timpang kayak deteksi fraud, akurasi bisa menyesatkan dan presisi plus recall yang nentuin keputusan.
Confusion matrix adalah tabel 2x2 yang ngebandingin tebakan model sama kenyataan.
Dari empat angka di dalamnya lahir akurasi, presisi, dan recall. Tiga metrik itu sering dihafal rumusnya tapi jarang dihubungin ke rupiah.
Aku pakai satu kasus deteksi transaksi mencurigakan di dompet digital, dan di akhir kamu bakal lihat selisih Rp 40 juta yang muncul cuma dari geser satu angka ambang.
Confusion matrix adalah tabel yang nunjukin berapa banyak tebakan model yang benar dan salah, dipecah per kelas. Empat selnya: true positive (ditebak positif dan memang positif), false positive (ditebak positif padahal bukan), true negative (ditebak negatif dan memang negatif), dan false negative (ditebak negatif padahal positif).
Nama "confusion" datang dari tujuannya: nunjukin kelas mana yang paling sering ketuker sama kelas lain.
Satu angka akurasi nggak bisa ngasih informasi itu. Tabelnya bisa.
Sebuah dompet digital lokal mau nyaring transaksi mencurigakan. Data uji bulan ini: 10.000 transaksi, 200 di antaranya beneran penipuan. Jadi kelas penipuan cuma 2%.
Model dijalankan dengan ambang bawaan 0,5. Hasilnya:
| Model bilang penipuan | Model bilang aman | Total | |
|---|---|---|---|
| Memang penipuan | 140 (TP) | 60 (FN) | 200 |
| Memang aman | 360 (FP) | 9.440 (TN) | 9.800 |
| Total | 500 | 9.500 | 10.000 |
Empat angka ini yang bakal kita pakai sepanjang artikel.
Akurasi adalah porsi tebakan benar dari seluruh data. Presisi adalah porsi tebakan positif yang ternyata benar. Recall adalah porsi kasus positif yang berhasil ketangkap model. Ketiganya dihitung dari empat sel yang sama, tapi jawab pertanyaan yang beda.
Akurasi = (TP + TN) / total
= (140 + 9.440) / 10.000 = 95,8%
Presisi = TP / (TP + FP)
= 140 / 500 = 28,0%
Recall = TP / (TP + FN)
= 140 / 200 = 70,0%
F1 = 2 x (presisi x recall) / (presisi + recall)
= 2 x (0,28 x 0,70) / 0,98 = 0,40
Akurasi 95,8% kedengeran bagus. Sekarang coba model paling malas di dunia: bilang "aman" ke semua transaksi.
Model malas itu dapat akurasi 98%, lebih tinggi dari model asli, dan nangkap nol penipuan.
Itu alasan kenapa akurasi nggak boleh jadi KPI tunggal buat data yang kelasnya timpang.
| Metrik | Pertanyaan yang dijawab | Siapa yang peduli |
|---|---|---|
| Akurasi | Berapa persen tebakan model yang benar? | Nyaris nggak ada, kalau datanya timpang |
| Presisi | Kalau model bilang penipuan, seberapa sering dia benar? | Tim operasional yang harus ngecek satu-satu |
| Recall | Dari semua penipuan, berapa yang ketangkap? | Tim risiko dan keuangan |
Presisi 28% artinya dari 500 transaksi yang ditandai, cuma 140 yang beneran penipuan. Tim verifikasi bakal ngecek 360 transaksi sah dan nemu nol masalah di sana.
Recall 70% artinya 60 penipuan lolos begitu aja.
Di sinilah metrik berubah jadi keputusan. Dua asumsi biaya yang dipakai tim risiko:
Biaya di ambang 0,5:
Penipuan lolos : 60 x Rp 850.000 = Rp 51.000.000
Blokir keliru : 360 x Rp 25.000 = Rp 9.000.000
Total : Rp 60.000.000
Sekarang geser ambangnya dan lihat apa yang terjadi.
| Ambang | TP | FN | FP | Recall | Presisi | Total biaya |
|---|---|---|---|---|---|---|
| 0,3 | 170 | 30 | 900 | 85,0% | 15,9% | Rp 48.000.000 |
| 0,5 | 140 | 60 | 360 | 70,0% | 28,0% | Rp 60.000.000 |
| 0,7 | 100 | 100 | 120 | 50,0% | 45,5% | Rp 88.000.000 |
Ambang 0,7 punya presisi terbaik, 45,5%, dan justru paling mahal. Selisihnya Rp 40 juta per 10.000 transaksi dibanding ambang 0,3.
Alasannya sederhana: satu penipuan yang lolos harganya 34 kali lipat satu blokir keliru.
Kalau perbandingan biayanya kebalik, misalnya pelanggan yang keblokir langsung pindah aplikasi dan hilang selamanya, kesimpulannya juga kebalik.
Aturan praktisnya: kejar recall kalau kasus positif yang lolos itu mahal, kejar presisi kalau tuduhan palsu itu mahal.
| Kasus | Yang dikejar | Alasan |
|---|---|---|
| Deteksi penipuan pembayaran | Recall | Uang hilang lebih mahal dari telepon verifikasi |
| Skrining awal penyakit | Recall | Pasien terlewat berakibat fatal, tes lanjutan murah |
| Filter spam email kantor | Presisi | Email penting masuk spam bikin kontrak batal |
| Rekomendasi produk di beranda | Presisi | Slot terbatas, salah tampil bikin pengguna kabur |
| Penyaringan CV tahap awal | Recall | Kandidat bagus yang kebuang nggak bisa dibalikin |
Perhatikan bahwa nggak satu pun keputusan di tabel itu diambil dari akurasi.
from sklearn.metrics import confusion_matrix, classification_report
tn, fp, fn, tp = confusion_matrix(y_asli, y_tebak).ravel()
print(f"TP={tp} FP={fp} FN={fn} TN={tn}")
print(classification_report(y_asli, y_tebak,
target_names=["aman", "penipuan"],
digits=3))
Fungsi classification_report langsung ngeluarin presisi, recall, dan F1 per kelas. Urutan nilai dari ravel() itu tn, fp, fn, tp, dan urutan ini sering bikin salah baca. Rinciannya ada di dokumentasi resmi scikit-learn.
Buat nyari ambang terbaik berdasarkan biaya, hitung langsung:
import numpy as np
prob = model.predict_proba(X_uji)[:, 1]
for t in np.arange(0.1, 0.95, 0.05):
tebak = (prob >= t).astype(int)
tn, fp, fn, tp = confusion_matrix(y_asli, tebak).ravel()
biaya = fn * 850_000 + fp * 25_000
print(f"ambang {t:.2f} recall {tp/(tp+fn):.3f} biaya Rp {biaya:,.0f}")
Loop sederhana ini lebih berguna dari ngejar F1 tertinggi, soalnya dia ngomong dalam satuan yang dimengerti manajemen.
Satu lagi yang sering kelewat: label "penipuan" di data latih datang dari laporan pelanggan, dan pelanggan nggak selalu lapor. Batas atas kualitas modelmu ditentukan sama data quality label itu.
Kalau hasil prediksimu masih di Excel, kamu nggak perlu Python buat bikin confusion matrix.
Misalnya kolom A berisi label sebenarnya dan kolom B berisi tebakan model, keduanya diisi "penipuan" atau "aman".
TP =COUNTIFS(A:A;"penipuan";B:B;"penipuan")
FP =COUNTIFS(A:A;"aman";B:B;"penipuan")
FN =COUNTIFS(A:A;"penipuan";B:B;"aman")
TN =COUNTIFS(A:A;"aman";B:B;"aman")
Empat baris COUNTIFS itu udah cukup buat ngisi seluruh tabel. Presisi dan recall tinggal pembagian biasa.
Bungkus pembagiannya pakai IFERROR biar nggak muncul error waktu model belum nandain apa-apa.
Tergantung mana kesalahan yang lebih mahal buat bisnismu. Kalau ngelewatin kasus positif berakibat fatal, misalnya fraud atau penyakit, recall yang kamu kejar. Kalau salah tuduh bikin pelanggan kabur atau tim buang waktu ngecek, presisi yang lebih penting. Hitung biaya rupiahnya, lalu pilih dari angka itu.
Karena akurasi ngitung semua tebakan benar tanpa peduli kelasnya. Kalau cuma 2% transaksi yang fraud, model yang selalu bilang "aman" langsung dapat akurasi 98% tanpa pernah nangkap satu fraud pun. Di data timpang, akurasi tinggi cuma nunjukin kelas mayoritasnya besar.
F1-score adalah rata-rata harmonik dari presisi dan recall, jadi satu angka yang naik cuma kalau dua-duanya lumayan. Dia berguna waktu kamu ngebandingin banyak model sekaligus. Buat keputusan akhir yang menyangkut biaya nyata, tetap balik ke presisi dan recall terpisah.
Bisa. Buat tiga kelas, tabelnya jadi 3x3, dan tiap baris adalah kelas sebenarnya sementara tiap kolom adalah tebakan model. Presisi dan recall dihitung per kelas. Yang paling berguna dari tabel besar ini adalah lihat pasangan kelas mana yang sering ketuker.
Mulai dari biaya. Kalikan jumlah kesalahan tiap jenis dengan kerugian rupiahnya, lalu hitung total biaya di beberapa ambang. Ambang terbaik adalah yang total biayanya paling kecil, dan itu jarang jatuh di angka 0,5 yang jadi bawaan library.
Akurasi 95,8% kalah sama model malas yang dapat 98% dan nangkap nol penipuan. Angka itu doang nggak layak dilaporin.
Presisi dan recall jawab pertanyaan yang beda, dan cuma salah satunya yang cocok sama masalahmu.
Sebelum bilang model kamu bagus, kalikan tiap jenis kesalahan sama biayanya. Selisih Rp 40 juta di kasus tadi muncul cuma dari geser ambang, tanpa ganti model sama sekali.
Lanjut baca algoritma Naive Bayes dan contoh hitung manualnya buat lihat dari mana angka prediksi itu datang, atau latihan narik data transaksi di NgulikSQL.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Kolom datetime nyimpen tanggal, jam, hari, semuanya nempel jadi satu. Accessor .dt di pandas ngeluarin tiap bagian jadi kolom sendiri buat dianalisa.
Nama toko ketik campur huruf besar-kecil, spasi nyasar di ujung, atau kode produk nempel jadi satu. Accessor .str di pandas ngerapiin semua itu tanpa loop.
Model machine learning cuma ngerti angka, bukan teks kayak merah atau biru. get_dummies ngubah kolom kategori jadi kolom 0/1 dalam satu baris kode.