Python Data Science Program
📓 Abrir notebook en GitHub

Clase 058 — Optuna y HPO bayesiano dedicado

Parte: 1 — Machine Learning Clásico · Fuente: Akiba et al. (2019) + Optuna docs. ⏱️ Duración estimada: 80 min.

🎯 Objetivo

Profundizar en Optuna —el framework de hyperparameter optimization estándar industrial 2026— aplicado a ML clásico (sklearn, XGBoost, LightGBM, CatBoost). Pasar de Grid/Random Search (clase 052) a TPE (Tree-structured Parzen Estimator) + Hyperband Pruner + persistencia con SQLite. Aprender a interpretar plot_optimization_history, plot_param_importances y plot_slice para entender qué hiperparámetros mueven la aguja.

📚 Resultados de aprendizaje

Al finalizar, el estudiante podrá:

🗺️ Temas

📖 Definiciones y características

📂 Dataset / recursos

🧪 Ejercicios

  1. Objective básico: tunear LogisticRegression(C, penalty) y RandomForest(n_estimators, max_depth) con TPE. 50 trials.
  2. Search space compuesto: hiperparámetros condicionales (e.g., solver=liblinear solo permite ciertos penalty). Optuna lo maneja con if.
  3. Pruning en XGBoost: usar XGBoostPruningCallback que reporta validación por boosting round → mata trials malos.
  4. Persistencia: optuna.create_study(study_name='exp1', storage='sqlite:///opt.db', load_if_exists=True). Re-correr y agregar trials.
  5. Multi-objective: maximizar accuracy AND minimizar inference time; obtener Pareto front con optuna.create_study(directions=['maximize', 'minimize']).

📝 Homework verificable

HPO con Optuna sobre XGBoost en credit-g:

  1. Espacio: n_estimators, max_depth, lr, subsample, colsample_bytree, reg_alpha, reg_lambda.
  2. 100 trials con TPE + Hyperband pruning.
  3. Reportar best_params, best_value, plot history + importances.
  4. Comparar contra RandomizedSearchCV(50 trials).

Criterio de aceptación: Optuna ≥ RandomizedSearch en AUC; plot_param_importances identifica lr y/o max_depth como las más importantes.

⚠️ Errores comunes

Síntoma / mensaje Causa y cómo arreglar
LR muestreado uniforme Fix: suggest_float('lr', 1e-5, 1e-1, log=True).
TPE no parece "inteligente" en < 20 trials El modelo interno necesita warmup. Fix: ≥ 50 trials.
study.optimize(n_jobs=4) se cuelga Race conditions con SQLite. Fix: usar Postgres para multi-job.
Pruner muy agresivo mata trials buenos Fix: ajustar MedianPruner(n_startup_trials=10, n_warmup_steps=5).
Olvido reportar valor intermedio para pruning El pruner no funciona sin trial.report(value, step).

❓ Preguntas frecuentes

❓ ¿TPE o CmaEs?

TPE para search spaces mezclados (cat + cont). CmaEs para puramente continuo, con poca cardinalidad — converge más rápido.

❓ ¿Cuántos trials?

Para ML clásico, 50-200 alcanza. Para DL caro (cada trial 1 h), 20-50 con pruning agresivo.

❓ ¿Distributed HPO?

Postgres storage + varios workers (Python processes en distintas máquinas). Optuna lo soporta nativo.

❓ ¿Pruning siempre?

Solo si el objective expone progreso intermedio (cada época en NN, cada boosting round en XGBoost). Para fit().score() directo, no aplica.

❓ ¿Visualizaciones para reportar al cliente?

plot_param_importances y plot_slice son las más comunicables. Muestran "qué cambió y cuánto".

🔗 Referencias

📥 Material descargable

➡️ Siguiente clase

Clase 059 — Launch, monitoreo y mantenimiento de modelos