Menambah jumlah tahap boosting tidak selalu memperbaiki hasil, karena skor data validasi memburuk setelah ensemble mulai menghafal derau. Topik ini membahas early stopping, yaitu mekanisme yang menghentikan pelatihan ketika tidak ada perbaikan lagi pada data validasi, lalu menggunakan model dari tahap terbaiknya. Bagian praktik menggunakan XGBoost pada dataset breast cancer dengan pembagian data latih, data validasi, dan data uji sebesar 60/20/20.
Mengapa lebih banyak tahap bisa memburuk#
Error pada data latih hampir selalu menurun setiap kali tahap bertambah, karena setiap pohon baru dilatih untuk mengoreksi sisa kesalahan yang tersisa pada data latih. Konsekuensinya, angka error data latih tidak pernah menjadi sinyal kapan harus berhenti, karena angka itu terus membaik tanpa memandang kualitas model. Nilai yang dikejar sebenarnya adalah kinerja pada data baru, dan kinerja itu terbaca pada data validasi. Kurva metrik validasi menurun pada tahap awal, melandai di sekitar titik terbaiknya, lalu naik kembali ketika model mulai menghafal derau. Posisi titik terbaik tersebut bergantung pada dataset, learning rate, dan ukuran pohon, sehingga tidak dapat ditebak hanya dengan melihat jumlah tahap.
Risikonya berlaku dua arah. Pelatihan yang berhenti terlalu cepat menghasilkan underfitting, sedangkan pelatihan yang berjalan terlalu lama menghasilkan overfitting sekaligus membuang waktu komputasi. Cara manual, yaitu melatih beberapa nilai n_estimators lalu membandingkan skornya, memakan waktu karena setiap konfigurasi harus dilatih dari awal. Early stopping menyelesaikan masalah tersebut dalam satu pelatihan karena keputusan berhenti diambil dari data yang memang disediakan untuk pemantauan.
Mekanisme early stopping pada XGBoost#
Early stopping memerlukan satu himpunan data khusus pemantauan, kemudian menghitung metrik pada himpunan itu di setiap tahap. Parameter early_stopping_rounds=20 berarti pelatihan berhenti apabila metrik validasi tidak membaik selama 20 tahap berturut-turut. Himpunan pemantauan diberikan melalui eval_set pada saat fit, dan data itu tidak digunakan untuk menyesuaikan parameter model karena murni berfungsi sebagai alat ukur. Metrik yang dipantau ditentukan melalui eval_metric, misalnya logloss untuk klasifikasi.
Ketika pelatihan berhenti, XGBoost menyimpan best_iteration, yaitu tahap dengan metrik validasi terbaik, dan prediksi selanjutnya menggunakan model dari tahap tersebut secara bawaan. Jaminan tersebut membuat anggaran n_estimators boleh diberi nilai besar, misalnya 500, karena pelatihan akan berhenti sendiri di sekitar titik optimalnya. Kombinasi anggaran besar dan early stopping menjadi cara yang lazim untuk menentukan panjang ensemble tanpa penalaan panjang.
Metrik per tahap yang terekam juga bermanfaat untuk dibaca ulang. Metode evals_result mengembalikan seluruh riwayat metrik, sehingga kurva validasi dapat diperiksa untuk melihat kapan perbaikannya melandai. Nilai early_stopping_rounds yang terlalu besar membuat pelatihan berjalan lama setelah titik terbaik, sedangkan nilai yang terlalu kecil berisiko berhenti sebelum titik itu. Karena itu, 20 sampai 50 tahap menjadi jarak penantian yang umum.
Praktik lengkap dengan pembagian 60/20/20#
Pembagian data dilakukan dua tahap agar ketiga peran tetap terpisah. Data uji sebesar 20 persen disisihkan lebih dahulu dan disimpan tanpa disentuh sampai penilaian akhir. Sisa 80 persen dipecah lagi menjadi data latih dan data validasi dengan porsi 25 persen dari sisanya, sehingga komposisi akhirnya 60/20/20.
Argumen stratify digunakan pada kedua pemecahan agar proporsi kelas tetap terjaga. Jumlah baris yang dicetak skrip memastikan pembagiannya benar, yaitu 341 baris latih, 114 baris validasi, dan 114 baris uji dari total 569 baris. Skrip berikut melatih model dengan anggaran 500 tahap, lalu melaporkan hasilnya.
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from xgboost import XGBClassifier
X, y = load_breast_cancer(return_X_y=True)
# pemisahan pertama: sisihkan data uji 20 persen, disimpan tanpa disentuh
X_sisa, X_uji, y_sisa, y_uji = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=42
)
# pemisahan kedua: 25 persen dari sisa menjadi data validasi (hasil akhir 60/20/20)
X_latih, X_valid, y_latih, y_valid = train_test_split(
X_sisa, y_sisa, test_size=0.25, stratify=y_sisa, random_state=42
)
print(f"Baris data latih = {X_latih.shape[0]}, validasi = {X_valid.shape[0]}, uji = {X_uji.shape[0]}")
model = XGBClassifier(
n_estimators=500, learning_rate=0.05, max_depth=3,
eval_metric="logloss", early_stopping_rounds=20,
n_jobs=1, random_state=42
)
# verbose=False menahan cetakan logloss per tahap selama fit berlangsung
model.fit(X_latih, y_latih, eval_set=[(X_valid, y_valid)], verbose=False)
# indeks pada evals_result dimulai dari 0, sehingga tahap ke-t berada pada indeks t-1
hasil = model.evals_result()["validation_0"]["logloss"]
for no_tahap in (1, 25, 50, 100, 150, 192, 212):
print(f"Tahap {no_tahap:>3} : logloss validasi = {hasil[no_tahap - 1]:.5f}")
print(f"Jumlah tahap yang dijalankan : {len(hasil)} dari anggaran 500")
print(f"Model terbaik ada di tahap : {model.best_iteration + 1}")
print(f"Akurasi data uji : {model.score(X_uji, y_uji):.4f}")Baris data latih = 341, validasi = 114, uji = 114
Tahap 1 : logloss validasi = 0.62259
Tahap 25 : logloss validasi = 0.23269
Tahap 50 : logloss validasi = 0.14912
Tahap 100 : logloss validasi = 0.12562
Tahap 150 : logloss validasi = 0.11821
Tahap 192 : logloss validasi = 0.11403
Tahap 212 : logloss validasi = 0.11569
Jumlah tahap yang dijalankan : 212 dari anggaran 500
Model terbaik ada di tahap : 192
Akurasi data uji : 0.9561Pelatihan berhenti setelah 212 tahap, jauh sebelum anggaran 500 tahap habis. Penghentian dini tersebut menunjukkan bahwa mekanisme ini bekerja. Model terbaik berada pada tahap 192, dan logloss validasi sesudahnya memburuk dari 0.11403 menjadi 0.11569 pada tahap terakhir. Prediksi data uji menggunakan 192 pohon terbaik tersebut, bukan seluruh 212 tahap yang dijalankan. Akurasi data uji 0.9561 baru dihitung setelah seluruh keputusan selesai, karena data uji tidak disentuh sejak pemisahan pertama.
Kesalahan umum#
- Menggunakan data uji sebagai
eval_set. Pemilihan tahap terbaik lalu berpijak pada data uji, sehingga data uji kehilangan netralitasnya dan menimbulkan kebocoran data (data leakage). Skor akhirnya menjadi terlalu optimis karena data uji ikut menentukan keputusan pelatihan, bukan hanya mengukur. Pemantauan hanya boleh menggunakan data validasi yang disisihkan sebelum pelatihan. - Menyamakan nilai atribut
best_iterationdengan nomor tahap. Atribut itu berbasis indeks yang dimulai dari nol, sehingga skrip di atas menambahkan satu sebelum mencetak nomor tahapnya. Kesalahan ini tidak memunculkan pesan error, tetapi seluruh pembacaan tahap bergeser satu posisi sehingga kesimpulannya keliru. - Menyetel
early_stopping_roundsterlalu ketat, misalnya 3 sampai 5, pada model dengan learning rate kecil. Peningkatan metrik antartahap memang lambat pada learning rate tersebut, sehingga pelatihan berhenti pada fluktuasi kecil sebelum titik terbaik tercapai. Solusinya berupa jarak penantian yang lebih longgar, misalnya 20 sampai 50 tahap, sesuai uraian pada bagian mekanisme early stopping.
Ringkasan#
- Error data latih terus menurun dengan tambahan tahap, sedangkan metrik validasi turun, melandai, lalu memburuk, sehingga jumlah tahap terbaik tidak dapat ditebak dari awal.
- Early stopping memantau metrik pada data validasi di setiap tahap dan menghentikan pelatihan bila tidak ada perbaikan selama
early_stopping_roundstahap berturut-turut. - Prediksi menggunakan model pada
best_iteration, sehingga anggarann_estimatorsboleh besar tanpa risiko berjalan terlalu jauh. - Data uji tetap di luar seluruh proses, karena pemantauan menggunakan data validasi dan penilaian akhir dilakukan satu kali di akhir.
Referensi#
- Using the Scikit-Learn Estimator Interface — XGBoost
— Halaman resmi antarmuka scikit-learn XGBoost, termasuk
eval_setdan early stopping. - XGBoost Parameters — DMLC
— Parameter
early_stopping_rounds,eval_metric, danetapada pelatihan XGBoost. - sklearn.model_selection.train_test_split — scikit-learn
— Dokumentasi fungsi pemecahan data dengan parameter
test_size,random_state, danstratify.