Fundamente de Data Science

4.3 Optimizarea hiperparametrilor

Hiperparametrii (k, max_depth, C, learning_rate…) nu se învață din date — îi alegi tu. Căutarea lor sistematică aduce de regulă ultimele puncte care fac diferența în clasament.

Teorie

Cross-validation — fundația evaluării corecte

Un singur split train/validare poate fi norocos sau ghinionist. K-fold cross-validation împarte train-ul în k felii (de regulă 5): antrenează de k ori, de fiecare dată validând pe altă felie, și raportează media. Mai stabil, folosește toate datele.

from sklearn.model_selection import cross_val_score, StratifiedKFold

scoruri = cross_val_score(model, X, y, cv=5, scoring="f1_macro")
print(scoruri.mean().round(3), "±", scoruri.std().round(3))
# la clasificare, felii stratificate (proporția claselor păstrată):
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

Grid Search — căutare exhaustivă

Definești o grilă de valori; se încearcă toate combinațiile, fiecare evaluată prin cross-validation.

from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier

grila = {
    "n_estimators": [100, 300],
    "max_depth": [None, 5, 10, 20],
    "min_samples_leaf": [1, 3, 5],
}
gs = GridSearchCV(RandomForestClassifier(random_state=42),
                  grila, cv=5, scoring="f1_macro", n_jobs=-1)
gs.fit(X_train, y_train)
print(gs.best_params_, gs.best_score_)
model_final = gs.best_estimator_       # gata antrenat pe tot train-ul

Random Search — căutare aleatoare

Când grila e prea mare, RandomizedSearchCV încearcă un număr fix de combinații aleatoare. Surprinzător de eficient: de obicei doar 1–2 hiperparametri contează cu adevărat, iar căutarea aleatoare acoperă mai multe valori distincte ale fiecăruia decât o grilă rigidă.

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

distributii = {
    "n_estimators": randint(100, 1000),
    "max_depth": randint(3, 30),
    "learning_rate": uniform(0.01, 0.3),
}
rs = RandomizedSearchCV(model, distributii, n_iter=40, cv=5,
                        scoring="f1_macro", n_jobs=-1, random_state=42)
rs.fit(X_train, y_train)
Grid SearchRandom Search
Combinații încercatetoaten_iter alese aleator
Potrivit când2–3 hiperparametri, valori puținemulți hiperparametri / intervale continue
Costexplodează exponențialcontrolat de tine
Scalarea și restul preprocesării trebuie incluse în Pipeline înainte de GridSearchCV — altfel scalerul „vede" feliile de validare și scorurile ies umflate.

Problemă rezolvată: tuning complet cu Pipeline

Pipeline + GridSearch pe o problemă de clasificare Mediu Rezolvată

Rețeta corectă și completă: preprocesare în pipeline, grilă peste model, evaluare cinstită — șablonul pe care îl poți refolosi la orice problemă tabelară de pe platformă.

Șablonul complet
import pandas as pd
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.metrics import classification_report

train = pd.read_csv("train.csv")
feats = [c for c in train.columns if c not in ("SampleID", "target")]
X_tr, X_va, y_tr, y_va = train_test_split(train[feats], train["target"],
                                          test_size=0.2, random_state=42,
                                          stratify=train["target"])

pipe = Pipeline([
    ("scaler", StandardScaler()),
    ("model", SVC()),
])
grila = {
    "model__C": [0.1, 1, 10, 100],
    "model__gamma": ["scale", 0.01, 0.1, 1],
}
gs = GridSearchCV(pipe, grila, cv=5, scoring="f1_macro", n_jobs=-1)
gs.fit(X_tr, y_tr)

print("Cei mai buni parametri:", gs.best_params_)
print("Scor CV:", round(gs.best_score_, 3))
print(classification_report(y_va, gs.predict(X_va)))   # verificare finală

Observă sintaxa model__C: numele pasului din pipeline + __ + numele hiperparametrului.

Probleme propuse

1. Numărătoarea costului Exercițiu

O grilă are 4×5×3 combinații cu cv=5. Câte antrenări rulează GridSearchCV? Dar RandomizedSearchCV cu n_iter=30? Ce alegi dacă o antrenare durează 30 de secunde?

2. Stabilitatea cross-validation Exercițiu

Rulează de 10 ori un train_test_split diferit și măsoară scorul; apoi rulează o singură dată cross_val_score cu cv=10. Compară împrăștierea rezultatelor.

3. Grid vs Random, pe bune Exercițiu

Pe aceeași problemă și același buget (40 de antrenări), compară scorul final GridSearchCV vs RandomizedSearchCV pentru un HistGradientBoosting. Care câștigă?

4. Puncte în plus pe platformă Platformă

Ia soluția ta cea mai bună de la orice problemă tabelară și adaugă-i tuning cu RandomizedSearchCV. Notează scorul înainte și după.