Pencarian hyperparameter secara manual, yaitu mencoba nilai satu per satu tanpa catatan, sulit dilaporkan dan sulit diulang. Grid search dan random search menggantinya dengan prosedur sistematis, yaitu menetapkan ruang pencarian, mengukur setiap kandidat dengan cross-validation, dan melaporkan kandidat dengan skor terbaik. Topik ini menjalankan keduanya pada ruang hyperparameter yang sama untuk DecisionTreeClassifier di atas dataset breast cancer, kemudian membaca pola hasilnya yang makin menurun seiring bertambahnya kandidat.
Grid search dan hitungannya#
Grid search menetapkan daftar nilai untuk setiap hyperparameter yang ditela, lalu mencoba seluruh kombinasi yang mungkin dibentuk dari daftar-daftar tersebut. Setiap kombinasi disebut kandidat, dan jumlah kandidatnya adalah hasil kali panjang setiap daftar. Untuk tiga daftar berukuran , , dan , ukuran ruang pencariannya adalah
Contoh pada praktik di bawah menggunakan daftar berisi 5, 3, dan 3 pilihan sehingga ruangnya memuat kandidat.
Setiap kandidat dinilai dengan k-fold cross-validation, sehingga jumlah pelatihan yang benar-benar dijalankan adalah jumlah kandidat dikali jumlah fold, yaitu pelatihan. Pada setiap kandidat, data latih dibagi menjadi lima fold dan pelatihan berjalan lima kali dengan fold validasi yang bergilir. Skor kandidatnya adalah rata-rata kelima skor validasi itu, dan kandidat dengan rata-rata tertinggi dinyatakan sebagai yang terbaik.
Akibat inilah grid cepat membesar. Menambah satu nilai pada satu daftar berarti menambah satu kandidat untuk setiap kombinasi daftar lainnya, sehingga ukuran grid berlipat, bukan hanya bertambah satu. Setelah pencarian selesai, opsi refit=True bawaan melatih ulang kandidat terbaik pada seluruh data latih sehingga best_estimator_ langsung siap digunakan untuk prediksi.
Random search dan pemberian sampelnya#
Random search tidak menjanjikan meliputi seluruh kombinasi, melainkan mengambil sejumlah kandidat secara acak dari ruang pencarian. Anggarannya ditetapkan langsung melalui n_iter, sedangkan random_state memastikan sampel yang sama dapat direproduksi. Daftar nilai pada param_distributions diperlakukan sebagai distribusi seragam, yaitu setiap nilainya berpeluang terpilih yang sama, dan rentang kontinu diberikan melalui distribusi scipy.stats seperti randint atau uniform.
Efisiensi random search berasal dari satu fakta praktis, yaitu tidak semua hyperparameter sama pentingnya terhadap skor. Apabila hanya satu hyperparameter yang benar-benar mengubah kinerja, kelemahan grid menjadi terlihat. Grid dengan enam nilai pada tiga hyperparameter hanya menguji enam nilai pada hyperparameter penting itu, karena setiap nilainya dipasangkan dengan seluruh kombinasi dua hyperparameter lainnya. Sebaliknya, 36 kandidat acak dari rentang kontinu menguji 36 nilai berbeda pada hyperparameter tersebut. Sampel acak dengan demikian menjangkau lebih banyak variasi pada sumbu yang berpengaruh tanpa membayar kombinasi sumbu yang tidak berpengaruh.
Konsekuensinya, jaminan kelengkapan tidak diperoleh. Random search tidak menjamin kandidat terbaik di seluruh ruang ikut tercoba, sehingga skornya bisa saja sedikit di bawah grid yang lengkap. Sebagai gantinya, biaya pencarian menjadi pasti karena ditentukan n_iter, bukan oleh ukuran ruang, dan ruang pencarian dapat dibuat seluas apa pun tanpa risiko ledakan kombinasi.
Praktik pada ruang yang sama#
Skrip grid-vs-random.py menetapkan satu ruang pencarian yang sama untuk DecisionTreeClassifier pada dataset breast cancer, yaitu max_depth dengan lima pilihan, min_samples_split dan min_samples_leaf masing-masing tiga pilihan. GridSearchCV dengan cv=5 menela seluruh 45 kandidat, sedangkan RandomizedSearchCV mengambil 12 kandidat acak dengan random_state=42. Skrip lalu mencetak lima kandidat terbaik versi grid beserta hasil pencarian acak. Skrip dijalankan dari direktori topiknya dengan python3 -B grid-vs-random.py.
"""Membandingkan GridSearchCV dan RandomizedSearchCV pada ruang pencarian yang sama."""
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
from sklearn.tree import DecisionTreeClassifier
X, y = load_breast_cancer(return_X_y=True)
# ruang pencarian yang sama untuk kedua metode
param_grid = {
"max_depth": [2, 4, 6, 8, None],
"min_samples_split": [2, 5, 10],
"min_samples_leaf": [1, 3, 5],
}
# ukuran grid = hasil kali banyaknya pilihan setiap hyperparameter
ukuran = 1
for pilihan in param_grid.values():
ukuran *= len(pilihan)
print(f"Ukuran grid : {ukuran} kandidat")
grid = GridSearchCV(
DecisionTreeClassifier(random_state=42), param_grid, cv=5
)
grid.fit(X, y)
hasil = grid.cv_results_
print(f"GridSearchCV : {len(hasil['params'])} kandidat x {grid.cv} fold = {len(hasil['params']) * grid.cv} pelatihan")
skor = hasil["mean_test_score"]
urutan = np.argsort(skor)[::-1]
print("Lima kandidat terbaik versi grid (skor CV rata-rata):")
for posisi in urutan[:5]:
print(f" {skor[posisi]:.4f} {hasil['params'][posisi]}")
terbaik = skor.max()
dalam_selisih = int(np.sum((terbaik - skor) <= 0.01))
print(f"Kandidat dalam 0.01 dari skor terbaik: {dalam_selisih} dari {len(skor)}")
print()
acak = RandomizedSearchCV(
DecisionTreeClassifier(random_state=42),
param_distributions=param_grid,
n_iter=12,
cv=5,
random_state=42,
)
acak.fit(X, y)
print(f"RandomizedSearchCV : 12 dari {ukuran} kandidat, {12 * 5} pelatihan")
print(f"Skor terbaik versi acak : {acak.best_score_:.4f}")
print(f"Parameter terbaik versi acak: {acak.best_params_}")Ukuran grid : 45 kandidat
GridSearchCV : 45 kandidat x 5 fold = 225 pelatihan
Lima kandidat terbaik versi grid (skor CV rata-rata):
0.9315 {'max_depth': None, 'min_samples_leaf': 5, 'min_samples_split': 10}
0.9315 {'max_depth': None, 'min_samples_leaf': 5, 'min_samples_split': 5}
0.9315 {'max_depth': None, 'min_samples_leaf': 5, 'min_samples_split': 2}
0.9315 {'max_depth': 8, 'min_samples_leaf': 5, 'min_samples_split': 2}
0.9315 {'max_depth': 8, 'min_samples_leaf': 5, 'min_samples_split': 5}
Kandidat dalam 0.01 dari skor terbaik: 22 dari 45
RandomizedSearchCV : 12 dari 45 kandidat, 60 pelatihan
Skor terbaik versi acak : 0.9315
Parameter terbaik versi acak: {'min_samples_split': 5, 'min_samples_leaf': 5, 'max_depth': 6}Pola menurun terbaca langsung dari daftar kandidat terbaik. Kelima kandidat atas mencetak skor identik 0.9315 dan semuanya menggunakan min_samples_leaf=5, yang berarti banyak kombinasi berujung pada pohon yang praktis setara. Pernyataan itu diperkuat baris terakhir bagian grid, yaitu 22 dari 45 kandidat berada dalam selisih 0.01 dari skor terbaik, sehingga separuh ruang pencarian memberikan manfaat yang nyaris sama. Setiap kandidat tambahan setelah titik ini hanya memperkecil selisih yang sudah tipis, dan di situlah pola hasil yang makin menurun.
Hasil random search melengkapi pembacaan tersebut. Dengan hanya 12 kandidat atau 60 pelatihan, pencarian acak menemukan skor terbaik yang sama sebesar 0.9315, karena banyak wilayah ruang pencarian menghasilkan pohon dengan kualitas yang nyaris sama. Grid tetap unggul ketika peta lengkap diperlukan untuk membaca efek tiap hyperparameter, sedangkan random search unggul ketika anggaran pelatihan terbatas dan ruang pencariannya lebar. Keduanya menggunakan fold cross-validation yang sama sehingga skornya dapat dibandingkan secara langsung.
Kesalahan umum#
- Menulis daftar nilai tanpa menghitung konsekuensinya. Satu nilai tambahan pada
max_depthlangsung menambah sembilan kandidat pada grid tiga hyperparameter lainnya, sehingga total pelatihan melonjak tanpa disadari. Perbaikannya adalah menghitung hasil kali panjang daftar sebelum pencarian dijalankan. - Membandingkan skor grid dan random yang menggunakan pembagi fold berbeda. Skor antar pembagi berbeda tidak sebanding, sehingga kesimpulan perbandingannya tidak sah. Kedua pencari diberi nilai
cvyang sama sebelum skornya dibandingkan. - Menala pada seluruh data lalu melaporkan
best_score_sebagai kinerja akhir. Angka itu condong terlalu tinggi karena kandidat yang menang dinilai oleh data yang sama yang memilihnya. Data uji disisihkan lebih dahulu, atau estimasinya diambil melalui nested cross-validation. - Menjalankan random search tanpa
random_state. Sampel kandidat berubah pada setiap eksekusi, sehingga angka yang dilaporkan tidak dapat direproduksi dan laporannya tidak dapat diperiksa ulang.random_statedipatok tetap sebelum pencarian dijalankan. - Memberikan rentang kontinu pada hyperparameter yang menuntut bilangan bulat. Distribusi
uniformmenghasilkan nilai desimal, sedangkanmax_depthhanya menerima bilangan bulat atauNone, sehingga pelatihan gagal dengan pesan parameter tidak valid. Rentang bilangan bulat diberikan melaluirandint.
Ringkasan#
- Grid search menela seluruh kombinasi ruang pencarian dengan biaya jumlah kandidat dikali jumlah fold, sedangkan random search mengambil
n_itersampel acak dengan anggaran yang pasti. - Jumlah kandidat grid adalah hasil kali panjang daftar setiap hyperparameter, sehingga ukuran grid naik berlipat saat satu daftar bertambah.
- Pada praktik, kelima kandidat terbaik berbagi skor 0.9315 dan 22 dari 45 kandidat berada dalam 0.01 dari skor terbaik, yaitu manfaat kandidat tambahan yang makin menurun.
- Random search dengan 12 kandidat mencapai skor terbaik yang sama karena banyak wilayah ruang menghasilkan pohon yang praktis setara.
Referensi#
- Tuning the hyper-parameters of an estimator — scikit-learn — Panduan resmi grid search, random search, dan cara membaca hasil penalaan.
- sklearn.model_selection.GridSearchCV — scikit-learn
— Dokumentasi penalaan seluruh kombinasi beserta opsi
refitdan atributbest_estimator_. - sklearn.model_selection.RandomizedSearchCV — scikit-learn
— Dokumentasi penalaan berbasis sampel acak dengan
n_iterdanrandom_state.