Satu model yang dilatih sendirian akan selalu membawa kebiasaan galatnya sendiri: decision tree terlalu dalam menghafal derau, regresi logistik tidak bisa menangkap pola nonlinier, k-nearest neighbors goyah pada data berdimensi tinggi. Ensemble learning mengambil jalan berbeda — alih-alih mencari satu model sempurna, pendekatan ini melatih beberapa model lalu menggabungkan hasilnya. Ide dasarnya sama seperti meminta pendapat tiga dokter dengan latar belakang berbeda sebelum mengambil keputusan diagnosis: kesalahan masing-masing berbeda arah, sehingga keputusan gabungan lebih stabil daripada keputusan satu orang. Chapter ini membedah mengapa strategi tersebut bekerja secara matematis, apa syarat yang harus dipenuhi, dan tiga keluarga besar ensemble yang akan kita jelajahi sepanjang Section ini.

Kebijaksanaan Kerumunan dan Teorema Juri #

Intuisi ensemble berakar pada kebijaksanaan kerumunan (wisdom of crowds): agregat dari banyak penilaian yang beragam sering lebih akurat daripada penilaian individu terbaik di dalam kelompok. Versi formalnya dikenal sebagai teorema juri Condorcet. Versi ringkasnya begini: jika setiap voter menjawab benar dengan peluang p > 0,5, maka peluang jawaban benar dari suara mayoritas naik seiring bertambahnya jumlah voter — asalkan penilaian mereka saling independen.

Mari kita hitung untuk tiga voter dengan peluang galat p = 0,3 (berarti peluang benar 0,7 — jauh dari sempurna). Suara mayoritas baru salah ketika minimal dua voter salah bersamaan, sehingga peluang galat mayoritas mengikuti distribusi binomial:

text
P(galat mayoritas) = 3 * p^2 * (1 - p) + p^3 = 0.216

Angka 0,216 lebih kecil daripada 0,3 — mayoritas tiga voter menenggelamkan galat individu. Perhatikan juga bahwa penurunan ini bukan linear: menambah voter ke grup yang sama-sama salah tidak menolong. Seluruh keuntungan berasal dari peluang kecil para voter salah bersamaan.

Dua Syarat: Akurasi dan Keragaman #

Rumus di atas menyimpan dua syarat tersembunyi yang menentukan hidup-mati sebuah ensemble. Pertama, tiap anggota harus lebih akurat daripada tebakan acak. Jika p melebihi 0,5 — peluang galat lebih besar daripada peluang benar — suara mayoritas justru mengunci kesalahan secara sistematis; tiga voter dengan akurasi 40% tidak membentuk ensemble, hanya komite yang kompak dalam kekeliruan. Kedua, galat anggota tidak boleh berkorelasi sempurna. Galat yang identik saling meniadakan apa pun? Justru sebaliknya: galat yang sama pada saat yang sama tidak punya pasangan lawan untuk diadu, sehingga agregatnya sama persis dengan satu anggota.

Syarat kedua inilah yang paling sering dilupakan praktisi pemula: tiga model identik yang dilatih pada data yang sama akan menghasilkan prediksi yang sama, dan suara mayoritasnya bukan peningkatan apa pun. Kita akan melihat bukti angkanya pada contoh kode di bawah.

Tiga Keluarga Ensemble #

Dari dua syarat tersebut, komunitas machine learning menurunkan tiga keluarga besar metode ensemble. Ketiganya berbeda cara menciptakan keragaman dan berbeda jenis galat yang ditekan — mengingat dekomposisi galat menjadi bias dan varians yang kita bahas pada Chapter Bias-Variance Tradeoff.

KeluargaPola gabungSumber keragamanGalat yang ditekan
BaggingParalel: model dilatih pada salinan bootstrap, hasil dirata-rataSampel bootstrap + subset fiturVarians (model tidak stabil)
BoostingSekuensial: tiap model memperbaiki galat gabungan sebelumnyaFokus pada data yang masih salahBias (model terlalu sederhana)
Voting/StackingHeterogen: model berbeda jenis digabung lewat suara atau meta-learnerPerbedaan algoritme itu sendiriKombinasi bias dan varians

Bagging menyerang model yang bergoyang (varians tinggi): pohon keputusan dalam rata-rata dengan salinan data yang digeser acak. Boosting menyerang model yang terlalu kaku (bias tinggi): rantai model belajar dari sisa galat pendahulunya, dibahas tuntas pada Chapter Gradient Boosting. Voting dan stacking menggabungkan model yang sepenuhnya berbeda jenis — topik Chapter Voting dan Stacking di ujung Section ini.

Bukti Angka: Mayoritas Tiga Voter #

Teori di atas layak diuji dengan angka nyata. Skrip berikut menyusun tiga eksperimen dalam satu berkas: aritmetika Condorcet, mayoritas tiga pohon beragam pada 40 sampel uji tetap, lalu kasus tiga voter identik sebagai pembanding.

python
# Ensemble learning: mengapa gabungan model "lemah" bisa mengalahkan
# model tunggal, dan mengapa diversitas menjadi syarat mutlaknya.
# Bagian 1: aritmetika mayoritas ala teorema juri Condorcet (tanpa data).
# Bagian 2: tiga voter beragam divoting pada 40 sampel uji tetap.
# Bagian 3: tiga voter identik -> diversitas nol, hasil juga nol.

import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

# --- Bagian 1: aritmetika suara mayoritas -----------------------------
# Skenario: 3 voter, masing-masing salah dengan peluang p.
# Jika galat mereka independen, suara mayoritas salah hanya saat
# minimal 2 dari 3 voter salah bersamaan (distribusi binomial).
p = 0.30
galat_mayoritas_independen = 3 * p**2 * (1 - p) + p**3
print("Bagian 1 - aritmetika suara mayoritas (3 voter):")
print(f"  {'peluang galat tiap voter':<42} : {p:.3f}")
print(f"  {'peluang galat mayoritas (independen)':<42} : "
      f"{galat_mayoritas_independen:.3f}")
print(f"  {'peluang galat mayoritas (seragam)':<42} : {p:.3f}")

# --- Bagian 2: tiga voter beragam pada data tetap ---------------------
X, y = make_classification(n_samples=240, n_features=10, n_informative=6,
                           n_redundant=2, flip_y=0.08, class_sep=0.9,
                           random_state=42)
X_latih, X_uji, y_latih, y_uji = train_test_split(
    X, y, test_size=40, random_state=42)

# Tiga pohon kecil dengan konfigurasi berbeda: inilah sumber diversitas.
konfigurasi = [
    ("pohon A (depth=3, fitur=5)", dict(max_depth=3, max_features=5)),
    ("pohon B (depth=3, fitur=4)", dict(max_depth=3, max_features=4)),
    ("pohon C (depth=6, fitur=3)", dict(max_depth=6, max_features=3)),
]

print("\nBagian 2 - tiga voter beragam (40 sampel uji tetap):")
prediksi = []
for nama, params in konfigurasi:
    voter = DecisionTreeClassifier(random_state=42, **params)
    voter.fit(X_latih, y_latih)
    pred = voter.predict(X_uji)
    prediksi.append(pred)
    n_galat = int(np.sum(pred != y_uji))
    print(f"  {nama:<28} : akurasi {np.mean(pred == y_uji):.3f} "
          f"({n_galat} galat)")

suara_mayoritas = (np.sum(prediksi, axis=0) >= 2).astype(int)
n_galat_mayoritas = int(np.sum(suara_mayoritas != y_uji))
print(f"  {'suara mayoritas 3 voter':<28} : akurasi "
      f"{np.mean(suara_mayoritas == y_uji):.3f} ({n_galat_mayoritas} galat)")

galat = np.array([pred != y_uji for pred in prediksi])
n_galat_bersama = int(np.all(galat, axis=0).sum())
print(f"  {'galat bersama ketiga voter':<28} : {n_galat_bersama} sampel")

# --- Bagian 3: tiga voter identik, diversitas nol ---------------------
# Konfigurasi sama pada data sama menghasilkan pohon yang sama persis,
# sehingga "mayoritas" hanyalah gema dari satu model tunggal.
print("\nBagian 3 - tiga voter identik (tanpa diversitas):")
pohon_identik = DecisionTreeClassifier(max_depth=6, random_state=42)
pohon_identik.fit(X_latih, y_latih)
pred_identik = [pohon_identik.predict(X_uji) for _ in range(3)]
semua_sama = all(np.array_equal(pred_identik[0], p) for p in pred_identik[1:])
print(f"  {'prediksi ketiganya identik':<28} : {semua_sama}")
suara_mayoritas_identik = (np.sum(pred_identik, axis=0) >= 2).astype(int)
n_galat_identik = int(np.sum(suara_mayoritas_identik != y_uji))
print(f"  {'akurasi voter tunggal':<28} : "
      f"{np.mean(pred_identik[0] == y_uji):.3f} ({n_galat_identik} galat)")
print(f"  {'akurasi suara mayoritas':<28} : "
      f"{np.mean(suara_mayoritas_identik == y_uji):.3f} ({n_galat_identik} galat)")

Output yang Dihasilkan:

text
Bagian 1 - aritmetika suara mayoritas (3 voter):
  peluang galat tiap voter                   : 0.300
  peluang galat mayoritas (independen)       : 0.216
  peluang galat mayoritas (seragam)          : 0.300

Bagian 2 - tiga voter beragam (40 sampel uji tetap):
  pohon A (depth=3, fitur=5)   : akurasi 0.775 (9 galat)
  pohon B (depth=3, fitur=4)   : akurasi 0.775 (9 galat)
  pohon C (depth=6, fitur=3)   : akurasi 0.700 (12 galat)
  suara mayoritas 3 voter      : akurasi 0.800 (8 galat)
  galat bersama ketiga voter   : 6 sampel

Bagian 3 - tiga voter identik (tanpa diversitas):
  prediksi ketiganya identik   : True
  akurasi voter tunggal        : 0.700 (12 galat)
  akurasi suara mayoritas      : 0.700 (12 galat)

Mari kita telaah bagian-bagian kunci skrip tersebut:

  1. Baris 16–22 (aritmetika Condorcet): variabel p menyimpan peluang galat tiap voter, lalu rumus binomial menghitung peluang minimal dua dari tiga voter salah. Ketiga baris print menampilkan pembandingannya secara berdampingan.
  2. Baris 25–29 (dataset tetap): make_classification(random_state=42) menyediakan 240 sampel, dan train_test_split(..., test_size=40, random_state=42) menyisihkan 40 sampel uji yang sama pada setiap eksekusi — angka akurasi kita pun dapat direproduksi.
  3. Baris 32–36 (sumber keragaman): ketiga pohon sengaja diberi max_depth dan max_features berbeda. Parameter max_features membatasi fitur yang boleh dipertimbangkan tiap pemecahan, sehingga tiap pohon “melihat” masalah dari sudut berbeda.
  4. Baris 40–47 (akurasi individu): tiap voter dilatih lalu dihitung akurasi dan jumlah galatnya pada 40 sampel uji. Ketiganya berada di kisaran 0,700–0,775 — model lemah yang jauh dari sempurna.
  5. Baris 49–52 (suara mayoritas): np.sum(prediksi, axis=0) >= 2 menjumlahkan prediksi tiga voter per sampel; nilai 2 atau 3 berarti mayoritas memilih kelas 1. Bandingkan hasilnya dengan baris sebelumnya.
  6. Baris 54–56 (galat bersama): matriks galat menandai posisi salah tiap voter, lalu np.all(galat, axis=0) menghitung sampel yang salah menurut ketiganya sekaligus — inti galat berkorelasi yang tidak bisa divoting habis.
  7. Baris 62–66 (voter identik): satu pohon dilatih lalu prediksinya digandakan tiga kali; np.array_equal memverifikasi ketiganya memang identik.
  8. Baris 67–72 (mayoritas identik): mekanisme voting yang sama diterapkan pada tiga salinan identik — hasilnya tidak bergerak sedikit pun dari model tunggalnya.

Membaca Hasil Eksperimen #

Output Bagian 2 memperlihatkan pelajaran inti ensemble dalam empat angka. Pohon A dan B masing-masing salah pada 9 sampel, pohon C pada 12 sampel, dan suara mayoritas hanya salah pada 8 sampel — akurasi gabungan 0,800 mengungguli anggota terbaiknya yang 0,775. Kuncinya ada pada baris “galat bersama”: dari 9–12 galat per anggota, hanya 6 sampel yang salah menurut ketiganya sekaligus. Galat 6 sampel itu tertanam dalam data (batas kelas yang memang tumpang tindih akibat flip_y) dan tidak akan hilang oleh voting; galat sisanya terdistribusi berbeda pada tiap pohon sehingga kalah suara.

Bagian 3 menampilkan kebalikannya. Tiga voter identik menghasilkan prediksi yang persis sama, dan suara mayoritasnya mencatat akurasi 0,700 — angka yang sama byte demi byte dengan model tunggalnya. Dua belas galat terjadi serentak pada ketiga voter karena ketiganya adalah satu model yang sama; tidak ada mekanisme yang bisa meniadakan galat dengan salinannya sendiri.

Keragaman pada contoh kita baru datang dari perbedaan max_features dan max_depth — mekanisme paling sederhana. Keluarga bagging mengambil ide ini jauh lebih serius dengan sampel bootstrap dan subset fitur acak pada skala industri, yang mengantarkan kita ke Chapter Bagging dan Random Forest.

Referensi Resmi #