Pada Chapter Validasi Walk-Forward, RandomForest 300 pohon milik Toko Ceria menang 12 dari 14 lipatan — kita tahu seberapa baik model tersebut meramalkan, tetapi tidak mengapa model mengambil keputusan tertentu pada pekan tertentu. Interpretabilitas (interpretability) adalah sejauh mana manusia dapat memahami alasan di balik keluaran sebuah model, sedangkan explainable AI (XAI) adalah kumpulan teknik untuk menambal kekurangan tersebut pada model yang sudah terlanjur kompleks. Section ini membuka kotak hitam tersebut secara sistematis, dimulai dari kosakata yang memetakan seluruh medan: mana yang dijelaskan (model itu sendiri atau tiap prediksinya), kapan dijelaskan (sejak lahir model atau setelahnya), dan dengan alat apa. Sepanjang section kita memakai satu studi kasus yang sama — pengajuan pinjaman di platform fiktif Kredit Ceria — sehingga setiap teknik dapat diadili pada data yang kebenarannya kita ketahui.
Empat Alasan Model Harus Bisa Dijelaskan #
Kebutuhan interpretabilitas bukan selera akademik; empat situasi nyata menuntutnya. Pertama, kepercayaan: tim operasional jarang menjalankan keputusan yang tidak bisa mereka dalami — dokter kredit yang diminta menolak seorang nasabah ingin tahu alasannya, bukan hanya skornya. Kedua, diagnosis: saat pipeline menurun kualitasnya, penjelasan fitur sering menjadi instrumen debugging tercepat — fitur yang seharusnya penting tapi terbaca nol adalah petunjuk kebocoran data atau kesalahan praproses. Ketiga, kepatuhan: regulasi di berbagai yurisdiksi mewajibkan alasan yang dapat diaudit untuk keputusan yang berdampak pada individu — penolakan pinjaman termasuk kategori itu. Keempat, sains: pada data penelitian, model yang akurat namun tak terbaca hanya memberi prediksi, bukan pemahaman; koefisien dan importance yang terbaca bisa menjadi hipotesis baru untuk diuji.
Peta Konsep: Tiga Sumbu Taksonomi #
Literatur interpretabilitas memetakan teknik lewat tiga sumbu yang saling tegak lurus. Sumbu pertama, intrinsik vs pasca-hoc (post-hoc): model intrinsik interpretable — Regresi Linier, Regresi Logistik, Decision Tree dangkal — terbaca langsung dari strukturnya; teknik post-hoc menjelaskan model yang sudah jadi tanpa mengubahnya. Sumbu kedua, global vs lokal: penjelasan global merangkum perilaku model di seluruh data (fitur mana yang penting secara umum), penjelasan lokal menjelaskan satu prediksi tunggal (mengapa pengajuan Budi ditolak). Sumbu ketiga, spesifik-model vs model-agnostic: alat seperti TreeExplainer memanfaatkan struktur pohon sehingga cepat tetapi terikat satu keluarga model; alat agnostik hanya membutuhkan kemampuan memprediksi sehingga berlaku untuk model apa pun.
| Alat (chapter) | Cakupan | Ketergantungan | Pertanyaan yang dijawab |
|---|---|---|---|
| Permutation Importance | Global | Agnostik | Fitur mana yang paling menopang skor? |
| Partial Dependence / ICE | Global + lokal per fitur | Agnostik | Bagaimana bentuk hubungan fitur–prediksi? |
| SHAP values | Lokal + agregasi global | Spesifik-model (pohon) | Berapa kontribusi tiap fitur pada satu prediksi? |
| Surrogate model | Global / lokal | Agnostik | Aturan sederhana apa yang meniru kotak hitam? |
Interpretabilitas Intrinsik: Membaca Koefisien #
Contoh pertama membangun data Kredit Ceria dengan mekanisme yang kita ciptakan sendiri: lima fitur, dan keputusan disetujui ditentukan oleh logit yang naik dengan pendapatan serta lama kerja, turun dengan rasio utang serta riwayat keterlambatan, dan sama sekali tidak memedulikan umur. Regresi Logistik kemudian dilatih pada fitur yang distandardisasi — supaya koefisien sebanding antar-fitur — dan dibandingkan dengan RandomForest pada data yang persis sama.
# Model intrinsik interpretable: Regresi Logistik pada data pengajuan
# pinjaman di platform fiktif "Kredit Ceria". Lima fitur, target berupa
# keputusan disetujui (1) atau ditolak (0). Hubungan target-fitur dibangun
# lewat logit linear sehingga koefisien model dapat dibandingkan langsung
# dengan mekanisme pembangkit datanya.
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
rng = np.random.default_rng(42)
n = 500
# Fitur pengajuan (satuan aslinya, tanpa scaling saat dibangkitkan).
pendapatan = rng.lognormal(mean=np.log(9.0), sigma=0.45, size=n) # juta/bulan
rasio_utang = rng.uniform(0.05, 0.95, size=n) # cicilan/penghasilan
lama_kerja = rng.uniform(0.0, 20.0, size=n) # tahun di pekerjaan kini
umur = rng.uniform(23.0, 60.0, size=n) # tahun; TIDAK dipakai target
riwayat_telat = np.clip(rng.poisson(1.2, size=n), 0, 12) # jumlah keterlambatan bayar
# Mekanisme pembangkit (ground truth): logit naik dengan pendapatan dan
# lama_kerja, turun dengan rasio_utang dan riwayat_telat; umur tidak masuk.
logit = (2.6 * (np.log(pendapatan) - np.log(9.0)) / 0.45
- 9.0 * (rasio_utang - 0.5)
+ 0.13 * (lama_kerja - 10.0)
- 0.55 * (riwayat_telat - 1.2)
+ rng.normal(scale=0.8, size=n))
disetujui = (logit > 0).astype(int)
fitur = ["pendapatan", "rasio_utang", "lama_kerja", "umur", "riwayat_telat"]
X = pd.DataFrame({
"pendapatan": pendapatan,
"rasio_utang": rasio_utang,
"lama_kerja": lama_kerja,
"umur": umur,
"riwayat_telat": riwayat_telat,
})[fitur]
X_latih, X_uji, y_latih, y_uji = train_test_split(
X, disetujui, test_size=0.25, random_state=42)
# Model intrinsik interpretable: fitur distandardisasi supaya koefisien
# sebanding antar-fitur dan arahnya langsung terbaca.
model_linier = make_pipeline(
StandardScaler(),
LogisticRegression(max_iter=1000, random_state=42),
)
model_linier.fit(X_latih, y_latih)
koefisien = model_linier.named_steps["logisticregression"].coef_[0]
print("Koefisien baku Regresi Logistik (fitur distandardisasi):")
for nama, b in sorted(zip(fitur, koefisien), key=lambda pasangan: -abs(pasangan[1])):
arah = "menaikkan" if b > 0 else "menurunkan"
print(f" {nama:>14}: {b:+.3f} (odds ratio {np.exp(b):.2f}, {arah} peluang)")
# Pembanding kotak hitam pada data yang sama: 300 pohon tanpa coef_.
model_forest = RandomForestClassifier(
n_estimators=300, random_state=42, n_jobs=1).fit(X_latih, y_latih)
print(f"\nAkurasi data uji Regresi Logistik : {model_linier.score(X_uji, y_uji):.3f}")
print(f"Akurasi data uji RandomForest (300): {model_forest.score(X_uji, y_uji):.3f}")
print("RandomForest tidak memiliki coef_; isinya 300 pohon kedalaman penuh.")Output yang Dihasilkan:
Koefisien baku Regresi Logistik (fitur distandardisasi):
pendapatan: +3.987 (odds ratio 53.92, menaikkan peluang)
rasio_utang: -2.882 (odds ratio 0.06, menurunkan peluang)
lama_kerja: +0.810 (odds ratio 2.25, menaikkan peluang)
riwayat_telat: -0.410 (odds ratio 0.66, menurunkan peluang)
umur: -0.102 (odds ratio 0.90, menurunkan peluang)
Akurasi data uji Regresi Logistik : 0.904
Akurasi data uji RandomForest (300): 0.880
RandomForest tidak memiliki coef_; isinya 300 pohon kedalaman penuh.Mari kita telaah baris-baris kunci pada contoh di atas:
- Baris 15–23 (pembangkitan fitur): seluruh keacakan berasal dari satu generator berseed, dan umur sengaja dibangkitkan tanpa hubungan dengan target — fitur umpan yang nanti menguji apakah model sungguh membedakan sinyal dari derau.
- Baris 27–32 (mekanisme kebenaran): keputusan lahir dari logit linear — ketentuan yang kita tulis sendiri, sehingga kelak koefisien model dapat diadili terhadapnya.
- Baris 48–53 (pipeline baku):
StandardScalerdi depanLogisticRegressionmembuat koefisien terukur dalam satuan simpangan baku;named_steps["logisticregression"].coef_[0]mengambil kelima angka itu. - Baris 56–58 (pencetakan terurut):
sorted(..., key=lambda pasangan: -abs(pasangan[1]))memanggil fitur berdasarkan besar pengaruhnya, dannp.exp(b)mengubah koefisien menjadi odds ratio yang mudah dibisikkan ke tim bisnis.
Hasilnya menunjukkan interpretasi intrinsik bekerja persis seperti dijanjikan. Arah seluruh koefisien cocok dengan mekanisme pembangkit: pendapatan dan lama kerja bertanda positif, rasio utang dan riwayat keterlambatan bertanda negatif. Urutan besaran juga benar — pendapatan dan rasio utang menempati dua posisi teratas — dan umur, fitur umpan, mendarat paling bawah dengan koefisien −0,102: nyaris nol, sisanya derau sampel. Bonus pelajaran ada pada dua baris akurasi: Regresi Logistik (0,904) justru mengungguli RandomForest (0,880) karena batas keputusan data ini memang linear — kompleksitas tidak selalu terbayar, dan pada data semacam ini model yang terbaca adalah pilihan yang menang dua kali.
Pratinjau Alat Post-hoc pada Kotak Hitam #
Bagaimana jika RandomForest memang perlu — misalnya karena hubungannya melengkung dan berinteraksi seperti pada data deret waktu Toko Ceria? Model tersebut tetap tanpa coef_, tetapi bukan berarti tidak bisa ditanya. Contoh kedua memberi pratinjau alat post-hoc pertama kita: permutation_importance mengacak satu kolom fitur pada data uji, lalu mengukur berapa akurasi model turun. Fitur yang penting bagi model akan membuat skor jatuh ketika hubungannya dengan target diputus lewat pengacakan itu.
# Pratinjau alat post-hoc: menanyakan kotak hitam tanpa membukanya.
# permutation_importance mengacak satu kolom fitur pada data uji lalu
# mengukur berapa jauh skor model turun. Chapter berikutnya membedah
# alat ini sampai tuntas; di sini kita cukup melihat pratinjaunya.
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.inspection import permutation_importance
from sklearn.model_selection import train_test_split
rng = np.random.default_rng(42)
n = 500
# Data pengajuan pinjaman "Kredit Ceria" -- generator sama dengan contoh
# sebelumnya agar kedua model dapat dibandingkan pada data identik.
pendapatan = rng.lognormal(mean=np.log(9.0), sigma=0.45, size=n)
rasio_utang = rng.uniform(0.05, 0.95, size=n)
lama_kerja = rng.uniform(0.0, 20.0, size=n)
umur = rng.uniform(23.0, 60.0, size=n)
riwayat_telat = np.clip(rng.poisson(1.2, size=n), 0, 12)
logit = (2.6 * (np.log(pendapatan) - np.log(9.0)) / 0.45
- 9.0 * (rasio_utang - 0.5)
+ 0.13 * (lama_kerja - 10.0)
- 0.55 * (riwayat_telat - 1.2)
+ rng.normal(scale=0.8, size=n))
disetujui = (logit > 0).astype(int)
fitur = ["pendapatan", "rasio_utang", "lama_kerja", "umur", "riwayat_telat"]
X = pd.DataFrame({
"pendapatan": pendapatan,
"rasio_utang": rasio_utang,
"lama_kerja": lama_kerja,
"umur": umur,
"riwayat_telat": riwayat_telat,
})[fitur]
X_latih, X_uji, y_latih, y_uji = train_test_split(
X, disetujui, test_size=0.25, random_state=42)
model_forest = RandomForestClassifier(
n_estimators=300, random_state=42, n_jobs=1).fit(X_latih, y_latih)
hasil = permutation_importance(
model_forest, X_uji, y_uji, scoring="accuracy",
n_repeats=20, random_state=42, n_jobs=1)
print(f"Akurasi dasar RandomForest pada data uji: {model_forest.score(X_uji, y_uji):.3f}")
print("\nPenurunan akurasi ketika satu fitur diacak (20 pengulangan, data uji):")
urutan = np.argsort(-hasil.importances_mean)
for i in urutan:
print(f" {fitur[i]:>14}: {hasil.importances_mean[i]:+.3f} +/- {hasil.importances_std[i]:.3f}")Output yang Dihasilkan:
Akurasi dasar RandomForest pada data uji: 0.880
Penurunan akurasi ketika satu fitur diacak (20 pengulangan, data uji):
pendapatan: +0.240 +/- 0.036
rasio_utang: +0.203 +/- 0.035
lama_kerja: +0.028 +/- 0.015
riwayat_telat: +0.003 +/- 0.008
umur: -0.005 +/- 0.010Dua baris terpenting pada contoh tersebut adalah baris 45–47: pemanggilan permutation_importance dengan scoring="accuracy", n_repeats=20 (setiap fitur diacak 20 kali agar rata-ratanya stabil beserta simpangan bakunya), dan random_state=42 agar hasil dapat direproduksi. Keluarannya memberi survei pertama tentang isi kotak hitam: RandomForest menaruh bobot terbesar pada pendapatan (+0,240) dan rasio utang (+0,203) — sepakat dengan koefisien Regresi Logistik dan dengan kebenaran data. Lama kerja menyusul tipis (+0,028), riwayat keterlambatan nyaris tak terasa (+0,003; kontribusinya memang kecil relatif terhadap derau), dan umur tampil dengan tanda negatif (−0,005) — pengacakan yang justru sedikit memperbaiki akurasi, tanda klasik fitur tanpa informasi.
Tarik-Menarik Akurasi dan Interpretabilitas #
Dua contoh di atas sekaligus mengoreksi anggapan keliru yang paling sering didengar: bahwa interpretabilitas selalu dibayar dengan akurasi. Pada data Kredit Ceria, model yang terbaca justru menang. Ketimpangan muncul ke arah sebaliknya — pada masalah dengan hubungan nonlinear dan interaksi yang kaya (pengenalan citra, data tabular bertingkat tinggi, gradient boosting pada fitur hasil rekayasa), model kompleks kerap unggul beberapa poin yang sulit dikejar model linier, dan di situlah teknik post-hoc memperoleh perannya. Praktik yang sehat mengikuti urutan: mulai dari model intrinsik sebagai baseline (kebiasaan yang sama dengan Chapter Apa itu Machine Learning?), naik ke model kompleks hanya bila selisih kinerjanya nyata dan melebihi biaya kejelasannya, lalu selidiki dengan alat post-hoc — atau pilih struktur penengah seperti Decision Tree dangkal atau model linier berbasis generalized additive model.
Peta telah terbentang dan pratinjau tadi meninggalkan satu pertanyaan besar: seberapa bisa dipercaya angka-angka importance itu, dan bagaimana cara memakainya dengan jujur? Pertanyaan itulah yang dijawab oleh alat pertama kita secara penuh pada Chapter Permutation Importance.
Referensi Resmi #
- Permutation feature importance — scikit-learn User Guide — panduan resmi teknik post-hoc yang dipratinjau pada contoh kedua.
- Logistic regression — scikit-learn User Guide — dokumentasi resmi model intrinsik interpretable pada contoh pertama.