Esercizio - Gradient boosting per la regressione sul dataset housing
Questa pagina non ha ancora la versione ripasso: qui sotto c'è il testo completo.
In questa pagina 3
Testo (laboratorio LAB5, esercizio 2). Con il dataset housing (California, distretti senza valori mancanti; target median_house_value, 9 feature tra cui la categorica ocean_proximity; si estrae un campione casuale di righe, training e test):
- adattare un albero di regressione (criterio MSE, foglie con la media) e calcolare l' sul test;
- implementare il gradient boosting per la regressione con alberi di regressione: predizione iniziale la media, alberi addestrati sui residui, aggiornamento con tasso ;
- studiare l'effetto di numero di alberi, profondità e tasso di apprendimento.
Teoria usata: Metodi ensemble - bagging, random forest e boostingUn albero da solo ha varianza alta; un ensemble combina molti modelli deboli. Bagging: ogni albero è addestrato su un campione bootstrap (n estrazioni con rimpiazzo, circa il 63% di campioni distinti) e si vota o si fa la media: riduce la varianza, perché la media di $T$ stimatori con varianza $\sigma^2$ e correlazione $\rho$ ha varianza $\rho\sigma^2+(1-\rho)\sigma^2/T$. Random forest = bagging + a ogni split solo $\sqrt p$ feature casuali (alberi meno correlati); l'importanza di una feature è la somma delle riduzioni di Gini pesate sui nodi in cui è usata. Boosting: alberi in sequenza, ciascuno corregge gli errori dei precedenti, e si riduce il bias. Gradient boosting: $F\leftarrow F+\eta h$ con $h$ albero sui residui (gradiente negativo della perdita), $\eta$ piccolo; AdaBoost: stump e pesi sui campioni sbagliati; XGBoost: similarity score $\frac{(\sum r)^2}{N+\lambda}$, gain, potatura con $\gamma$, output $\frac{\sum r}{N+\lambda}$. Programma di Telecomunicazioni: Random Forests; boosting come approfondimento.Metodi ensemble - bagging, random forest e boosting → (gradient boosting, residui, tasso di apprendimento); Alberi di decisioneUn albero di decisione partiziona i dati con una sequenza di regole su una sola variabile alla volta (nodi interni = regole, foglie = predizioni: classe più frequente, oppure media del target in regressione). Si costruisce in modo ricorsivo scegliendo a ogni nodo la divisione che rende i figli più «puri»: con l'entropia $H=-\sum p_i\log_2p_i$ e il guadagno d'informazione $IG=H(S)-\sum\frac{|S_v|}{|S|}H(S_v)$ (ID3), oppure con l'indice di Gini $1-\sum p_i^2$ e soglie $x\le t$ su variabili numeriche (CART); in regressione con MSE o riduzione di varianza. Un albero pienamente sviluppato fa overfitting (varianza alta): si limita con la profondità massima (pre-potatura) o con la potatura a costo-complessità $R_\alpha(T)=R(T)+\alpha|T|$ (post-potatura). Pro: interpretabile, niente normalizzazione, predizione immediata; contro: varianza alta, da cui le foreste. Programma di Telecomunicazioni: Decision Trees e Random Forests.Alberi di decisione → (alberi di regressione, MSE, riduzione di varianza); in Regressione lineareNell'apprendimento supervisionato si impara una funzione $F(x)$ dagli esempi $(x,y)$: regressione se $y$ è continua, classificazione se è categorica. Il modello lineare è $F_\beta(x)=\beta_0+\beta_1x_1+\dots+\beta_px_p=X\beta$ (con una colonna di uni per $\beta_0$) e i parametri si scelgono minimizzando l'errore quadratico medio $\mathrm{MSE}=\frac1n\sum_i(y_i-F_\beta(x_i))^2$, funzione convessa dei parametri. Annullando il gradiente di $J(\beta)=|y-X\beta|^2$ si ottengono le equazioni normali $X^TX\beta=X^Ty$ e la soluzione dei minimi quadrati ordinari $\beta=(X^TX)^{-1}X^Ty$. Il coefficiente di determinazione $R^2=1-SS_{res}/SS_{tot}$ misura la qualità del fit (0 = come la media, negativo = peggio della media). Un modello va valutato su un test set mai usato per addestrare: l'errore sul training è ottimistico e un polinomio di grado alto lo azzera senza generalizzare.Regressione lineare →.
Algoritmo
- (media del target di training).
- Per : residui ; si addestra un albero di regressione sui residui (foglia = media dei residui che ci cadono); si aggiorna .
- Previsione: .
def fit_gb(X, y, T, eta, depth):
F = np.full(len(y), y.mean()); trees = []
for _ in range(T):
tree = DecisionTreeRegressor(max_depth=depth).fit(X, y - F) # alberi sui residui
F += eta * tree.predict(X); trees.append(tree)
return y.mean(), trees
def predict_gb(X, base, trees, eta): return base + eta * sum(t.predict(X) for t in trees)(Nel laboratorio gli alberi sono quelli scritti a mano, con MSECriterion e node_prediction_regression; la categorica ocean_proximity si tratta come feature categorica nel loro codice e viene codificata con interi per scikit-learn.)
Risultati (campione di 2000 righe, seme 0; sul test, 400 campioni)
- Predittore costante (la media): (come previsto, circa ).
- Singolo albero di profondità 5: .
Numero di alberi (profondità 3, ):
| 2 | 4 | 10 | 50 | 100 | 300 | |
|---|---|---|---|---|---|---|
| training | ||||||
| test |
Ogni albero aggiunto riduce l'errore (i residui si accorciano a ogni passo di un fattore legato a ): con e pochi alberi si è ancora lontani dalla soluzione, che serve molti passi. Il test cresce ma più lentamente del training: a 300 alberi il divario tra training () e test () mostra overfitting crescente.
Profondità degli alberi (, ): profondità 2: training , test ; profondità 4: e ; profondità 10: e . Alberi molto profondi memorizzano il training (R² uguale a ) e generalizzano peggio: sono weak learner troppo forti. Il boosting funziona meglio con alberi poco profondi (stump, profondità 3-6), che riducono il bias un po' alla volta.
Tasso di apprendimento (profondità 3, ): : test (troppo lento: 100 piccoli passi non bastano); : ; : (training ); : con training : passi grandi significano meno regolarizzazione e più overfitting. «Molti piccoli passi» generalizzano meglio, a costo di più alberi.
Confronto. Il gradient boosting con 100 alberi di profondità 4 () supera di molto sia il singolo albero () sia il modello costante, restando interpretabile solo in parte.
Discrepanza nel notebook di laboratorio
La funzione ha la firma fit_gradient_boosting_regression(X_train, y_train, X_test, y_test, n_estimators=100, learning_rate=0.1, max_depth=3, cat_features=None), ma la cella che esplora «la profondità massima» la chiama come fit_gradient_boosting_regression(X_train, y_train, T, learning_rate, max_depth, cat_features=[8]): per l'ordine degli argomenti il valore max_depth (2, 4, 10) finisce in n_estimators, mentre max_depth resta e T, learning_rate finiscono in X_test, y_test, che la funzione non usa. Il ciclo che stampa «Max depth» varia quindi in realtà il numero di alberi (2, 4 e 10 alberi di profondità 3), non la profondità: i valori di stampati vanno letti di conseguenza. Per studiare la profondità servono gli argomenti con nome (n_estimators=T, learning_rate=eta, max_depth=d).