Setelah konstruksi fitur, jumlah kolom biasanya bertambah, dan tidak semuanya berguna: sebagian miskin sinyal, sebagian saling menyalin informasi. Feature selection memangkas kolom-kolom tersebut sebelum model dilatih. Chapter ini membahas keluarga pertama dari tiga keluarga metode: filter, yang menilai fitur langsung dari statistik data tanpa melibatkan model apa pun. Kita akan memakai satu dataset kampanye pemasaran sintetis — 120 pelanggan, 8 fitur kandidat, target biner “merespons kampanye atau tidak” — dan membiarkan metode filter membuktikan dirinya menemukan tiga fitur yang benar-benar memuat sinyal.
Mengapa Memilih Subset Fitur #
Empat alasan praktis menjawab pertanyaan ini. Pertama, training menjadi lebih cepat dan murah: biaya melatih banyak model tumbuh mengikuti jumlah fitur, dan seleksi dini memotong biaya itu untuk seluruh eksperimen berikutnya. Kedua, risiko overfitting turun: pada sampel terbatas, dimensi fitur yang besar memberi model ruang lebih luas untuk menghafal derau — gejala yang dibahas pada Chapter Overfitting dan Underfitting. Ketiga, model lebih mudah ditafsirkan: koefisien tiga fitur bisa dibaca dan dijelaskan kepada pemangku kepentingan; tiga ratus tidak. Keempat, biaya pengumpulan data turun: fitur yang terbukti tidak terpilih tidak perlu dihitung atau dibeli datanya di sistem produksi.
Tiga Kelompok Kriteria Filter #
Metode filter murah karena setiap fitur dinilai sekali lewat perhitungan statistik, hasilnya bisa dipakai untuk model apa pun, dan tidak ada latihan model yang berulang. Kriteria penilaiannya terbagi tiga kelompok: varians tiap fitur, korelasi antar fitur, dan uji statistik antara fitur dan label.
Menyaring dengan Ambang Varians #
Fitur yang nilainya nyaris tidak pernah berubah tidak punya daya pembeda: kolom yang 99% isinya sama tidak bisa memisahkan pelanggan yang merespons dari yang tidak. VarianceThreshold(threshold=0.01) membuang semua kolom dengan varians di bawah ambang tersebut. Perhatikan bahwa varians bukan ukuran informativitas — pada data contoh kita nanti, fitur informatif riwayat_pembelian justru punya varians terkecil — melainkan penyaring awal kolom mati.
Menyiang Redundansi dengan Korelasi #
Dua fitur yang berkorelasi tinggi membawa informasi hampir sama; mempertahankan keduanya menambah dimensi tanpa menambah sinyal, dan membuat koefisien model tidak stabil. Praktik lazimnya: bila korelasi Pearson |r| melewati sekitar 0,9, buang salah satu dari pasangan itu. Kandidat yang dipertahankan biasanya yang paling murah dikumpulkan atau paling mudah dijelaskan — pertimbangan operasional, bukan statistik.
Menguji Hubungan Fitur dengan Label #
Kelompok ketiga paling penting: mengukur seberapa kuat tiap fitur berhubungan dengan label. Tiga uji yang paling sering dipakai punya asumsi berbeda-beda:
| Metode | Asumsi pada data | Menangkap |
|---|---|---|
chi2 | Nilai non-negatif (hitungan) | Ketergantungan fitur-label untuk data hitungan seperti frekuensi kata atau jumlah klik |
f_classif | Numerik, sebaran mendekati normal | Perbedaan rata-rata antar kelas (hubungan linier) |
mutual_info_classif | Numerik maupun kategorikal, bebas bentuk sebaran | Hubungan apa pun dengan label, termasuk non-linier |
Chi-squared wajar untuk matriks hitungan kata; ANOVA F murah dan cepat; mutual information paling bebas asumsi dan sanggup menemukan fitur yang berhubungan melengkung dengan label — dengan tarif komputasi yang sedikit lebih tinggi.
SelectKBest: Membungkus Skor menjadi Selektor #
Uji statistik menghasilkan skor per fitur; SelectKBest mengubah skor itu menjadi selektor konkret dengan mempertahankan k fitur berskor tertinggi. Pilihan k bisa diganti pendekatan persentil lewat SelectPercentile (misalnya menyisakan 50% teratas) ketika jumlah fiturnya ratusan dan nilai k yang pas belum diketahui. Skor mentahnya tetap tersedia di atribut scores_ untuk dibaca sebelum memutuskan. Satu detail teknis: mutual_info_classif memakai keacakan internal, sehingga saat dibungkus sebagai score_func nilainya perlu dibekukan dengan partial(mutual_info_classif, random_state=42) agar hasil seleksi deterministik.
Contoh: Dataset Kampanye 120 Pelanggan #
Dataset contoh dibangun make_classification dengan delapan fitur, tiga di antaranya informatif dan lima sisanya derau murni. Parameter shuffle=False dipilih agar kolom informatif pasti berada di indeks 0–2 — kebenaran yang kita ketahui, tetapi belum diketahui metode seleksinya — sehingga keberhasilan penemuan bisa diverifikasi jujur. Nama fitur diberi rasa kampanye pemasaran (kunjungan_mingguan, durasi_kunjungan, riwayat_pembelian, usia, kode_area, skor_kredit, jumlah_perangkat, tayangan_iklan) walau nilainya sintetis.
# Seleksi fitur keluarga filter: varians, mutual information, dan korelasi.
# Dataset sintetis kampanye pemasaran: 120 pelanggan, 8 fitur, 3 di antaranya
# sengaja dibuat informatif oleh generator (kolom indeks 0-2).
from functools import partial
import numpy as np
from sklearn.datasets import make_classification
from sklearn.feature_selection import SelectKBest, VarianceThreshold, mutual_info_classif
X, y = make_classification(
n_samples=120,
n_features=8,
n_informative=3,
n_redundant=0, # tanpa kolom redundan bawaan; redundansi didemokan manual
n_clusters_per_class=1,
class_sep=1.5,
shuffle=False, # agar kolom informatif pasti berada di indeks 0-2
random_state=42,
)
nama_fitur = [
"kunjungan_mingguan", # indeks 0: informatif
"durasi_kunjungan", # indeks 1: informatif
"riwayat_pembelian", # indeks 2: informatif
"usia", # indeks 3: derau
"kode_area", # indeks 4: derau
"skor_kredit", # indeks 5: derau
"jumlah_perangkat", # indeks 6: derau
"tayangan_iklan", # indeks 7: derau
]
informatif_sejati = ["kunjungan_mingguan", "durasi_kunjungan", "riwayat_pembelian"]
# --- (a) Varians tiap fitur, lalu VarianceThreshold pada kolom nyaris konstan ---
print("(a) Varians tiap fitur:")
for nama, varians in zip(nama_fitur, X.var(axis=0)):
print(f" {nama:<20}{varians:6.3f}")
rng = np.random.default_rng(42)
kolom_konstan = 5.0 + rng.normal(0.0, 0.01, size=120) # nilai nyaris tak berubah
X_dengan_konstan = np.column_stack([X, kolom_konstan])
nama_lengkap = nama_fitur + ["fitur_konstan"]
penyaring_var = VarianceThreshold(threshold=0.01)
X_bersih = penyaring_var.fit_transform(X_dengan_konstan)
dihapus = [n for n, s in zip(nama_lengkap, penyaring_var.get_support()) if not s]
print(f"\nVarianceThreshold(0.01): {X_dengan_konstan.shape[1]} kolom -> {X_bersih.shape[1]} kolom")
print(f"Kolom yang dibuang: {', '.join(dihapus)}")
# --- (b) Skor mutual information tiap fitur terhadap label ---
skor_mi = mutual_info_classif(X, y, random_state=42)
urutan = np.argsort(skor_mi)[::-1]
print("\n(b) Skor mutual information (diurutkan menurun):")
for indeks in urutan:
print(f" {nama_fitur[indeks]:<20}{skor_mi[indeks]:6.3f}")
tiga_teratas = sorted(nama_fitur[i] for i in urutan[:3])
print(f"Tiga skor tertinggi : {', '.join(tiga_teratas)}")
print(f"Informatif sejati : {', '.join(sorted(informatif_sejati))}")
if tiga_teratas == sorted(informatif_sejati):
print("Kesimpulan: tiga peringkat teratas cocok seluruhnya dengan informatif sejati.")
# --- (c) SelectKBest membungkus skor mutual information ---
# random_state di-bekukan lewat partial agar skor deterministik saat dipanggil ulang.
pemilih = SelectKBest(score_func=partial(mutual_info_classif, random_state=42), k=3)
pemilih.fit(X, y)
terpilih = [n for n, s in zip(nama_fitur, pemilih.get_support()) if s]
print(f"\n(c) Fitur terpilih SelectKBest(k=3): {', '.join(terpilih)}")
# --- (d) Redundansi: dua fitur berkorelasi tinggi ---
pendapatan_juta = rng.normal(12.0, 2.5, size=120)
pengeluaran_juta = 0.8 * pendapatan_juta + rng.normal(0.0, 0.6, size=120)
matriks_r = np.corrcoef(pendapatan_juta, pengeluaran_juta)
print("\n(d) Matriks korelasi dua fitur kandidat:")
print(f" {'':<14}{'pendapatan':>10}{'pengeluaran':>13}")
for nama_baris, baris in zip(["pendapatan", "pengeluaran"], matriks_r):
print(f" {nama_baris:<14}{baris[0]:>10.3f}{baris[1]:>13.3f}")
r = matriks_r[0, 1]
print(f"Korelasi r = {r:.3f}; |r| > 0.90 -> salah satu kolom dibuang (redundan)")Output yang Dihasilkan:
(a) Varians tiap fitur:
kunjungan_mingguan 3.998
durasi_kunjungan 1.385
riwayat_pembelian 0.737
usia 1.021
kode_area 0.932
skor_kredit 1.035
jumlah_perangkat 0.994
tayangan_iklan 0.934
VarianceThreshold(0.01): 9 kolom -> 8 kolom
Kolom yang dibuang: fitur_konstan
(b) Skor mutual information (diurutkan menurun):
kunjungan_mingguan 0.438
riwayat_pembelian 0.281
durasi_kunjungan 0.079
kode_area 0.057
skor_kredit 0.052
tayangan_iklan 0.038
jumlah_perangkat 0.037
usia 0.012
Tiga skor tertinggi : durasi_kunjungan, kunjungan_mingguan, riwayat_pembelian
Informatif sejati : durasi_kunjungan, kunjungan_mingguan, riwayat_pembelian
Kesimpulan: tiga peringkat teratas cocok seluruhnya dengan informatif sejati.
(c) Fitur terpilih SelectKBest(k=3): kunjungan_mingguan, durasi_kunjungan, riwayat_pembelian
(d) Matriks korelasi dua fitur kandidat:
pendapatan pengeluaran
pendapatan 1.000 0.955
pengeluaran 0.955 1.000
Korelasi r = 0.955; |r| > 0.90 -> salah satu kolom dibuang (redundan)Mari kita telaah bagian-bagian utama skrip di atas:
- Baris 11–20 (
X, y = make_classification(...)): dataset 120 baris × 8 kolom dibangun denganrandom_state=42;shuffle=Falsedann_redundant=0menjadikan indeks 0–2 satu-satunya pembawa sinyal. - Baris 22–32 (
nama_fitur = ...): nama domain dipetakan ke tiap kolom, dan daftarinformatif_sejatimencatat kebenaran dari generator — pembanding bagi hasil metode. - Baris 34–48: varians tiap fitur dicetak, lalu
VarianceThresholddidemokan dengan satu kolom tambahanfitur_konstanyang nilainya bergoyang sangat kecil di sekitar 5,0. - Baris 50–60 (
skor_mi = mutual_info_classif(...)): skor mutual information dihitung denganrandom_state=42, diurutkan menurun, lalu dibandingkan dengan daftar informatif sejati. - Baris 62–67 (
pemilih = SelectKBest(...)): selektor dengank=3di-fit, danget_support()menandai kolom mana yang lolos. - Baris 69–78: dua fitur buatan —
pendapatandanpengeluaranyang merupakan kombinasi linier plus derau — dihitung korelasinya sebagai contoh redundansi.
Membaca Hasil: Skor Menyingkap Struktur Data #
Bacaan output bagian (a) memberi pelajaran pertama: varians tidak mengenali informativitas. Fitur kunjungan_mingguan memang bervarians terbesar (3,998), tetapi riwayat_pembelian yang informatif justru bervarians terkecil (0,737) — sementara usia yang murni derau bervarians 1,021. VarianceThreshold kemudian menunjukkan fungsi aslinya: dari 9 kolom (8 fitur + fitur_konstan), hanya kolom buatan itu yang dibuang.
Bagian (b) adalah momen pembuktian. Tiga skor mutual information tertinggi jatuh pada kunjungan_mingguan (0,438), riwayat_pembelian (0,281), dan durasi_kunjungan (0,079) — tepat ketiga fitur informatif sejati, tanpa metode ini pernah diberi tahu. Lima fitur derau tertinggal di bawah 0,06. Perhatikan bahwa durasi_kunjungan informatif namun sinyalnya paling tipis (0,079, hanya sedikit di atas derau tertinggi 0,057) — batas antara “informatif lemah” dan “derau” pada data nyata memang tidak selalu lebar, dan itulah mengapa k yang terlalu kecil berisiko memangkas fitur yang masih berguna. Bagian (c) menegaskan hal yang sama dari sisi selektor: SelectKBest mempertahankan tepat ketiga fitur itu.
Bagian (d) memperlihatkan redundansi dalam angka: korelasi pendapatan–pengeluaran mencapai 0,955, jauh di atas ambang praktis 0,9. Salah satu kolom layak dibuang, dan pilihan jatuh pada pendapatan bila pengeluaran lebih murah dikumpulkan langsung dari sistem pembayaran — keputusan operasional di atas keputusan statistik.
Kekuatan filter sekaligus batasnya terlihat jelas: seluruh penilaian dilakukan per fitur secara terpisah, tanpa pernah bertanya bagaimana model justru memakai kombinasi fitur. Chapter berikutnya, Feature Selection dengan RFE, menyerahkan jabatan juri kepada model itu sendiri.
Referensi Resmi #
- scikit-learn — User Guide: Feature selection — penjelasan resmi seluruh metode filter, wrapper, dan embedded.
- sklearn.feature_selection.SelectKBest — API Reference — selektor k-terbaik yang dipakai pada contoh.
- sklearn.feature_selection.mutual_info_classif — API Reference — skor mutual information untuk klasifikasi.
- sklearn.feature_selection.VarianceThreshold — API Reference — penyaring ambang varians.