Salta al contenuto
Note per Studenti Esercizio - Gradient boosting per la regressione sul dataset housing

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, 20 43320\,433 distretti senza valori mancanti; target median_house_value, 9 feature tra cui la categorica ocean_proximity; si estrae un campione casuale di 20002000 righe, 80%80\% training e 20%20\% test):

  1. adattare un albero di regressione (criterio MSE, foglie con la media) e calcolare l'R2R^2 sul test;
  2. implementare il gradient boosting per la regressione con alberi di regressione: predizione iniziale la media, alberi addestrati sui residui, aggiornamento con tasso η\eta;
  3. 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); R2R^2 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

  1. F0(x)=yˉtrainF_0(x)=\bar y_{\text{train}} (media del target di training).
  2. Per m=1,…,Tm=1,\dots,T: residui ri=yi−Fm−1(xi)r_i=y_i-F_{m-1}(x_i); si addestra un albero di regressione hmh_m sui residui (foglia = media dei residui che ci cadono); si aggiorna Fm=Fm−1+η hmF_m=F_{m-1}+\eta\,h_m.
  3. Previsione: FT(x)=yˉ+η∑mhm(x)F_T(x)=\bar y+\eta\sum_mh_m(x).
python
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; R2R^2 sul test, 400 campioni)

  • Predittore costante (la media): R2=−0,005R^2=-0{,}005 (come previsto, circa 00).
  • Singolo albero di profondità 5: R2=0,583R^2=0{,}583.

Numero di alberi (profondità 3, η=0,1\eta=0{,}1):

TT 2 4 10 50 100 300
R2R^2 training 0,1820{,}182 0,3080{,}308 0,5330{,}533 0,7800{,}780 0,8470{,}847 0,9270{,}927
R2R^2 test 0,1800{,}180 0,3150{,}315 0,5270{,}527 0,7000{,}700 0,7450{,}745 0,7600{,}760

Ogni albero aggiunto riduce l'errore (i residui si accorciano a ogni passo di un fattore legato a η\eta): con η=0,1\eta=0{,}1 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 (0,9270{,}927) e test (0,7600{,}760) mostra overfitting crescente.

Profondità degli alberi (T=100T=100, η=0,1\eta=0{,}1): profondità 2: training 0,7830{,}783, test 0,7360{,}736; profondità 4: 0,9040{,}904 e 0,761\mathbf{0{,}761}; profondità 10: 1,0001{,}000 e 0,6620{,}662. Alberi molto profondi memorizzano il training (R² uguale a 11) 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, T=100T=100): η=0,01\eta=0{,}01: test 0,5170{,}517 (troppo lento: 100 piccoli passi non bastano); η=0,1\eta=0{,}1: 0,7450{,}745; η=0,5\eta=0{,}5: 0,7440{,}744 (training 0,9530{,}953); η=1\eta=1: 0,6580{,}658 con training 0,9730{,}973: 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 (R2=0,76R^2=0{,}76) supera di molto sia il singolo albero (0,580{,}58) 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 33 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 R2R^2 stampati vanno letti di conseguenza. Per studiare la profondità servono gli argomenti con nome (n_estimators=T, learning_rate=eta, max_depth=d).

Lezioni in cui compare

Teoria collegata