Menangani data tidak seimbang dengan resampling dan cost-sensitive learning plus metrik yang tepat seperti PR-AUC dan F2, lalu membangun deteksi anomaly dengan Isolation Forest dan One-Class SVM pada skenario deteksi fraud 2026.

Kita sudah menyentuh ketidakseimbangan data di episode 6 (churn). Episode ini kita masuk jauh lebih dalam, karena ada kelas masalah di mana ketidakseimbangan bukan sekadar gangguan — ia adalah inti masalahnya: deteksi fraud. Dari sejuta transaksi, mungkin hanya 100 yang curang (0.01%). Dan setiap yang terlewat berarti uang hilang.
Mengapa topik ini layak satu episode penuh? Karena di data yang sangat tidak seimbang, hampir semua yang kalian pelajari sebelumnya bisa menipu: accuracy meledak palsu, model "tampak" sempurna padahal buta terhadap kelas minoritas, dan SMOTE sederhana bisa menghasilkan sampel sintetis yang tidak realistis.
Ingat kembali confusion matrix dari episode 6. Dengan 0.01% fraud, model yang menebak "semua normal" mendapat accuracy 99.99%. Tampak mengagumkan — padahal ia tidak mendeteksi fraud apa pun.
Metrik yang benar adalah yang fokus pada kelas minoritas:
| Metrik | Fokus | Kapan dipakai |
|---|---|---|
| PR-AUC | Precision vs recall pada kelas minoritas | Data sangat tidak seimbang |
| F2 | Recall dihargai 2x precision | Biaya false negative lebih tinggi |
| Recall pada kelas minoritas | Persentase fraud tertangkap | Prioritas jangan ada yang lewat |
F2 score relevan karena biaya sebuah fraud terlewat (uang hilang) jauh lebih besar daripada biaya alert palsu (tim mengecek transaksi normal).
Langkah pertama yang paling sederhana: beri tahu model bahwa salah mengira fraud normal itu mahal. Sebagian besar model punya parameter ini:
from sklearn.linear_model import LogisticRegression
# class_weight menaikkan penalti kesalahan pada kelas minoritas
model = LogisticRegression(class_weight="balanced")
# Atau sangat spesifik: 1 unit posisi normal, 100 untuk fraud
weights = {0: 1.0, 1: 100.0}
model = LogisticRegression(class_weight=weights)Cara lain dengan threshold: alih-alih memakai default 0.5, turunkan threshold keputusan sehingga lebih banyak transaksi diperiksa sebagai fraud — recall naik, precision turun, sesuai prioritas bisnis.
Di episode 6 kita mengenalkan SMOTE. Untuk kasus ekstrem, ada varian yang lebih matang:
from imblearn.over_sampling import BorderlineSMOTE
from imblearn.pipeline import Pipeline as ImbPipeline
from sklearn.ensemble import RandomForestClassifier
pipeline = ImbPipeline([
("smote", BorderlineSMOTE(random_state=42)),
("clf", RandomForestClassifier(random_state=42, n_jobs=-1)),
])
pipeline.fit(X_train, y_train)Ingat kembali aturan emas episode 6: SMOTE hanya untuk data train, di dalam pipeline, setelah split.
Warning
Di data yang sangat tidak seimbang, oversampling berlebihan bisa membuat model overfit terhadap sampel sintetis — belajar menghafal interpolasi, bukan pola asli. Mulai dari class_weight="balanced" yang sederhana, baru tambah SMOTE jika recall-nya masih kurang.
Precision-recall curve menggambarkan trade-off precision vs recall pada semua threshold:
from sklearn.metrics import (
precision_recall_curve, auc, fbeta_score,
)
proba = pipeline.predict_proba(X_test)[:, 1]
precision, recall, _ = precision_recall_curve(y_test, proba)
print(f"PR-AUC = {auc(recall, precision):.4f}")
print(f"F2 score = {fbeta_score(y_test, pipeline.predict(X_test), beta=2):.3f}")PR-AUC yang rendah (misal 0.1) terdengar buruk, tapi di data 0.01% fraud justru wajar — model masih 10x lebih baik dari random. Bandingkan selalu dengan baseline acak yang nilainya sama dengan proporsi kelas minoritas.
Kadang kalian bahkan tidak punya label fraud sama sekali — atau fraud bentuk baru muncul yang tidak ada di data historis. Di sinilah anomaly detection berperan: mendeteksi titik yang menyimpang dari pola normal, tanpa perlu contoh fraud sebelumnya.
Isolation Forest bekerja dengan intuisi cerdas: anomaly itu mudah diisolasi. Bayangkan membagi ruang data dengan potongan acak — titik normal butuh banyak potongan untuk dipisahkan (mereka berkerumun), titik aneh terisolasi hanya dengan sedikit potongan.
from sklearn.ensemble import IsolationForest
model = IsolationForest(
contamination=0.001, # proporsi anomaly yang diduga
random_state=42,
)
model.fit(X)
preds = model.predict(X) # 1 = normal, -1 = anomaly
anomalies = X[preds == -1]
print(f"Anomali terdeteksi: {len(anomalies)}")contamination adalah tebakan proporsi anomali — sangat bergantung pada domain. Nilai -1 menandai transaksi mencurigakan untuk ditinjau manual.
One-Class SVM belajar "batas" data normal; data di luar batas dianggap anomali. Lebih mahal komputasinya dan sensitif pada scaling:
from sklearn.svm import OneClassSVM
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
ocsvm = Pipeline([
("scale", StandardScaler()),
("svm", OneClassSVM(nu=0.001)),
])
preds = ocsvm.fit_predict(X)| Algoritma | Kelebihan | Kekurangan |
|---|---|---|
| Isolation Forest | Cepat, tidak butuh scaling, bagus di dimensi tinggi | Perlu tebakan contamination |
| One-Class SVM | Batas keputusan halus | Lambat di data besar, wajib scaling |
| KNN (k-th neighbor) | Intuitif | Butuh metrik jarak & scaling |
| DBSCAN (episode 8) | Gratis outlier saat clustering | Parameter eps sensitif |
Alur kerja yang realistis untuk deteksi fraud:
Model ML tidak menggantikan review manual — ia mempersempit daftar yang perlu direview, dari sejuta menjadi seratus. Gabungkan dua pendekatan sekaligus:
# Model supervised: belajar dari fraud yang sudah dikenal
clf = ImbPipeline([
("smote", BorderlineSMOTE(random_state=42)),
("clf", RandomForestClassifier(random_state=42)),
])
clf.fit(X_train, y_train)
# Model unsupervised: menangkap fraud bentuk baru
iso = IsolationForest(contamination=0.001, random_state=42)
iso.fit(X_train)
# Gabungkan: transaksi mencurigakan jika model supervised ATAU unsupervised menandainya
risky = (clf.predict_proba(X_test)[:, 1] > 0.5) | (iso.predict(X_test) == -1)Kombinasi supervised + unsupervised menangkap keduanya: pola fraud yang sudah dikenal (dipelajari dari label) dan pola baru yang menyimpang dari normal (tanpa label).
contamination asal tebak pada Isolation Forest — kalibrasi dengan domain knowledge.Pada episode 14 ini, kalian telah menguasai penanganan data tidak seimbang dan deteksi anomaly.
Inti yang harus dibawa pulang:
class_weight, tambah SMOTE (Borderline/ADASYN) jika perlu.Di episode 15 selanjutnya kita akan membahas categorical data & encoding lanjutan — target encoding, ordinal, dan frequency encoding, penanganan high-cardinality, serta workflow feature engineering ala kompetisi Kaggle untuk data tabular. Sampai jumpa di episode 15!