Disiplin Perbandingan Model

Disiplin membandingkan model: pemisahan sama, metrik sama, dan uji berpasangan.

Daftar isi

Keputusan memilih satu dari beberapa model hanya sebagus cara membandingkannya. Perbandingan yang adil menuntut tiga disiplin sekaligus, yaitu baris data yang sama, metrik yang sama, dan pembacaan selisih yang memperhitungkan variasi antar fold. Topik ini mempraktikkan ketiganya dengan membandingkan regresi logistik, pohon keputusan, dan random forest pada dataset breast cancer, lalu menutupnya dengan uji t berpasangan (paired t-test) atas fold yang sama.

Tiga syarat perbandingan yang adil#

Syarat pertama adalah baris uji yang sama. Dua model yang dinilai pada pemisahan berbeda membawa keberuntungan pemisahan masing-masing ke dalam angkanya, sehingga selisih skor mencampur dua sumber sekaligus, yaitu perbedaan model dan perbedaan komposisi data uji. Pemisahan dibuat satu kali dengan train_test_split yang random_state dan stratify-nya dipatok sama, kemudian hasilnya digunakan bersama oleh seluruh kandidat model. Untuk perbandingan antar fold, objek pembagi fold yang sama diberikan kepada setiap model.

Syarat kedua adalah perlakuan preprocessing yang sama. Penskalaan yang dihitung dari data yang berbeda membuat dua model bekerja pada masukan yang tidak sebanding, dan penskalaan yang dihitung dari seluruh data menimbulkan kebocoran. Cara yang paling aman adalah membungkus setiap model beserta transformasinya dalam Pipeline, sehingga statistik transformasi hanya dihitung dari data latih pada setiap percobaan. Struktur ini juga memastikan setiap model dibandingkan tanpa keuntungan tersembunyi dari perlakuan fitur yang berbeda.

Syarat ketiga adalah metrik yang sama beserta ambangnya. Akurasi menerapkan ambang 0.5 secara implisit, sedangkan AUC menilai urutan skor tanpa ambang, sehingga membandingkan akurasi satu model dengan AUC model lain tidak menghasilkan keputusan yang bermakna. Satu metrik dipilih sesuai tujuan masalah, lalu digunakan untuk semua kandidat, dan angka pelengkapnya dilaporkan sebagai informasi tambahan.

Uji t berpasangan atas fold yang sama#

Selisih rata-rata dua skor cross-validation belum cukup untuk menyatakan satu model unggul, karena skor antar fold berayun dan rata-rata kecil dapat berubah urutan pada seed yang berbeda. Uji t berpasangan bekerja pada selisih per fold dj=sA,j−sB,jd_j = s_{A,j} - s_{B,j}, dengan sA,js_{A,j} dan sB,js_{B,j} sebagai skor kedua model pada fold yang sama. Karena kedua model menilai fold yang persis sama, variasi antar fold saling meniadakan, dan yang tersisa adalah konsistensi arah selisihnya. Statistik ujinya adalah

t=dˉsd/k t = \frac{\bar{d}}{s_d / \sqrt{k}}

dengan dˉ\bar{d} rata-rata selisih per fold, sds_d deviasi standar selisih, dan kk banyaknya fold. Nilai pp yang kecil menunjukkan selisih yang arahnya konsisten dan bukan hasil keberuntungan beberapa fold saja.

Pembacaannya memerlukan tiga catatan kejujuran. Dengan kk yang kecil, misalnya lima fold, daya ujinya rendah sehingga selisih yang nyata pun dapat gagal melewati taraf 0.05. Fold-fold tersebut juga saling bertumpuk karena data latihnya berbagi baris, sehingga uji ini lebih tepat dibaca sebagai perkiraan, bukan pengujian yang bersih secara statistik. Karena itu rata-rata, deviasi standar, dan nilai pp dilaporkan sebagai satu kesatuan, bukan nilai pp saja.

Praktik: tiga model pada data yang sama#

Skrip bandingkan-model.py menyiapkan tiga fungsi model, yaitu pipeline StandardScaler dan LogisticRegression, DecisionTreeClassifier berkedalaman empat, serta RandomForestClassifier dengan 100 pohon, semuanya dengan random_state=42. Satu pemisahan data uji digunakan bersama, kemudian StratifiedKFold lima fold yang sama diberikan kepada cross_val_score ketiga model. Pada akhirnya, ttest_rel dari scipy menguji berpasangan dua model teratas, yaitu regresi logistik dan random forest. Skrip dijalankan dari direktori topiknya dengan python3 -B bandingkan-model.py.

python bandingkan-model.py
"""Membandingkan tiga model pada pemisahan, fold, dan metrik yang sama."""

from scipy.stats import ttest_rel
from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold, cross_val_score, train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.tree import DecisionTreeClassifier

X, y = load_breast_cancer(return_X_y=True)


def logreg():
    return make_pipeline(StandardScaler(), LogisticRegression(max_iter=5000))


def pohon():
    return DecisionTreeClassifier(max_depth=4, random_state=42)


def hutan():
    return RandomForestClassifier(n_estimators=100, random_state=42)


kandidat = [
    ("regresi logistik", logreg),
    ("pohon keputusan  ", pohon),
    ("random forest    ", hutan),
]

# pemisahan yang sama untuk ketiga model
X_latih, X_uji, y_latih, y_uji = train_test_split(
    X, y, test_size=0.20, random_state=42, stratify=y
)
print("Akurasi satu pemisahan yang sama (random_state=42):")
for nama, buat in kandidat:
    akurasi = buat().fit(X_latih, y_latih).score(X_uji, y_uji)
    print(f"  {nama}: {akurasi:.4f}")

# fold yang sama untuk ketiga model
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
print()
print("Akurasi per fold pada cross-validation yang sama:")
print(f"  {'model':<18}" + "".join(f"  fold {i}" for i in range(1, 6)) + "   rata-rata")
skor_semua = {}
for nama, buat in kandidat:
    skor = cross_val_score(buat(), X, y, cv=cv)
    skor_semua[nama.strip()] = skor
    baris = "".join(f"  {s:.4f}" for s in skor)
    print(f"  {nama:<18}{baris}   {skor.mean():.4f}")

# uji t berpasangan atas dua model dengan rata-rata terbaik
t_stat, p_nilai = ttest_rel(skor_semua["regresi logistik"], skor_semua["random forest"])
print()
print("Uji t berpasangan, regresi logistik vs random forest:")
print(f"  t = {t_stat:.4f}, p = {p_nilai:.4f}")
text Keluaran
Akurasi satu pemisahan yang sama (random_state=42):
  regresi logistik: 0.9825
  pohon keputusan  : 0.9386
  random forest    : 0.9561

Akurasi per fold pada cross-validation yang sama:
  model               fold 1  fold 2  fold 3  fold 4  fold 5   rata-rata
  regresi logistik    0.9737  0.9474  0.9649  0.9912  0.9912   0.9737
  pohon keputusan     0.9561  0.8684  0.9211  0.9298  0.9381   0.9227
  random forest       0.9649  0.9386  0.9561  0.9474  0.9735   0.9561

Uji t berpasangan, regresi logistik vs random forest:
  t = 2.5865, p = 0.0609

Pada satu pemisahan tunggal, regresi logistik tercatat 0.9825 dan unggul 2.64 poin persentase atas random forest, selisih yang tampak cukup untuk langsung dijadikan dasar keputusan. Tabel cross-validation pada fold yang sama menyajikan pembacaan yang lebih hati-hati, yaitu rata-rata 0.9737 berbanding 0.9561, sehingga keunggulannya menyusut menjadi 1.76 poin persentase. Urutan keduanya tetap sama pada pemisahan ini, tetapi tabel juga memperlihatkan ayunan antar fold, misalnya skor pohon yang jatuh ke 0.8684 pada fold kedua.

Uji t berpasangan melengkapi pembacaan tersebut. Nilai t 2.5865 dengan p 0.0609 menyertai selisih yang positif pada kelima pasangan fold, tetapi lima pasangan belum cukup untuk melewati taraf 0.05. Kesimpulan yang jujur adalah regresi logistik tampak unggul atas random forest pada data ini. Namun, bukti dari lima fold belum kuat untuk menyatakan keunggulan itu pasti. Keputusan dapat ditunda sampai tersedia lebih banyak fold atau pengulangan cross-validation.

Kesalahan umum#

  • Membandingkan model pada pemisahan berbeda karena dieksekusi di tempat terpisah dengan seed berbeda. Selisih yang terbaca mencampur perbedaan model dengan keberuntungan pemisahan. Perbaikannya adalah membuat satu objek pemisahan atau pembagi fold, lalu memberikannya kepada semua kandidat.
  • Membandingkan metrik yang berbeda, misalnya akurasi lawan AUC, karena keduanya mengukur hal yang berbeda pada skala yang berbeda. Satu metrik dipilih sesuai tujuan masalah dan digunakan untuk seluruh kandidat.
  • Menyatakan satu model unggul dari selisih tipis tanpa uji apa pun. Selisih 0.0176 pada lima fold masih berpeluang berasal dari kebetulan, seperti p 0.0609 pada praktik di atas. Selisih dilaporkan bersama sebarannya dan diuji berpasangan sebelum dinyatakan konsisten.
  • Menerapkan uji berpasangan pada skor yang tidak berpasangan. ttest_rel mengasumsikan kedua deret skor berasal dari fold yang sama, sedangkan skor dari pembagi fold berbeda tidak memiliki pasangan yang sah. Pembagi fold yang sama diberikan kepada kedua model sebelum uji dijalankan.
  • Menguji setiap pasangan model lalu melaporkan pasangan dengan p terkecil. Makin banyak pasangan yang diuji, makin besar peluang satu pasangan meloloskan taraf 0.05 karena kebetulan semata. Pasangan yang diuji ditetapkan lebih dahulu sesuai pertanyaan perbandingannya.

Ringkasan#

  • Perbandingan yang adil menuntut baris uji, preprocessing, dan metrik yang sama, dan pipeline per model menjaga dua syarat pertama.
  • Uji t berpasangan menghitung selisih pada fold yang sama, sehingga variasi antar fold tidak dihitung dua kali.
  • Hasil praktiknya, regresi logistik unggul 1.76 poin persentase atas random forest pada rata-rata lima fold, tetapi p 0.0609 belum melewati taraf 0.05.
  • Selisih yang tipis dilaporkan bersama sebaran dan hasil ujinya, bukan sebagai kemenangan yang pasti.

Referensi#