Faza 02 · lecția 12

Reglarea hiperparametrilor

Scopul lecției: Hiperparametrii sunt reglajele pe care le faceți înainte de începerea antrenării. Reglarea lor bună face diferența dintre un model mediocru și unul excelent.

Versiunea curentă AlexBred.com: primele 100 de lecții ale programului în limba română.

Curs
AI Engineering from Scratch
Fază
Bazele învățării automate
Lectură
28 min.
Verificat
Cuprinsul lecției
  1. Obiective de învățare
  2. Problema
  3. Conceptul
  4. Parametri în raport cu hiperparametrii
  5. Căutarea pe grilă
  6. Căutarea aleatoare
  7. Optimizarea bayesiană
  8. Oprirea timpurie
  9. Planificatoare ale ratei de învățare
  10. Importanța hiperparametrilor
  11. Strategie practică
  12. Integrarea validării încrucișate
  13. Sfaturi practice
  14. Construiți
  15. Pasul 1: Căutare pe grilă de la zero
  16. Pasul 2: Căutare aleatoare de la zero
  17. Pasul 3: Optimizare bayesiană (simplificată)
  18. Pasul 4: Comparați toate metodele
  19. Folosiți
  20. Optuna în practică
  21. Optuna cu eliminare timpurie
  22. Instrumentele de reglare încorporate în sklearn
  23. Greșeli frecvente în reglarea hiperparametrilor
  24. Exerciții
  25. Termeni-cheie
  26. Lecturi suplimentare

Hiperparametrii sunt reglajele pe care le faceți înainte de începerea antrenării. Reglarea lor bună face diferența dintre un model mediocru și unul excelent.

Tip: Construire Limbaj: Python Cerințe preliminare: Faza 2, lecția 11 (Metode de ansamblu) Durată: ~90 de minute

Obiective de învățare

  • Implementați de la zero căutarea pe grilă, căutarea aleatoare și optimizarea bayesiană și comparați eficiența lor în raport cu numărul de evaluări
  • Explicați de ce căutarea aleatoare depășește căutarea pe grilă atunci când majoritatea hiperparametrilor au o dimensionalitate efectivă redusă
  • Construiți o buclă de optimizare bayesiană folosind un model surogat și o funcție de achiziție pentru a ghida căutarea
  • Proiectați o strategie de reglare a hiperparametrilor care evită supraînvățarea setului de validare printr-o validare încrucișată corespunzătoare

Problema

Modelul dumneavoastră de gradient boosting are o rată de învățare, un număr de arbori, o adâncime maximă, un număr minim de eșantioane pe frunză, un raport de subeșantionare și un raport de eșantionare a coloanelor. Aceștia sunt șase hiperparametri. Dacă fiecare are câte 5 valori rezonabile, grila are 5^6 = 15.625 de combinații. Antrenarea fiecăreia durează 10 secunde. Încercarea tuturor necesită 43 de ore de calcul.

Căutarea pe grilă este abordarea evidentă și cea mai slabă la scară mare. Căutarea aleatoare obține rezultate mai bune cu mai puțin calcul. Optimizarea bayesiană se descurcă și mai bine, învățând din evaluările anterioare. Cunoașterea strategiei potrivite și a hiperparametrilor care contează efectiv economisește zile de timp GPU irosit.

Notă tehnică a traducerii: Superioritatea căutării aleatoare sau bayesiene nu este universală; ea depinde de spațiul de căutare, buget, dimensionalitatea efectivă, zgomot și costul evaluării. Căutarea pe grilă poate rămâne potrivită pentru unul sau doi hiperparametri discreți ori când trebuie evaluată exhaustiv o grilă mică.

Conceptul

Parametri în raport cu hiperparametrii

Parametrii sunt învățați în timpul antrenării (ponderi, deplasări, praguri de divizare). Hiperparametrii sunt stabiliți înainte de începerea antrenării și controlează modul în care are loc învățarea.

Hiperparametru Ce controlează Interval tipic
Rata de învățare Mărimea pasului la fiecare actualizare de la 0,001 la 1,0
Numărul de arbori/epoci Durata antrenării de la 10 la 10.000
Adâncimea maximă Complexitatea modelului de la 1 la 30
Regularizarea (lambda) Prevenirea supraînvățării de la 0,0001 la 100
Dimensiunea lotului Zgomotul estimării gradientului de la 16 la 512
Rata de dropout Fracțiunea de neuroni eliminați de la 0,0 la 0,5

Căutarea pe grilă

Căutarea pe grilă evaluează fiecare combinație a valorilor specificate. Este exhaustivă și ușor de înțeles, dar costul său crește exponențial odată cu numărul de hiperparametri.

Grilă pentru 2 hiperparametri:

  learning_rate: [0.01, 0.1, 1.0]
  max_depth:     [3, 5, 7]

  Evaluări: 3 x 3 = 9 combinații

  (0.01, 3)  (0.01, 5)  (0.01, 7)
  (0.1,  3)  (0.1,  5)  (0.1,  7)
  (1.0,  3)  (1.0,  5)  (1.0,  7)

Căutarea pe grilă are un defect fundamental: dacă un hiperparametru contează, iar celălalt nu, majoritatea evaluărilor sunt irosite. Din 9 evaluări obțineți doar 3 valori unice ale parametrului important.

Căutarea aleatoare

Căutarea aleatoare eșantionează hiperparametrii din distribuții, nu dintr-o grilă. Cu același buget de 9 evaluări, obțineți 9 valori unice ale fiecărui hiperparametru.

Диаграмма к уроку «Reglarea hiperparametrilor»

De ce căutarea aleatoare depășește grila (Bergstra și Bengio, 2012):

  • Majoritatea hiperparametrilor au o dimensionalitate efectivă redusă. De obicei, doar 1–2 dintre cei 6 hiperparametri contează pentru o anumită problemă.
  • Căutarea pe grilă irosește evaluări pe dimensiuni neimportante.
  • Căutarea aleatoare acoperă mai dens dimensiunile importante pentru același buget.
  • După 60 de încercări aleatoare, aveți o probabilitate de 95% de a găsi un punct aflat în limita a 5% față de optim (dacă acesta există în spațiul de căutare).

Notă tehnică a traducerii: Dimensionalitatea efectivă redusă descrie funcția de răspuns într-un anumit set de date, nu fiecare hiperparametru în mod intrinsec. Calculul pentru 60 de încercări este 1 - 0,95^60 ≈ 95,4%: el reprezintă probabilitatea de a eșantiona cel puțin o dată regiunea celor mai bune 5% din distribuția de căutare, nu garanția unei valori a obiectivului aflate la cel mult 5% de optim.

Optimizarea bayesiană

Căutarea aleatoare ignoră rezultatele. Ea nu învață că ratele de învățare mari provoacă divergență ori că adâncimea 3 depășește în mod consecvent adâncimea 10. Optimizarea bayesiană folosește evaluările anterioare pentru a decide unde să caute în continuare.

Диаграмма к уроку «Reglarea hiperparametrilor»

Cele două componente-cheie:

Modelul surogat: Un model cu evaluare ieftină (de obicei, un proces gaussian) care aproximează funcția-obiectiv costisitoare. El oferă atât o predicție, cât și o estimare a incertitudinii în orice punct al spațiului de căutare.

Funcția de achiziție: Decide unde să se facă următoarea evaluare prin echilibrarea exploatării (căutarea în apropierea punctelor bune cunoscute) cu explorarea (căutarea acolo unde incertitudinea este mare). Alegeri frecvente:

  • Îmbunătățirea așteptată (Expected Improvement, EI): Câtă îmbunătățire față de cea mai bună valoare actuală așteptăm în acest punct?
  • Limita superioară de încredere (Upper Confidence Bound, UCB): Predicția plus un multiplu al incertitudinii. O valoare UCB mai mare înseamnă fie un punct promițător, fie unul neexplorat.
  • Probabilitatea de îmbunătățire (Probability of Improvement, PI): Care este probabilitatea ca acest punct să depășească cea mai bună valoare actuală?

Optimizarea bayesiană găsește de obicei hiperparametri mai buni decât căutarea aleatoare cu de 2–5 ori mai puține evaluări. Costul suplimentar al ajustării modelului surogat este neglijabil față de antrenarea modelului propriu-zis.

Notă tehnică a traducerii: Reducerea de 2–5 ori nu este o garanție generală. Avantajul depinde de cât de bine modelează surogatul obiectivul și de calitatea funcției de achiziție; pentru obiective ieftine, multe observații ori spații dificil de modelat, costul surogatului poate să nu fie neglijabil. Definiția UCB de mai sus presupune maximizarea; pentru minimizare se folosește de regulă o limită inferioară sau se schimbă semnul obiectivului.

Oprirea timpurie

Nu fiecare rulare de antrenare trebuie să se încheie. Dacă o configurație este clar slabă după 10 epoci, opriți-o și treceți la următoarea. Aceasta este oprirea timpurie în contextul căutării hiperparametrilor.

Strategii:

  • Bazată pe răbdare: Opriți dacă pierderea de validare nu s-a îmbunătățit timp de N epoci consecutive
  • Eliminare după mediană: Opriți dacă rezultatul intermediar al încercării este mai slab decât mediana încercărilor finalizate la același pas
  • Hyperband: Alocați bugete mici multor configurații, apoi măriți progresiv bugetul celor mai bune

Hyperband este deosebit de eficient. Începe cu 81 de configurații a câte 1 epocă, păstrează treimea cea mai bună, le acordă câte 3 epoci, păstrează din nou treimea cea mai bună și continuă în același fel. Astfel găsește configurații bune de 10–50 de ori mai repede decât evaluarea tuturor configurațiilor cu bugetul complet.

Notă tehnică a traducerii: Succesiunea 81→27→9→3→1 descrie un singur bracket agresiv de Successive Halving pentru R=81 și eta=3. Hyperband rulează mai multe astfel de bracket-uri, cu compromisuri diferite între numărul de configurații și bugetul inițial. Accelerarea de 10–50 de ori este dependentă de problemă și nu este garantată, mai ales când performanța la buget mic prezice slab performanța finală.

Planificatoare ale ratei de învățare

Rata de învățare este aproape întotdeauna cel mai important hiperparametru. În loc să o mențină fixă, planificatoarele o ajustează în timpul antrenării.

Planificator Formulă Când se utilizează
Scădere în trepte Înmulțire cu 0,1 la fiecare N epoci Antrenarea clasică a CNN-urilor
Atenuare cosinusoidală lr * 0.5 * (1 + cos(pi * t / T)) Alegere modernă implicită
Încălzire + atenuare Creștere liniară, apoi atenuare cosinusoidală Transformere
Un ciclu Creștere, apoi scădere într-un singur ciclu Convergență rapidă
Reducere la platou Reducere cu un factor când metrica stagnează Alegere implicită sigură

Importanța hiperparametrilor

Nu toți hiperparametrii contează în aceeași măsură. Cercetările asupra pădurilor aleatoare (Probst et al., 2019) și gradient boosting arată tipare consecvente:

Importanță mare:

  • Rata de învățare (reglați-o întotdeauna prima)
  • Numărul de estimatori/epoci (folosiți oprirea timpurie în locul reglării)
  • Intensitatea regularizării

Importanță medie:

  • Adâncimea maximă/numărul de straturi
  • Numărul minim de eșantioane pe frunză/degradarea ponderilor
  • Raportul de subeșantionare

Importanță redusă:

  • Numărul maxim de caracteristici (pentru păduri aleatoare)
  • Alegerea concretă a funcției de activare
  • Dimensiunea lotului (într-un interval rezonabil)

Reglați mai întâi parametrii importanți și lăsați-i pe ceilalți la valorile implicite.

Notă tehnică a traducerii: Importanța hiperparametrilor este specifică algoritmului, implementării, distribuției datelor, metricii și domeniului de căutare. Studiul Probst et al. analizează „tunability” în contexte experimentale concrete și nu justifică o clasificare universală; de exemplu, max_features, dimensiunea lotului ori funcția de activare pot deveni decisive în alte regimuri.

Strategie practică

Диаграмма к уроку «Reglarea hiperparametrilor»

Fluxul concret:

  1. Începeți cu valorile implicite ale bibliotecii. Acestea sunt alese de practicieni cu experiență și vă duc adesea la 80% din rezultat.
  2. Căutare aleatoare grosieră. Intervale largi, 20–50 de încercări. Folosiți oprirea timpurie pentru a elimina rapid rulările slabe.
  3. Analizați rezultatele. Ce hiperparametri sunt corelați cu performanța? Restrângeți spațiul de căutare.
  4. Căutare fină. Optimizare bayesiană sau căutare aleatoare focalizată în spațiul restrâns. 50–100 de încercări.
  5. Reantrenați pe toate datele de antrenare cu cei mai buni hiperparametri găsiți.

Notă tehnică a traducerii: Procentele și numerele de încercări sunt euristici, nu bugete validate universal. Valorile implicite pot fi baze bune, dar nu au o garanție de „80%”. La reantrenare, „toate datele de antrenare” poate include porțiunea folosită la validare, dar nu setul de testare păstrat pentru evaluarea finală.

Integrarea validării încrucișate

Reglarea hiperparametrilor pe o singură împărțire de validare este riscantă. Cei mai buni hiperparametri s-ar putea supraînvăța pe pliul de validare concret. Validarea încrucișată imbricată rezolvă această problemă folosind două bucle:

  • Bucla exterioară (evaluare): împarte datele în antrenare+validare și testare. Raportează performanța fără deplasare.
  • Bucla interioară (reglare): împarte antrenarea+validarea în antrenare și validare. Găsește cei mai buni hiperparametri.

Диаграмма к уроку «Reglarea hiperparametrilor»

Fiecare pliu exterior își găsește independent cei mai buni hiperparametri. Scorurile exterioare reprezintă o estimare fără deplasare a performanței de generalizare.

Cu sklearn:

from sklearn.model_selection import cross_val_score, GridSearchCV
from sklearn.ensemble import GradientBoostingRegressor

inner_cv = GridSearchCV(
    GradientBoostingRegressor(),
    param_grid={
        "learning_rate": [0.01, 0.05, 0.1],
        "max_depth": [2, 3, 5],
        "n_estimators": [50, 100, 200],
    },
    cv=5,
    scoring="neg_mean_squared_error",
)

outer_scores = cross_val_score(
    inner_cv, X, y, cv=5, scoring="neg_mean_squared_error"
)

print(f"Nested CV MSE: {-outer_scores.mean():.4f} +/- {outer_scores.std():.4f}")

Aceasta este costisitoare (5 pliuri exterioare x 5 pliuri interioare x 27 de puncte ale grilei = 675 de ajustări de model), dar vă oferă o estimare de încredere a performanței. Folosiți-o când raportați rezultatele finale în articole sau când miza deciziei este mare.

Notă tehnică a traducerii: Validarea imbricată estimează performanța întregii proceduri de selectare a modelului și reduce optimismul selecției, dar „fără deplasare” nu trebuie citit drept garanție exactă pentru orice eșantion finit ori schemă de pliuri. Cu refit=True implicit, exemplul efectuează și câte o ajustare finală a celui mai bun model în fiecare pliu exterior, deci 675 nu include toate cele 5 reantrenări. outer_scores.std() este abaterea standard între pliuri, nu eroare standard sau interval de încredere.

Sfaturi practice

Începeți cu rata de învățare. Ea este întotdeauna cel mai important hiperparametru pentru metodele bazate pe gradient. O rată de învățare slabă face ca orice altceva să devină irelevant. Fixați ceilalți hiperparametri la valorile implicite și parcurgeți mai întâi rata de învățare.

Folosiți distribuții log-uniforme pentru rata de învățare și regularizare. Diferența dintre 0,001 și 0,01 contează la fel de mult ca diferența dintre 0,1 și 1,0. Căutarea liniară irosește bugetul la capătul cu valori mari.

Folosiți oprirea timpurie în loc să reglați n_estimators. Pentru boosting și rețele neurale, setați n_estimators sau numărul de epoci la o valoare mare și lăsați oprirea timpurie să decidă când să se oprească. Astfel eliminați un hiperparametru din căutare.

Alocarea bugetului. Cheltuiți 60% din bugetul de reglare pe cei mai importanți 2 hiperparametri. Cheltuiți restul de 40% pe toate celelalte. Primii 2 explică cea mai mare parte a variației performanței.

Scara contează. Nu căutați niciodată dimensiunea lotului pe o scară logaritmică (16, 32, 64 sunt valori potrivite). Căutați întotdeauna rata de învățare pe o scară logaritmică. Potriviți distribuția de căutare cu modul în care hiperparametrul afectează modelul.

Tip de model Hiperparametri principali Căutare recomandată Buget
Pădure aleatoare n_estimators, max_depth, min_samples_leaf Căutare aleatoare, 50 de încercări Mic (antrenare rapidă)
Gradient boosting learning_rate, n_estimators, max_depth Bayesiană, 100 de încercări + oprire timpurie Mediu
Rețea neurală learning_rate, weight_decay, batch_size Bayesiană sau aleatoare, peste 100 de încercări Mare (antrenare lentă)
SVM C, gamma (nucleu RBF) Grilă pe scară logaritmică, 25–50 de încercări Mic (2 parametri)
Lasso/Ridge alpha Căutare 1D pe scară logaritmică, 20 de încercări Foarte mic
XGBoost learning_rate, max_depth, subsample, colsample Bayesiană, 100–200 de încercări + oprire timpurie Mediu

Dacă aveți îndoieli: folosiți căutarea aleatoare cu un număr de încercări egal cu de 2 ori numărul hiperparametrilor (de exemplu, 6 hiperparametri = minimum 12 încercări). Veți fi surprinși cât de des căutarea aleatoare cu 50 de încercări depășește o căutare pe grilă proiectată cu atenție.

Notă tehnică a traducerii: Formulările „întotdeauna”, „niciodată”, raportul 60/40 și regula de 2 ori numărul hiperparametrilor sunt euristici. Rata de învățare, dimensiunea lotului și numărul de iterații interacționează cu optimizatorul și cu bugetul de calcul; oprirea timpurie nu este strict superioară în orice problemă și poate introduce propriul criteriu de reglare.

k-fold-cv

Construiți

Pasul 1: Căutare pe grilă de la zero

Codul din code/tuning.py implementează de la zero căutarea pe grilă, căutarea aleatoare și un optimizator bayesian simplu.

def grid_search(model_fn, param_grid, X_train, y_train, X_val, y_val):
    keys = list(param_grid.keys())
    values = list(param_grid.values())
    best_score = -float("inf")
    best_params = None
    n_evals = 0

    for combo in itertools.product(*values):
        params = dict(zip(keys, combo))
        model = model_fn(**params)
        model.fit(X_train, y_train)
        score = evaluate(model, X_val, y_val)
        n_evals += 1

        if score > best_score:
            best_score = score
            best_params = params

    return best_params, best_score, n_evals

Pasul 2: Căutare aleatoare de la zero

def random_search(model_fn, param_distributions, X_train, y_train,
                  X_val, y_val, n_iter=50, seed=42):
    rng = np.random.RandomState(seed)
    best_score = -float("inf")
    best_params = None

    for _ in range(n_iter):
        params = {k: sample(v, rng) for k, v in param_distributions.items()}
        model = model_fn(**params)
        model.fit(X_train, y_train)
        score = evaluate(model, X_val, y_val)

        if score > best_score:
            best_score = score
            best_params = params

    return best_params, best_score, n_iter

Notă tehnică a traducerii: Aceste două fragmente ilustrează o interfață generică, dar nu coincid cu semnăturile din fișierul complet code/tuning.py: acolo funcțiile construiesc direct GBMForTuning, folosesc neg_mse și sample_param și returnează istoricul, nu doar numărul de evaluări. Fragmentele nu sunt autonome fără definițiile evaluate, sample, importurile și modelul furnizate separat.

Pasul 3: Optimizare bayesiană (simplificată)

Ideea de bază: ajustați un proces gaussian la perechile observate (hiperparametru, scor), apoi folosiți o funcție de achiziție pentru a decide unde să căutați în continuare.

class SimpleBayesianOptimizer:
    def __init__(self, search_space, n_initial=5):
        self.search_space = search_space
        self.n_initial = n_initial
        self.X_observed = []
        self.y_observed = []

    def _kernel(self, x1, x2, length_scale=1.0):
        dists = np.sum((x1[:, None, :] - x2[None, :, :]) ** 2, axis=2)
        return np.exp(-0.5 * dists / length_scale ** 2)

    def _fit_gp(self, X_new):
        X_obs = np.array(self.X_observed)
        y_obs = np.array(self.y_observed)
        y_mean = y_obs.mean()
        y_centered = y_obs - y_mean

        K = self._kernel(X_obs, X_obs) + 1e-4 * np.eye(len(X_obs))
        K_star = self._kernel(X_new, X_obs)

        L = np.linalg.cholesky(K)
        alpha = np.linalg.solve(L.T, np.linalg.solve(L, y_centered))
        mu = K_star @ alpha + y_mean

        v = np.linalg.solve(L, K_star.T)
        var = 1.0 - np.sum(v ** 2, axis=0)
        var = np.maximum(var, 1e-6)

        return mu, var

    def _expected_improvement(self, mu, var, best_y):
        sigma = np.sqrt(var)
        z = (mu - best_y) / (sigma + 1e-10)
        ei = sigma * (z * norm_cdf(z) + norm_pdf(z))
        return ei

    def suggest(self):
        if len(self.X_observed) < self.n_initial:
            return sample_random(self.search_space)

        candidates = [sample_random(self.search_space) for _ in range(500)]
        X_cand = np.array([to_vector(c) for c in candidates])
        mu, var = self._fit_gp(X_cand)
        ei = self._expected_improvement(mu, var, max(self.y_observed))
        return candidates[np.argmax(ei)]

    def observe(self, params, score):
        self.X_observed.append(to_vector(params))
        self.y_observed.append(score)

Surogatul GP oferă două lucruri în fiecare punct candidat: un scor prezis (mu) și o incertitudine (var). Îmbunătățirea așteptată le echilibrează: favorizează punctele în care modelul prezice scoruri mari SAU în care incertitudinea este mare. La început, majoritatea punctelor au incertitudine mare, astfel încât optimizatorul explorează. Mai târziu, se concentrează asupra regiunii celei mai promițătoare.

Notă tehnică a traducerii: Fragmentul depinde de funcțiile nedefinite aici norm_cdf, norm_pdf, sample_random și to_vector; fișierul complet folosește alte nume și metode interne. În plus, implementarea completă aproximează CDF-ul normal prin 0.5 * (1 + tanh(x * 0.7978845608)), care nu este CDF-ul normal exact și poate distorsiona valorile EI. Acesta este un demonstrator didactic, nu un proces gaussian robust pentru producție.

Pasul 4: Comparați toate metodele

Rulați toate cele trei metode pe aceeași funcție-obiectiv sintetică și comparați-le. Această comparație folosește un wrapper simplificat care apelează fiecare optimizator cu o funcție-obiectiv directă (fără antrenarea unui model), astfel încât API-ul diferă de implementările bazate pe modele de mai sus:

def synthetic_objective(params):
    lr = params["learning_rate"]
    depth = params["max_depth"]
    return -(np.log10(lr) + 2) ** 2 - (depth - 4) ** 2 + 10

param_grid = {
    "learning_rate": [0.001, 0.01, 0.1, 1.0],
    "max_depth": [2, 3, 4, 5, 6, 7, 8],
}

grid_best = None
grid_score = -float("inf")
grid_history = []
for combo in itertools.product(*param_grid.values()):
    params = dict(zip(param_grid.keys(), combo))
    score = synthetic_objective(params)
    grid_history.append((params, score))
    if score > grid_score:
        grid_score = score
        grid_best = params

param_dist = {
    "learning_rate": ("log_float", 0.001, 1.0),
    "max_depth": ("int", 2, 8),
}

rand_best = None
rand_score = -float("inf")
rand_history = []
rng = np.random.RandomState(42)
for _ in range(28):
    params = {k: sample(v, rng) for k, v in param_dist.items()}
    score = synthetic_objective(params)
    rand_history.append((params, score))
    if score > rand_score:
        rand_score = score
        rand_best = params

optimizer = SimpleBayesianOptimizer(param_dist, n_initial=5)
bayes_history = []
for _ in range(28):
    params = optimizer.suggest()
    score = synthetic_objective(params)
    optimizer.observe(params, score)
    bayes_history.append((params, score))
bayes_score = max(s for _, s in bayes_history)

print(f"{'Method':<20} {'Best Score':>12} {'Evaluations':>12}")
print("-" * 50)
print(f"{'Grid Search':<20} {grid_score:>12.4f} {len(grid_history):>12}")
print(f"{'Random Search':<20} {rand_score:>12.4f} {len(rand_history):>12}")
print(f"{'Bayesian Opt':<20} {bayes_score:>12.4f} {len(bayes_history):>12}")

Cu același buget, optimizarea bayesiană găsește de obicei cel mai repede scorul optim, deoarece nu irosește evaluări în regiuni evident slabe. Căutarea aleatoare acoperă un spațiu mai mare decât căutarea pe grilă. Căutarea pe grilă câștigă doar când aveți foarte puțini hiperparametri și vă permiteți evaluarea exhaustivă.

Notă tehnică a traducerii: În această funcție sintetică, optimul exact este learning_rate=0.01, max_depth=4, iar grila conține explicit acest punct; căutarea pe grilă îl va găsi garantat în 28 de evaluări, în timp ce căutarea continuă aleatoare aproape sigur nu va eșantiona exact 0.01. Prin urmare, o singură rulare nu demonstrează concluzia din paragraf. Pentru o comparație echitabilă sunt necesare spații comparabile, mai multe semințe și statistici asupra performanței în funcție de buget.

Folosiți

Optuna în practică

Optuna este biblioteca recomandată pentru reglarea serioasă a hiperparametrilor. Ea acceptă eliminarea timpurie, căutarea distribuită și vizualizarea direct din pachet.

import optuna

def objective(trial):
    lr = trial.suggest_float("learning_rate", 1e-4, 1e-1, log=True)
    n_est = trial.suggest_int("n_estimators", 50, 500)
    max_depth = trial.suggest_int("max_depth", 2, 10)

    model = GradientBoostingRegressor(
        learning_rate=lr,
        n_estimators=n_est,
        max_depth=max_depth,
    )
    model.fit(X_train, y_train)
    return mean_squared_error(y_val, model.predict(X_val))

study = optuna.create_study(direction="minimize")
study.optimize(objective, n_trials=100)

print(f"Best params: {study.best_params}")
print(f"Best MSE: {study.best_value:.4f}")

Funcții-cheie Optuna:

  • suggest_float(..., log=True) pentru parametri care se caută cel mai bine pe scară logaritmică (rata de învățare, regularizarea)
  • suggest_int pentru parametri întregi
  • suggest_categorical pentru alegeri discrete
  • MedianPruner încorporat pentru oprirea timpurie a încercărilor slabe
  • study.trials_dataframe() pentru analiză

Notă tehnică a traducerii: Recomandarea unei biblioteci este o alegere de instrument, nu o concluzie universală. Acest obiectiv optimizează în mod repetat același set y_val; evaluarea finală trebuie făcută pe un set de testare neatins sau printr-o schemă imbricată.

Optuna cu eliminare timpurie

Eliminarea oprește din timp încercările nepromițătoare, economisind masiv resurse de calcul. Iată tiparul:

import optuna
from sklearn.model_selection import cross_val_score

def objective(trial):
    params = {
        "learning_rate": trial.suggest_float("lr", 1e-4, 0.5, log=True),
        "max_depth": trial.suggest_int("max_depth", 2, 10),
        "n_estimators": trial.suggest_int("n_estimators", 50, 500),
        "subsample": trial.suggest_float("subsample", 0.5, 1.0),
    }

    model = GradientBoostingRegressor(**params)
    scores = cross_val_score(model, X_train, y_train, cv=3,
                             scoring="neg_mean_squared_error")
    mean_score = -scores.mean()

    trial.report(mean_score, step=0)
    if trial.should_prune():
        raise optuna.TrialPruned()

    return mean_score

pruner = optuna.pruners.MedianPruner(n_startup_trials=10, n_warmup_steps=5)
study = optuna.create_study(direction="minimize", pruner=pruner)
study.optimize(objective, n_trials=200)

MedianPruner oprește o încercare dacă valoarea sa intermediară este mai slabă decât mediana tuturor încercărilor finalizate la același pas. Eliminarea necesită apelarea trial.report() pentru raportarea metricilor intermediare și a trial.should_prune() pentru verificarea necesității opririi încercării. n_startup_trials=10 asigură că cel puțin 10 încercări sunt finalizate complet înainte ca eliminarea să înceapă. De regulă, aceasta economisește 40–60% din calculul total.

Notă tehnică a traducerii: Exemplul nu poate realiza eliminarea descrisă: raportează o singură valoare la step=0, după ce cross_val_score a finalizat deja toate cele trei ajustări, iar n_warmup_steps=5 dezactivează eliminarea până după pasul 5. Pentru economii reale, trebuie raportate metrici în timpul unei bucle iterative de antrenare, la pași crescători, înainte de consumarea întregului buget. Procentul de 40–60% nu este garantat.

Instrumentele de reglare încorporate în sklearn

Pentru experimente rapide, sklearn oferă GridSearchCV, RandomizedSearchCV și HalvingRandomSearchCV:

from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import loguniform, randint

param_dist = {
    "learning_rate": loguniform(1e-4, 0.5),
    "max_depth": randint(2, 10),
    "n_estimators": randint(50, 500),
}

search = RandomizedSearchCV(
    GradientBoostingRegressor(),
    param_dist,
    n_iter=100,
    cv=5,
    scoring="neg_mean_squared_error",
    random_state=42,
    n_jobs=-1,
)
search.fit(X_train, y_train)
print(f"Best params: {search.best_params_}")
print(f"Best CV MSE: {-search.best_score_:.4f}")

Folosiți loguniform din scipy pentru rata de învățare și regularizare. Folosiți randint pentru hiperparametrii întregi. Opțiunea n_jobs=-1 paralelizează pe toate nucleele CPU.

Greșeli frecvente în reglarea hiperparametrilor

Scurgerea de date prin preprocesare. Dacă ajustați un scalator pe întregul set de date înainte de validarea încrucișată, informațiile din pliul de validare se scurg în antrenare. Puneți întotdeauna preprocesarea într-un Pipeline, astfel încât să fie ajustată numai pe pliul de antrenare.

Supraînvățarea setului de validare. Rularea a mii de încercări antrenează efectiv pe setul de validare. Folosiți validarea încrucișată imbricată pentru estimările finale ale performanței sau păstrați separat un set de testare pe care nu îl atingeți niciodată în timpul reglării.

Căutarea într-un interval prea îngust. Dacă cea mai bună valoare se află la marginea spațiului de căutare, nu ați căutat suficient de larg. Valoarea optimă s-ar putea afla în afara intervalului. Verificați întotdeauna dacă cei mai buni parametri se află la margini.

Ignorarea efectelor de interacțiune. Rata de învățare și numărul de estimatori interacționează puternic în boosting. O rată de învățare mică are nevoie de mai mulți estimatori. Reglarea lor independentă produce rezultate mai slabe decât reglarea lor împreună.

Neutilizarea opririi timpurii pentru modelele iterative. Pentru gradient boosting și rețele neurale, setați n_estimators sau numărul de epoci la o valoare mare și folosiți oprirea timpurie. Aceasta este strict mai bună decât reglarea numărului de iterații drept hiperparametru.

Notă tehnică a traducerii: Un optimum la margine este un semnal pentru revizuirea domeniului, nu o dovadă că acesta trebuie extins; limitele pot reflecta stabilitatea, latența sau alte constrângeri. Nici oprirea timpurie nu este „strict” superioară: rezultatul depinde de metrica monitorizată, frecvența evaluării, răbdare, zgomot și posibilitatea reală a estimatorului de a continua antrenarea incremental.

Exerciții

  1. Rulați căutarea pe grilă și căutarea aleatoare cu același buget total (de exemplu, 50 de evaluări). Comparați cele mai bune scoruri găsite. Rulați experimentul de 10 ori cu semințe diferite. Cât de des câștigă căutarea aleatoare?

  2. Implementați Hyperband de la zero. Începeți cu 81 de configurații, fiecare antrenată timp de 1 epocă. Păstrați treimea cea mai bună la fiecare rundă și triplați-le bugetul. Comparați calculul total (suma tuturor epocilor pentru toate configurațiile) cu rularea celor 81 de configurații cu bugetul complet.

  3. Adăugați un planificator al ratei de învățare (atenuare cosinusoidală) la implementarea gradient boosting din lecția 11. Ajută în comparație cu o rată de învățare fixă?

  4. Folosiți Optuna pentru a regla un RandomForestClassifier pe un set de date real (de exemplu, setul de date despre cancer mamar din sklearn). Folosiți optuna.visualization.plot_param_importances(study) pentru a vedea care hiperparametri contează cel mai mult. Corespunde rezultatul clasamentului importanței din această lecție?

  5. Implementați o funcție de achiziție simplă (Expected Improvement) și demonstrați explorarea în raport cu exploatarea. Reprezentați grafic media și incertitudinea modelului surogat și arătați unde alege EI să facă următoarea evaluare.

Termeni-cheie

Termen Ce spun oamenii Ce înseamnă de fapt
Hiperparametru „O setare pe care o alegeți” O valoare stabilită înainte de antrenare, care controlează procesul de învățare și nu este învățată din date
Căutare pe grilă „Încercați fiecare combinație” Căutare exhaustivă pe o grilă specificată de parametri. Cost exponențial.
Căutare aleatoare „Doar eșantionați aleatoriu” Eșantionează hiperparametrii din distribuții. Acoperă dimensiunile importante mai bine decât căutarea pe grilă.
Optimizare bayesiană „Căutare inteligentă” Folosește un model surogat al obiectivului pentru a decide unde să evalueze în continuare, echilibrând explorarea cu exploatarea
Model surogat „O aproximare ieftină” Un model (de obicei, un proces gaussian) care aproximează funcția-obiectiv costisitoare din evaluările observate
Funcție de achiziție „Unde să căutăm în continuare” Evaluează punctele candidate echilibrând îmbunătățirea așteptată cu incertitudinea. EI și UCB sunt alegeri frecvente.
Oprire timpurie „Nu mai pierdeți timpul” Încheie antrenarea devreme când performanța de validare nu se mai îmbunătățește
Hyperband „Turneu eliminatoriu pentru configurații” Alocare adaptivă a resurselor: începe cu multe configurații și bugete mici, le păstrează pe cele mai bune și le mărește bugetele
Planificator al ratei de învățare „Schimbă lr în timpul antrenării” O funcție care ajustează rata de învățare pe parcursul antrenării pentru o convergență mai bună

Lecturi suplimentare


Sursă: Hyperparameter Tuning — original

Navigare: înapoi: 02.11 — Metode de ansamblu · Faza 2 — Bazele învățării automate · Catalog complet · în continuare: 02.13 — Pipeline-uri de învățare automată.