Semua metrik sejauh ini menjawab “seberapa baik model sekarang”. Learning curve menjawab pertanyaan yang lebih strategis: “ke mana performa ini akan bergerak jika kita menambah data — dan apakah menambah data memang obat yang tepat?”. Kurva pembelajaran menggambar skor data latih dan skor data validasi sebagai fungsi dari jumlah sampel latih, dan bentuk kedua kurva tersebut ternyata mengandung diagnosis yang hampir selalu bisa dibaca langsung: model yang menghafal, model yang terlalu sederhana, dan titik di mana data tambahan berhenti membayar. Chapter ini membedah fungsi learning_curve dari scikit-learn, membaca dua pola klasik dalam angka, lalu menutup dengan tabel keputusan pola → diagnosis → tindakan.
Cara Kerja learning_curve #
Fungsi learning_curve dari sklearn.model_selection menjalankan eksperimen bertingkat: untuk tiap ukuran latih yang diminta (misalnya 30, 60, 120, 180, 240 sampel), fungsi ini melatih model pada subset sebesar tersebut, mengukur skor pada data latih itu sendiri dan pada data validasi, lalu mengulang prosesnya untuk tiap fold cross-validation. Hasilnya tiga array: ukuran latih efektif, matriks skor latih berdimensi (jumlah ukuran) x (jumlah fold), dan matriks skor validasi dengan bentuk yang sama. Rata-rata per baris (.mean(axis=1)) menghasilkan dua kurva yang siap dibaca — kita tidak menggambar grafiknya, tetapi mencetak angkanya.
Satu detail mekanis perlu dicatat: karena tiap putaran memakai cross-validation 5-fold, satu fold selalu disisihkan sebagai validasi, sehingga ukuran latih maksimum adalah 4/5 dari data. Pada data 300 sampel, baris terakhir tabel kita berhenti di 240 sampel latih — bukan 300.
Dua Pola yang Bisa Didiagnosis #
Pola pertama: selisih (gap) besar, skor latih tinggi. Kurva latih nempel di angka tinggi (misalnya 1,000 untuk pohon keputusan yang tumbuh penuh) sementara kurva validasi tertinggal jauh di bawah. Model cukup fleksibel untuk menghafal data latih berapa pun ukurannya, tetapi hafalan tersebut tidak menular ke data baru. Diagnosisnya adalah overfitting — didominasi variansi. Menambah data akan menutup gap perlahan, tetapi obat yang lebih murah dan lebih cepat adalah menurunkan kapasitas model: membatasi kedalaman pohon, menambah regularisasi, atau memilih model yang lebih sederhana.
Pola kedua: kedua kurva rendah dan berdempetan. Kurva latih dan kurva validasi berjarak sempit, keduanya berhenti di level yang tidak memuaskan. Model sudah terlalu sederhana untuk menangkap pola data — diagnosisnya underfitting — didominasi bias. Yang penting: menambah data TIDAK akan menolong pola ini; kedua kurva sudah sejajar, sehingga data baru hanya memperpanjang garis datar yang sama. Obatnya ada di sisi model dan fitur: model yang lebih ekspresif, fitur baru yang lebih informatif, atau rekayasa fitur yang lebih baik.
Kapan Menambah Data Membayar #
Kurva pembelajaran juga menjawab pertanyaan anggaran. Bila kurva validasi masih menanjak tajam di ujung kanan grafik, data tambahan kemungkinan besar masih memperbaiki performa — pengumpulan data layak didanai. Bila kurva validasi sudah mendatar, data tambahan bernilai kecil; anggaran lebih baik dialihkan ke sumber masalah yang lain. Mari kita lihat keduanya sekaligus pada dua model atas data yang sama.
# Learning curve: skor latih vs skor validasi seiring bertambahnya data.
# Dua pola berbeda muncul dari dua model pada data yang sama.
import numpy as np
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold, learning_curve
from sklearn.tree import DecisionTreeClassifier
# Data sintetis tetap berisi 300 sampel dengan derau label (flip_y)
# supaya skor tidak pernah menyentuh 1.000 dan polanya terlihat jelas.
X, y = make_classification(
n_samples=300,
n_features=10,
n_informative=6,
n_redundant=2,
flip_y=0.10,
random_state=42,
)
# Dengan 5-fold CV, satu fold selalu disisihkan sebagai validasi,
# sehingga ukuran data latih maksimum = 4/5 x 300 = 240 sampel.
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
ukuran_latih = np.array([30, 60, 120, 180, 240])
kandidat = [
("LogisticRegression", LogisticRegression(max_iter=1000, random_state=42)),
("DecisionTree tumbuh penuh", DecisionTreeClassifier(random_state=42)),
]
for nama, estimator in kandidat:
ukuran, skor_latih, skor_validasi = learning_curve(
estimator, X, y, train_sizes=ukuran_latih, cv=cv,
scoring="accuracy", n_jobs=1,
)
rata_latih = skor_latih.mean(axis=1)
rata_validasi = skor_validasi.mean(axis=1)
print(f"== {nama} ==")
print(" n | latih | validasi | gap")
for n, a, b in zip(ukuran, rata_latih, rata_validasi):
print(f" {n:>5d} | {a:.3f} | {b:.3f} | {a - b:.3f}")
print()Output yang Dihasilkan:
== LogisticRegression ==
n | latih | validasi | gap
30 | 0.940 | 0.793 | 0.147
60 | 0.900 | 0.823 | 0.077
120 | 0.867 | 0.820 | 0.047
180 | 0.853 | 0.827 | 0.027
240 | 0.833 | 0.827 | 0.007
== DecisionTree tumbuh penuh ==
n | latih | validasi | gap
30 | 1.000 | 0.743 | 0.257
60 | 1.000 | 0.797 | 0.203
120 | 1.000 | 0.773 | 0.227
180 | 1.000 | 0.850 | 0.150
240 | 1.000 | 0.803 | 0.197Mari kita telaah bagian-bagian pentingnya:
- Baris 12–19 (
make_classification): 300 sampel denganflip_y=0.10menaruh lantai galat di atas nol — data memang mengandung 10% label yang tertukar sehingga tidak ada model yang mencapai akurasi 1,000. - Baris 23–24 (
cvdanukuran_latih): fold diacak dan dikuncirandom_state=42; daftar ukuran latih naik dari 30 sampai 240 — batas maksimum 5-fold CV. - Baris 26–29 (
kandidat): dua estimator dengan struktur berlawanan —LogisticRegressionyang kapasitasnya terbatas, danDecisionTreeClassifiertanpa batas kedalaman yang kapasitasnya sangat besar. - Baris 32–35 (
learning_curve(...)): satu pemanggilan mengembalikan tiga array;skor_latihdanskor_validasiberbentuk matriks5 ukuran x 5 fold. - Baris 36–37 (
.mean(axis=1)): rata-rata antar fold per ukuran mengubah matriks menjadi dua kurva angka; kolomgappada baris 42 mencetak selisihnya sebagai alat diagnosis utama.
Bacaan output pertama — LogisticRegression — adalah pola konvergensi. Dari 30 sampai 240 sampel, skor latih turun (0,940 → 0,833) sementara skor validasi naik (0,793 → 0,827); gap menutup dari 0,147 menjadi 0,007. Kedua kurva berakhir rendah dan berdempet — model ini sudah mentok di kemampuannya menangkap pola dari 10 fitur tersebut. Data tambahan akan mempersempit gap sedikit lagi lalu berhenti; kenaikan berarti harus datang dari fitur atau model yang lebih ekspresif.
Bacaan output kedua — DecisionTree tumbuh penuh — adalah pola gap yang gigih. Skor latih tertahan di 1,000 pada setiap ukuran: pohon tanpa batas kedalaman selalu sanggup menghafal seluruh data latih, berapa pun banyaknya. Sementara itu skor validasi berkisar 0,74–0,85 dan gap tetap lebar (0,15–0,26) bahkan di 240 sampel. Diagnosis: overfitting yang didominasi variansi. Menambah data ke beberapa ribu sampel akan menutup gap pelan-pelan, tetapi membatasi kedalaman pohon atau memangkasnya jauh lebih murah. Bandingkan tabel di bawah:
| Pola pada learning curve | Diagnosis | Obat yang tepat |
|---|---|---|
| Latih tinggi, validasi jauh di bawah, gap lebar | Overfitting (variansi tinggi) | Turunkan kapasitas: batasi kedalaman, regularisasi, model lebih sederhana |
| Kedua kurva rendah dan berdempet | Underfitting (bias tinggi) | Naikkan kapasitas atau perbaiki fitur; data tambahan tidak menolong |
| Validasi masih menanjak di ujung kanan | Data belum cukup | Kumpulkan data tambahan — investasi masih membayar |
| Validasi mendatar di ujung kanan | Data sudah cukup | Hentikan pengumpulan; perbaiki sumber masalah yang lain |
Kedua pola tersebut — gap lebar karena variansi, kurva datar karena bias — adalah wajah dari kompromi fundamental yang mengatur semua model machine learning. Bab penutup section ini membongkar kompromi itu sampai ke rumusnya: bias-variance tradeoff, tempat bias, variansi, dan derau dipisahkan menjadi tiga angka yang bisa dihitung sendiri pada Chapter Bias-Variance Tradeoff.
Referensi Resmi #
- Validation curves: plotting scores to evaluate models — user guide resmi learning curve dan validation curve.
- sklearn.model_selection.learning_curve — API Reference — dokumentasi fungsi beserta bentuk array yang dikembalikan.