Saltar al contenido

# machine-learning-clasico-con-python

Machine Learning con scikit-learn y XGBoost

Volver a la portada del curso
Notebook

Notebook: árboles, Random Forest, gradient boosting y XGBoost

Sección 5 · Árboles, boosting con XGBoost y ajuste de hiperparámetros

Árboles, Random Forest, gradient boosting y XGBoost

Este notebook integra el módulo de árboles y boosting. Empieza con un árbol que memoriza, lo arregla con Random Forest y gradient boosting, y termina con XGBoost: early stopping, desbalance de clases, una tabla comparativa e importancias. Esta guía acompaña al notebook arboles-y-ensambles: qué hace cada sección y qué cifra debes encontrar. La primera celda incluye la versión de xgboost; si no lo tienes, instálalo con pip install xgboost.

1. Árboles y ensambles de scikit-learn

  • Un árbol sin límite llega a 1.000 en train con 184 hojas y cae a 0.747 en test (AUC 0.693). Con profundidad 3, el primer corte es bailabilidad <= 0.66.
  • Random Forest con 300 árboles y min_samples_leaf=3: AUC test 0.856. Se estabiliza desde unos 50 árboles.
  • Gradient boosting: accuracy 0.829 y AUC 0.868; con learning_rate=1.0 memoriza (AUC 0.796).

2. HistGradientBoosting con early stopping

HistGradientBoostingClassifier agrupa cada columna en intervalos antes de cortar, acepta faltantes y, con early_stopping=True, aparta el 10 % de train como validación. Qué buscar: se detiene en 39 árboles de 500 posibles, con AUC test 0.843.

3. XGBoost con early stopping

Se aparta una validación dentro de train (900 canciones de ajuste y 225 de validación); el test no se toca. En xgboost 2.1 o superior, early_stopping_rounds y eval_metric van en el constructor:

from xgboost import XGBClassifier

X_fit, X_val, y_fit, y_val = train_test_split(X_tr, y_tr, test_size=0.2, stratify=y_tr, random_state=42)
pre_xgb = pre.fit(X_fit)
xgb_es = XGBClassifier(n_estimators=1000, learning_rate=0.05, max_depth=4, subsample=0.8,
                       colsample_bytree=0.8, eval_metric="logloss", early_stopping_rounds=50,
                       random_state=42)
xgb_es.fit(pre_xgb.transform(X_fit), y_fit,
           eval_set=[(pre_xgb.transform(X_fit), y_fit), (pre_xgb.transform(X_val), y_val)],
           verbose=False)
print(xgb_es.best_iteration)

Qué buscar: best_iteration 93, log-loss de validación 0.4352 (0.2641 en train). La curva muestra la log-loss de train bajando sin parar y la de validación tocando fondo cerca de la ronda 93. El modelo final se reentrena con todo train dentro de un Pipeline con 94 árboles: AUC test 0.863.

4. scale_pos_weight

En train hay 816 negativos y 309 positivos: scale_pos_weight = 2.64. Con el umbral 0.5, el peso sube el recall de 0.563 a 0.748 y baja la precision de 0.744 a 0.583; el AUC casi no cambia (0.863 contra 0.856). Es otra forma de mover el punto de corte, no una mejora del orden.

5. Tabla comparativa

AUC por validación cruzada estratificada de 5 pliegues sobre train, más el tiempo de los 5 ajustes:

modeloAUC CVdesviación
XGBoost0.8520.021
GradientBoosting0.8490.026
Random Forest0.8470.021
HistGradientBoosting0.8330.022
Árbol(4)0.7850.028

Los tres primeros están separados por 0.005, menos que la desviación entre pliegues. Los tiempos dependen de tu máquina; en la de referencia XGBoost fue el ensamble más rápido.

6. Importancias: gain contra impureza

Por gain, XGBoost pone arriba colaboracion (13.9 %), bailabilidad (12.6 %) y en_playlist (11.6 %); el Random Forest pone arriba duracion_seg, bailabilidad y seguidores_miles. Por weight (número de cortes), la más usada en XGBoost es seguidores_miles: las continuas ofrecen muchos cortes, las binarias se usan poco pero cada corte mejora mucho la pérdida.

7. Ejercicios

Se mantienen los seis ejercicios de árboles y ensambles (árbol de profundidad 3, min_samples_leaf, bosque sin freno, tasa de aprendizaje, rankings de importancia y hits contra falsas alarmas) y se agregan tres de XGBoost:

  1. Bajar learning_rate a 0.03: best_iteration sube de 93 a 128. Tasa y número de árboles se ajustan juntos.
  2. max_depth 3 contra 8: con 3, 115 rondas y log-loss 0.4332; con 8, se detiene en 53 rondas con 0.4578. Los árboles profundos memorizan antes.
  3. XGBoost con los datos sucios sin imputar tempo_bpm ni seguidores_miles: AUC CV 0.854, prácticamente igual que imputando la mediana (0.855). XGBoost aprende hacia qué rama mandar los faltantes.

Errores comunes: usar el test como eval_set, subir n_estimators sin bajar learning_rate, y fijar scale_pos_weight y además mover el umbral sin medir. Las soluciones están al final del notebook.

Recursos