Model machine learning yang kita bangun bukan untuk menjawab soal yang sudah dilihatnya, melainkan soal yang belum pernah muncul — transaksi berikutnya, pasien berikutnya, rumah berikutnya. Kemampuan itu disebut generalisasi, dan kegagalan generalisasi adalah sumber masalah paling mahal dalam proyek machine learning. Kegagalannya datang dalam dua bentuk: model yang terlalu kaku sehingga pola aslinya tidak tertangkap (underfitting), dan model yang terlalu lentur sehingga ikut menghafal derau data (overfitting). Chapter ini membedah keduanya lewat eksperimen yang bisa Anda jalankan sendiri — satu kurva, tiga tingkat kompleksitas, dan tabel angka yang menampar.

Menghafal Bukan Berarti Paham #

Mari kita mulai dari masalahnya. Data dunia nyata selalu memuat dua komponen bercampur: pola yang ingin kita pelajari, dan derau (noise) acak yang tidak ingin kita pelajari — kesalahan pencatatan, faktor tak teramati, kebetulan sampling. Sebuah model yang bekerja baik harus menangkap polanya dan mengabaikan deraunya. Model yang ikut mempelajari derau akan tampak hebat di atas data yang dipakainya belajar, lalu jatuh begitu diuji pada data baru; ia seperti murid yang menghafal kunci jawaban satu paket soal, bukan memahami materinya.

Tingkat “kelenturan” model — istilah teknisnya kapasitas atau kompleksitas — adalah tuas utama yang menentukan posisi kita di antara dua jurang:

  • Underfitting (kapasitas terlalu rendah): model terlalu sederhana untuk menangkap pola. Kesalahannya bersifat sistematis — kurva yang seharusnya melengkung dipaksa lurus. Hasilnya buruk pada data latih dan data uji. Istilah informalnya: model terlalu bias pada satu bentuk sederhana.
  • Overfitting (kapasitas terlalu tinggi): model punya ruang cukup untuk menyalin data latih titik demi titik, termasuk deraunya. Kurvanya berayun liar menembus tiap titik latih. Hasilnya nyaris sempurna pada data latih tetapi runyuh pada data uji. Istilah informalnya: model memiliki variance tinggi — prediksinya sangat bergantung pada sampel kebetulan mana yang dipakai melatihnya; ganti sampelnya, kurvanya berubah drastis.

Ujian Klasik: Kurva Sinus Berderau #

Eksperimen standar untuk memperlihatkan kedua jurang ini dirancang sebagai berikut. Buat data dari fungsi sin(x) ditambah derau Gaussian — polanya sinus, deraunya acak. Sisihkan 20 titik sebagai data latih dan 20 titik baru sebagai data uji, keduanya dari proses yang sama. Lalu latih tiga model regresi polinomial berbeda derajat: 1 (garis lurus), 3 (kurva landai), dan 15 (kurva berparameter banyak), masing-masing dibangun dari gabungan PolynomialFeatures dan LinearRegression dalam sebuah Pipeline.

python
# Demonstrasi klasik underfitting vs overfitting pada data fungsi sinus berderau.
# Derajat polinomial 1 (terlalu sederhana), 3 (pas), dan 15 (terlalu kompleks)
# dibandingkan lewat MSE pada data latih dan data uji.

import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures


def buat_data(n, rng):
    """Ambil n titik dari kurva sin(x) dengan derau Gaussian tetap."""
    x = rng.uniform(-3.0, 3.0, size=n)
    derau = rng.normal(loc=0.0, scale=0.4, size=n)
    y = np.sin(x) + derau
    return x.reshape(-1, 1), y


rng = np.random.default_rng(42)
X_latih, y_latih = buat_data(20, rng)  # 20 titik untuk melatih model
X_uji, y_uji = buat_data(20, rng)  # 20 titik baru untuk menguji

print(f"{'derajat':>7} {'parameter':>10} {'MSE latih':>11} {'MSE uji':>11}")
for derajat in [1, 3, 15]:
    model = make_pipeline(
        PolynomialFeatures(degree=derajat, include_bias=False),
        LinearRegression(),
    )
    model.fit(X_latih, y_latih)
    mse_latih = mean_squared_error(y_latih, model.predict(X_latih))
    mse_uji = mean_squared_error(y_uji, model.predict(X_uji))
    # 1 fitur input -> derajat d menghasilkan d + 1 parameter (d pangkat + intercept)
    print(f"{derajat:>7} {derajat + 1:>10} {mse_latih:>11.3f} {mse_uji:>11.3f}")

print()
print("Pola khasnya: MSE latih turun terus seiring derajat naik,")
print("sedangkan MSE uji mula-mula turun lalu melonjak saat model terlalu kompleks.")

Output yang Dihasilkan:

text
derajat  parameter   MSE latih     MSE uji
      1          2       0.156       0.160
      3          4       0.070       0.105
     15         16       0.011 2426126.947

Pola khasnya: MSE latih turun terus seiring derajat naik,
sedangkan MSE uji mula-mula turun lalu melonjak saat model terlalu kompleks.

Bedah kode baris demi baris:

  1. Baris 12–17 (def buat_data): satu fungsi pembangkit data. Baris 14 mengambil n titik x acak seragam di rentang [-3, 3]; baris 15 menambahkan derau Gaussian bersimpangan 0,4; baris 16 menggabungkannya menjadi y = sin(x) + derau. Karena rng dibuat berseed, data yang sama lahir di setiap eksekusi.
  2. Baris 20–22: rng = np.random.default_rng(42) menjadi sumber ketertentuan seluruh eksperimen. Baris 21 menarik 20 titik latih; baris 22 menarik 20 titik uji dari aliran acak yang sama — kedua himpunan berbeda, tetapi keduanya dari proses pembangkit yang identik, sehingga perbandingannya adil.
  3. Baris 25–29 (loop dan make_pipeline): tiap derajat membangun pipeline dua langkah — PolynomialFeatures mengubah satu fitur x menjadi x, x², ..., x^d, lalu LinearRegression mencari koefisien terbaik lewat least squares. Derajat adalah hyperparameter kapasitas: derajat 15 memberi model 16 parameter untuk 20 titik data.
  4. Baris 30–32: model dilatih hanya pada data latih, lalu MSE dihitung dua kali — pada data latih (seberapa rapat kurvanya menempel pada bahan belajar) dan pada data uji (seberapa jauh generalisasinya).
  5. Baris 33–34: tabel dicetak dengan kolom jumlah parameter sebagai ukuran kompleksitas yang eksplisit.

Membaca Tabel: Tanda Tangan Overfitting #

Tiga baris output di atas memuat seluruh cerita bab ini:

  • Derajat 1 — underfitting: MSE latih 0,156 dan MSE uji 0,160, keduanya tinggi dan hampir setara. Garis lurus memang tidak bisa mengikuti lengkung sinus; kesalahan didominasi bentuk model yang salah, bukan derau. Ciri underfitting persis seperti ini: buruk di mana-mana.
  • Derajat 3 — pas: MSE latih 0,070, MSE uji 0,105. Kurva kubik cukup lentur mengikuti sinus namun terlalu kaku untuk menyalin derau. Selisih latih-uji kecil, dan MSE uji terendah di antara ketiganya.
  • Derajat 15 — overfitting: MSE latih 0,011 (nyaris sempurna) tetapi MSE uji 2.426.126,947. Inilah tanda tangan overfitting: MSE latih turun terus sementara MSE uji meroket. Akar dari MSE uji tersebut sekitar 1.557 — padahal seluruh nilai y hanya bergerak di rentang kira-kira −1,4 sampai 1,4. Prediksinya melesat ribuan kali lipat dari rentang data.

Mengapa derajat 15 jatuh seburuk itu? Dengan 16 parameter dan hanya 20 titik latih, kurva polinomial berhasil menembus atau mendekati setiap titik latih — termasuk deraunya. Untuk melakukannya, koefisien x^13 hingga x^15 membengkak besar; di antara titik-titik latih yang berjarak, suku-suku pangkat tinggi itu saling mengalahkan dan membuat kurva berayun dengan amplitudo ribuan. Titik uji yang jatuh di wilayah ayunan itu menerima prediksi mustahil — dan kuadrat kesalahannya membengkak ke jutaan. Model tidak gagal karena kurang belajar; ia gagal karena belajar berlebihan.

Tuas Perbaikan yang Tersedia #

Ketika tanda tangan overfitting (atau underfitting) terbaca, kita memiliki repertoar tindakan standar yang teruji:

TindakanCara kerjaMembantuDibahas di
Tambah data latihDerau rata-rata saling menghapus; kurva dipaksa konsistenOverfittingSection Evaluasi (learning curve)
Turunkan kompleksitasDerajat/pohon lebih dangkal mengurangi kapasitas menghafalOverfittingSection Regresi dan Klasifikasi
Regularisasi (Ridge, Lasso)Hukuman atas koefisien besar menahan ayunan kurvaOverfittingChapter Regularisasi: Ridge, Lasso, dan Elastic Net
Naikkan kompleksitas / fitur baruModel kaku diberi bentuk yang lebih kayaUnderfittingSection Feature Engineering
Cross-validationEstimasi generalisasi lebih stabil sebelum memilih modelKeduanya (mencegah pilihan keliru)Chapter Cross-Validation

Ada satu disiplin terakhir yang menopang semua eksperimen di atas: seluruh angka yang kita baca — data latih 0,156, akurasi 0,974 pada chapter sebelumnya — hanya bermakna karena hasilnya sama setiap kali dijalankan ulang. Bagaimana kendali atas keacakan itu bekerja adalah bahasan penutup section ini, Chapter Reproduksibilitas dengan random_state.

Referensi Resmi #