📖 Teoría

Optimización de Hiperparámetros

Los hiperparámetros determinan cómo aprende tu modelo. Optimizarlos correctamente puede ser la diferencia entre un modelo mediocre y uno de estado del arte. Desde Grid Search hasta optimización bayesiana, domina las técnicas que los mejores practicians usan.

🎛️ ¿Qué son los hiperparámetros?

En el entrenamiento de un modelo de deep learning, existen dos tipos fundamentales de variables que determinan el comportamiento del modelo:

  • Parámetros del modelo (\(\theta\)): los pesos y biases de la red neuronal, que se aprenden automáticamente durante el entrenamiento mediante la optimización de la función de pérdida
  • Hiperparámetros (\(\lambda\)): configuraciones que el diseñador humano elige antes del entrenamiento, y que controlan cómo se realiza el aprendizaje
💡

Definición formal: Un hiperparámetro es cualquier variable de configuración cuyo valor se establece antes de que comience el proceso de aprendizaje, y que no se actualiza por el algoritmo de optimización (backpropagation + optimizer).

Ejemplos comunes de hiperparámetros

Entrenamiento
  • Learning rate (\(\eta\))
  • Batch size
  • Número de épocas
  • Optimizer (SGD, Adam…)
  • Scheduler del LR
  • Weight decay (\(\lambda\))
Arquitectura
  • Número de capas
  • Neuronas por capa
  • Función de activación
  • Kernel size (CNNs)
  • Número de heads (Transformers)
  • Dimensión del embedding
Regularización
  • Dropout rate
  • L1 / L2 penalty
  • Data augmentation params
  • Label smoothing
  • Early stopping patience
  • Gradient clipping

La elección de hiperparámetros ha sido un reto central en machine learning desde sus inicios. En los primeros días del deep learning, los practicantes confiaban casi exclusivamente en la intuición y la experiencia para ajustar estos valores. A medida que las redes crecieron en tamaño y complejidad — pasando de modelos con miles de parámetros a arquitecturas con miles de millones — la HPO sistemática se volvió no solo deseable, sino imprescindible. Un mismo modelo puede variar su rendimiento en más de 10 puntos porcentuales de accuracy simplemente cambiando el learning rate o el weight decay.

La sensibilidad del modelo a cada hiperparámetro varía enormemente. Investigaciones recientes muestran que el learning rate suele ser el hiperparámetro más crítico, seguido del batch size y la profundidad de la red. Otros, como el \(\epsilon\) de Adam, rara vez necesitan ajuste.

Objetivo formal de HPO $$\lambda^* = \underset{\lambda \in \Lambda}{\arg\min} \; \mathcal{L}_{val}\!\left(\theta^*(\lambda)\right) \quad \text{donde} \quad \theta^*(\lambda) = \underset{\theta}{\arg\min} \; \mathcal{L}_{train}(\theta, \lambda)$$

Es decir, buscamos los hiperparámetros \(\lambda^*\) que, una vez entrenado el modelo hasta su óptimo \(\theta^*(\lambda)\), minimicen la pérdida en el conjunto de validación, no en el de entrenamiento.

🔄 HPO vs optimización de parámetros

Aunque ambos procesos buscan «optimizar», son fundamentalmente diferentes en su naturaleza y en los algoritmos que utilizan:

AspectoParámetros (\(\theta\))Hiperparámetros (\(\lambda\))
¿Qué se optimiza? Pesos y biases de la red Configuraciones del entrenamiento y arquitectura
¿Cómo se optimiza? Gradient descent (backprop) Grid search, random search, Bayesian opt…
¿Gradientes disponibles? ✅ Sí, \(\nabla_\theta \mathcal{L}\) es diferenciable ❌ No en general (espacio discreto, no diferenciable)
Coste de evaluar Un forward + backward pass (~ms) Un entrenamiento completo (~horas/días)
Dimensionalidad Millones–miles de millones Típicamente 5–30
Función objetivo Pérdida en training set Pérdida/métrica en validation set
Tipo de problema Optimización continua (mayormente) Caja negra, mixto (cont. + discreto + categórico)
🔬

Optimización bilevel: La HPO es un problema de optimización de dos niveles. En el nivel inferior, entrenamos el modelo (optimizamos \(\theta\) con gradient descent). En el nivel superior, evaluamos la configuración de hiperparámetros y buscamos la mejor combinación de \(\lambda\). Cada evaluación del nivel superior requiere ejecutar todo el nivel inferior.

📊 El bucle de optimización de hiperparámetros

1
Seleccionar \(\lambda\) El algoritmo HPO propone una configuración de hiperparámetros
2
Entrenar modelo Entrenamiento completo con \(\lambda\) → obtener \(\theta^*(\lambda)\)
3
Evaluar en validación Medir \(\mathcal{L}_{val}(\theta^*(\lambda))\) o accuracy, F1…
4
Actualizar estrategia Usar el resultado para guiar la próxima selección de \(\lambda\)
↩ repetir

Nótese que el paso 4 (actualizar estrategia) es lo que diferencia los distintos algoritmos de HPO. En Grid y Random Search, este paso no existe realmente: los puntos a evaluar están predeterminados. En la optimización bayesiana, este paso es donde reside toda la inteligencia: el algoritmo construye un modelo probabilístico de la función objetivo y lo usa para decidir qué configuración probar a continuación. Esta capacidad de aprender de evaluaciones pasadas es lo que permite a la BO ser mucho más eficiente con el presupuesto computacional.

Esta naturaleza de evaluación costosa es la que hace tan importante elegir un algoritmo de HPO eficiente. Un enfoque ingenuo podría requerir cientos de entrenamientos completos, mientras que métodos como la optimización bayesiana pueden encontrar buenas configuraciones en 20–50 evaluaciones.

⚠️ Data leakage en HPO

Uno de los errores más comunes y peligrosos en machine learning es el data leakage (fuga de datos): cuando información del conjunto de test se «filtra» al proceso de selección del modelo, produciendo métricas artificialmente optimistas.

🚨

Error crítico: Si usas el conjunto de test para elegir hiperparámetros, estás optimizando directamente sobre el test set. Tu modelo memorizará las peculiaridades del test, y las métricas reportadas no reflejarán el rendimiento real en producción. Esto invalida completamente la evaluación.

Este problema es más común de lo que parece. En una revisión de 2019 publicada en Nature Machine Intelligence, los autores encontraron que una proporción significativa de estudios publicados en biomedicina contenían alguna forma de data leakage, lo que llevó a métricas infladas y a modelos que fallaban en producción. El data leakage es especialmente insidioso en HPO porque la optimización de hiperparámetros implica muchas evaluaciones sobre los mismos datos, amplificando el riesgo de sobreajuste al conjunto de validación.

La solución: tres conjuntos de datos

Para una evaluación rigurosa, necesitamos tres conjuntos separados, cada uno con un propósito claramente definido:

Training (60-80%)
Validation (10-20%)
Test (10-20%)
Aprender \(\theta\)
Los parámetros del modelo se optimizan con estos datos
Elegir \(\lambda\)
HPO evalúa aquí cada configuración
Evaluación final
Solo se usa UNA vez al final
🔑

Regla de oro: El conjunto de test es sagrado. Nunca debe influir en ninguna decisión de diseño: ni la arquitectura, ni los hiperparámetros, ni el preprocesamiento. Si miras las métricas de test y luego vuelves a cambiar algo, ya no es test, es validación.

¿Qué pasa si tengo pocos datos?

Cuando el dataset es pequeño, reservar un 20% para validación puede ser un desperdicio. Aquí es donde entra la validación cruzada, que abordamos en la siguiente sección. También existen estrategias como:

  • Stratified splitting: mantener la distribución de clases en cada split
  • Time-based splitting: para series temporales, usar los datos más recientes como test
  • Group splitting: asegurar que datos del mismo grupo (paciente, usuario) no aparezcan en train y test

🔁 Validación cruzada

La validación cruzada (cross-validation, CV) es una técnica que permite usar todos los datos tanto para entrenamiento como para validación, rotando qué porción sirve como validación en cada iteración. La variante más popular es el k-Fold CV.

k-Fold Cross-Validation

El dataset se divide en \(k\) particiones (folds) de tamaño similar. Se realizan \(k\) entrenamientos, usando cada vez un fold diferente como validación y los \(k-1\) restantes como entrenamiento:

🧪 Visualiza k-Fold Cross-Validation

5

🟢 Training    🟠 Validación — cada fold rota como validación

La métrica final es el promedio de las \(k\) evaluaciones, con su desviación estándar como medida de variabilidad:

Estimación CV $$\text{Score}_{CV} = \frac{1}{k} \sum_{i=1}^{k} \text{Score}_i \quad \pm \quad \sigma = \sqrt{\frac{1}{k}\sum_{i=1}^{k}(\text{Score}_i - \text{Score}_{CV})^2}$$

CV en el contexto de HPO

En HPO, la validación cruzada sustituye al validation set fijo. Para cada configuración de hiperparámetros \(\lambda\), se ejecuta un k-Fold CV completo, y la métrica promediada es la que guía la búsqueda:

HPO con CV $$\lambda^* = \underset{\lambda \in \Lambda}{\arg\min} \; \frac{1}{k}\sum_{i=1}^{k}\mathcal{L}_{val}^{(i)}\!\left(\theta^{*(i)}(\lambda)\right)$$
⏱️

Coste computacional: Con k-Fold CV, cada evaluación de hiperparámetros requiere entrenar \(k\) modelos completos. Si \(k=5\) y estás probando 100 configuraciones, son 500 entrenamientos. En deep learning, donde cada entrenamiento puede tardar horas, esto es a menudo prohibitivo. Soluciones: usar \(k\) pequeño (3 o 5), early stopping, o un holdout fijo con datos suficientes.

Variantes de cross-validation

VarianteDescripciónCuándo usar
k-Fold estándar Divide en k particiones aleatorias Caso general con datos suficientes
Stratified k-Fold Mantiene la distribución de clases en cada fold Clasificación con clases desbalanceadas
Leave-One-Out (LOO) \(k = N\), cada muestra es un fold Datasets muy pequeños (<100 muestras)
Repeated k-Fold Repite k-Fold varias veces con semillas distintas Cuando se necesita estimación muy robusta
Time Series Split Folds temporales: entrena en pasado, valida en futuro Series temporales (no se puede mezclar temporal)
Group k-Fold Asegura que un grupo completo está en un solo fold Datos agrupados (mismo paciente, mismo sensor…)

En la práctica, la elección de la variante de CV depende del problema y del tamaño del dataset. Para la mayoría de problemas de deep learning con datasets grandes (>50.000 muestras), un holdout fijo (train/val/test split) suele ser suficiente y es mucho más rápido. La CV se reserva para datasets pequeños o cuando se necesita una estimación muy robusta del rendimiento. En el contexto de HPO, la CV se combina con el algoritmo de búsqueda: cada evaluación de hiperparámetros usa la métrica promediada de los folds para guiar la búsqueda, lo que produce estimaciones más estables pero a un coste computacional proporcionalmente mayor.

🧠 Optimización bayesiana: la idea

La optimización bayesiana (BO) es una estrategia de optimización de caja negra diseñada para funciones que son costosas de evaluar, ruidosas y sin gradientes. Estas tres propiedades describen perfectamente la HPO en deep learning.

A diferencia de Grid y Random Search, la BO es un método secuencial informado: cada nueva evaluación se elige inteligentemente basándose en los resultados de las anteriores. Esto permite encontrar buenas configuraciones con muchas menos evaluaciones.

💡

Idea fundamental: En lugar de evaluar la función objetivo directamente (entrenar un modelo cada vez), construimos un modelo probabilístico barato (surrogate model) que aproxima la función objetivo. Usamos este modelo barato para decidir dónde evaluar a continuación, equilibrando entre explorar regiones desconocidas y explotar regiones prometedoras.

Los dos componentes clave

La optimización bayesiana tiene dos pilares:

📈
Surrogate Model
Un modelo probabilístico que aproxima la función objetivo \(f(\lambda)\). Proporciona no solo una predicción sino también una incertidumbre (cuánto confiamos en la predicción en cada punto).

Opciones comunes: Gaussian Process (GP), Tree-structured Parzen Estimator (TPE), Random Forests.
🎯
Acquisition Function
Una función barata que usa las predicciones del surrogate model para decidir dónde evaluar a continuación. Equilibra:

Explotación: evaluar donde el surrogate predice buenos resultados
Exploración: evaluar donde la incertidumbre es alta

El algoritmo general

El flujo secuencial de la optimización bayesiana es:

0
Inicialización: Evaluar \(n_0\) puntos aleatorios (típicamente 5-10) para tener un dataset inicial \(\mathcal{D}_0 = \{(\lambda_i, y_i)\}_{i=1}^{n_0}\)
Para \(t = 1, 2, \ldots, T\):
1
Ajustar surrogate: Entrenar el modelo probabilístico con \(\mathcal{D}_{t-1}\)
2
Optimizar acquisition: \(\lambda_t = \arg\max_\lambda \alpha(\lambda \,|\, \mathcal{D}_{t-1})\)
3
Evaluar objetivo: \(y_t = f(\lambda_t) + \varepsilon\) (entrenar modelo con \(\lambda_t\))
4
Actualizar datos: \(\mathcal{D}_t = \mathcal{D}_{t-1} \cup \{(\lambda_t, y_t)\}\)

La clave está en los pasos 1-2: entrenar el surrogate es rápido (milisegundos), y optimizar la acquisition function también es rápido. El paso costoso (3) se ejecuta solo una vez por iteración, en lugar de las cientos de veces de un Grid Search.

La optimización bayesiana fue popularizada en el contexto de HPO por el trabajo seminal de Snoek, Larochelle & Adams (2012), quienes demostraron que BO con GPs podía igualar o superar el rendimiento de expertos humanos ajustando hiperparámetros de redes neuronales, usando un orden de magnitud menos evaluaciones que Random Search. Su sistema, Spearmint, fue uno de los primeros frameworks prácticos de BO para deep learning y motivó toda una línea de investigación que continúa hoy. Desde entonces, la BO se ha convertido en el estándar de referencia para HPO cuando cada evaluación es costosa (horas o días de entrenamiento).

📊 Procesos Gaussianos (GP)

El surrogate model más usado en la optimización bayesiana clásica es el Proceso Gaussiano (Gaussian Process, GP). Un GP es una distribución de probabilidad sobre funciones: no predice un solo valor, sino una distribución normal completa en cada punto, con media y varianza.

Definición formal

Un GP queda completamente definido por una función media \(m(\lambda)\) y una función kernel (covarianza) \(k(\lambda, \lambda')\):

Definición GP $$f(\lambda) \sim \mathcal{GP}\big(m(\lambda), \; k(\lambda, \lambda')\big)$$

En la práctica, se suele asumir \(m(\lambda) = 0\) (media cero) y se deja que el kernel capture toda la estructura. La predicción del GP en un punto nuevo \(\lambda^*\), condicionada en los datos observados \(\mathcal{D} = \{(\lambda_i, y_i)\}_{i=1}^{n}\), es:

Predicción GP $$\mu(\lambda^*) = \mathbf{k}_*^T \mathbf{K}^{-1} \mathbf{y}$$ $$\sigma^2(\lambda^*) = k(\lambda^*, \lambda^*) - \mathbf{k}_*^T \mathbf{K}^{-1} \mathbf{k}_*$$

Donde \(\mathbf{K}\) es la matriz de covarianza de los puntos observados (\(K_{ij} = k(\lambda_i, \lambda_j)\)), \(\mathbf{k}_*\) es el vector de covarianzas entre el punto nuevo y los observados, y \(\mathbf{y}\) es el vector de valores observados.

🔬

Interpretación intuitiva:

  • \(\mu(\lambda^*)\) es la mejor estimación del valor de la función en \(\lambda^*\)
  • \(\sigma^2(\lambda^*)\) mide la incertidumbre: es alta lejos de los puntos observados y baja cerca de ellos
  • Juntos definen una «banda de confianza» alrededor de la predicción

Funciones kernel

El kernel \(k(\lambda, \lambda')\) controla las propiedades de las funciones que el GP puede representar: suavidad, periodicidad, escala de variación. Los más usados en HPO son:

RBF (Squared Exponential)
El más popular
\(k(\lambda, \lambda') = \sigma_f^2 \exp\!\left(-\frac{|\lambda - \lambda'|^2}{2\ell^2}\right)\)
Asume funciones infinitamente suaves. \(\ell\) controla la escala de variación.
Matérn 5/2
Recomendado para HPO
\(k = \sigma_f^2\!\left(1 + \frac{\sqrt{5}r}{\ell} + \frac{5r^2}{3\ell^2}\right) e^{-\frac{\sqrt{5}r}{\ell}}\)
Menos suave que RBF, más realista para funciones de pérdida reales.
Matérn 3/2
Funciones rugosas
\(k = \sigma_f^2\!\left(1 + \frac{\sqrt{3}r}{\ell}\right) e^{-\frac{\sqrt{3}r}{\ell}}\)
Aún menos suave. Útil cuando la función objetivo tiene cambios bruscos.

🧪 Experimenta: Gaussian Process en acción

1.0
0.10

Haz clic en el canvas para añadir puntos observados. La línea verde es la media del GP, la banda sombreada es ±2σ (intervalo de confianza 95%).

Limitaciones de los GPs

  • Coste computacional: La inversión de \(\mathbf{K}\) es \(O(n^3)\), lo que limita los GPs a unas pocas miles de observaciones. Para HPO esto no suele ser problema (tenemos <100 evaluaciones), pero limita otros usos.
  • Espacios de alta dimensionalidad: Los GPs pierden efectividad cuando \(d > 20\), ya que la mayoría de los puntos están «lejos» unos de otros (curse of dimensionality).
  • Variables categóricas: Los kernels estándar no manejan bien variables categóricas. Se necesitan kernels especializados o codificaciones.

Estas limitaciones han motivado el desarrollo de alternativas como TPE y Random Forests como surrogate models, que veremos en la sección de surrogate models alternativos. No obstante, los GPs siguen siendo la opción preferida cuando el espacio de búsqueda es continuo y de dimensionalidad moderada (\(d < 20\)), gracias a su elegante cuantificación de la incertidumbre y sus sólidas garantías teóricas.

🧪 Experimenta con el GP y la optimización bayesiana completa en la herramienta interactiva →

🎯 Funciones de adquisición

La función de adquisición \(\alpha(\lambda)\) usa las predicciones del surrogate model (media \(\mu\) e incertidumbre \(\sigma\)) para asignar un «valor de utilidad» a cada punto del espacio de hiperparámetros. El siguiente punto a evaluar es el que maximiza esta utilidad:

Selección del siguiente punto $$\lambda_{t+1} = \underset{\lambda \in \Lambda}{\arg\max} \; \alpha(\lambda \,|\, \mu, \sigma, \mathcal{D}_t)$$

La acquisition function codifica el trade-off exploración vs explotación: ¿evaluamos donde creemos que el resultado será bueno (explotación), o donde no sabemos nada (exploración)?

Expected Improvement (EI)

La función de adquisición más popular. Mide la mejora esperada respecto al mejor valor observado hasta ahora \(f^* = \min_i y_i\):

Expected Improvement $$\text{EI}(\lambda) = \mathbb{E}\!\left[\max\left(f^* - f(\lambda), \; 0\right)\right]$$

Cuando el surrogate es un GP, esta esperanza tiene una forma cerrada (no requiere simulaciones de Monte Carlo):

EI — forma cerrada $$\text{EI}(\lambda) = (f^* - \mu(\lambda)) \cdot \Phi(z) + \sigma(\lambda) \cdot \phi(z) \quad \text{donde} \quad z = \frac{f^* - \mu(\lambda)}{\sigma(\lambda)}$$

Donde \(\Phi\) y \(\phi\) son la CDF y PDF de la normal estándar respectivamente. El primer término favorece la explotación (valores de \(\mu\) bajos) y el segundo la exploración (valores de \(\sigma\) altos).

Otras funciones de adquisición

Probability of Improvement (PI)

La más simple: mide la probabilidad de mejorar el mejor valor actual:

PI $$\text{PI}(\lambda) = \Phi\!\left(\frac{f^* - \mu(\lambda)}{\sigma(\lambda)}\right)$$

Problema: PI es demasiado «greedy» (explota mucho y explora poco). Tiende a converger prematuramente a un óptimo local. Por eso EI es preferida en la práctica.

Upper Confidence Bound (UCB / LCB)

Combina media e incertidumbre con un parámetro \(\kappa\) que controla el trade-off:

LCB (para minimización) $$\text{LCB}(\lambda) = \mu(\lambda) - \kappa \cdot \sigma(\lambda)$$

El siguiente punto a evaluar es \(\arg\min \text{LCB}(\lambda)\). \(\kappa\) alto = más exploración, \(\kappa\) bajo = más explotación. Valores típicos: \(\kappa \in [1, 3]\). Ventaja: tiene garantías teóricas de convergencia (regret bounds).

Knowledge Gradient (KG)

Mide el valor de la información: ¿cuánto mejoraría nuestra decisión final si evaluáramos en el punto \(\lambda\)?

KG $$\text{KG}(\lambda) = \mathbb{E}\!\left[\min_{\lambda'} \mu_{t+1}(\lambda') \,\Big|\, \text{evaluar } \lambda\right] - \min_{\lambda'} \mu_t(\lambda')$$

Teóricamente óptimo para un horizonte de una sola evaluación restante. Más costoso de calcular que EI pero puede ser más eficiente con presupuestos muy limitados.

Thompson Sampling

En lugar de calcular una función analítica, simplemente muestreamos una función del GP posterior y evaluamos en su mínimo:

  1. Muestrear \(\tilde{f} \sim \mathcal{GP}(\mu, \sigma^2)\)
  2. Evaluar en \(\lambda_{t+1} = \arg\min \tilde{f}(\lambda)\)

Simple, naturalmente parallelizable (muestrear varias funciones → evaluar varios puntos a la vez), y con buen equilibrio exploración/explotación. Muy usado en HPO moderno.

Comparación visual de acquisition functions

🧪 Compara funciones de adquisición

2.0

Arriba: GP con media (verde) y banda de confianza. Abajo: función de adquisición.
La línea punteada roja marca dónde se evaluará a continuación (máximo de la acquisition).

🌳 Surrogate models alternativos

Aunque los Gaussian Processes son el surrogate model clásico, tienen limitaciones (escala \(O(n^3)\), dificultad con variables categóricas). Existen alternativas importantes:

Tree-structured Parzen Estimator (TPE)

Usado por Optuna y Hyperopt. En lugar de modelar \(p(y|\lambda)\) directamente (como un GP), TPE modela las distribuciones de \(\lambda\) condicionadas en si el resultado fue «bueno» o «malo»:

TPE — modelo generativo $$p(\lambda | y) = \begin{cases} \ell(\lambda) & \text{si } y < y^* \quad \text{(buenos)} \\ g(\lambda) & \text{si } y \geq y^* \quad \text{(malos)} \end{cases}$$

Donde \(y^*\) es un cuantil (típicamente el percentil 25 de los valores observados). El siguiente punto se elige maximizando la ratio \(\ell(\lambda) / g(\lambda)\), que es equivalente a maximizar la Expected Improvement.

Ventajas de TPE:

  • Maneja naturalmente variables categóricas, condicionales y jerárquicas
  • Coste lineal \(O(n)\) en vez de cúbico
  • Escala bien a espacios de alta dimensionalidad
  • Es el motor de Optuna, la librería de HPO más popular

Random Forests (SMAC)

SMAC (Sequential Model-based Algorithm Configuration) usa Random Forests como surrogate. La incertidumbre se estima a partir de la varianza entre los árboles del ensemble. Ventajas:

  • Manejo natural de variables categóricas y condicionales
  • Robusto a outliers
  • Usado extensamente en AutoML (Auto-WEKA, Auto-sklearn)

Comparación de surrogate models

SurrogateCosteVariables categóricasAlta dimensiónUsado por
Gaussian Process \(O(n^3)\) ⚠️ Requiere codificación ⚠️ Problemas si \(d > 20\) BoTorch, GPyOpt, Spearmint
TPE \(O(n \log n)\) ✅ Natural ✅ Escala bien Optuna, Hyperopt
Random Forest \(O(n \log n)\) ✅ Natural ✅ Robusto SMAC, Auto-sklearn
Bayesian Neural Net \(O(n)\) (aprox.) ✅ Con embedding ✅ Muy bueno BOHB, DNGO

En la práctica, la elección del surrogate depende del tipo de espacio de búsqueda y del presupuesto computacional. Para espacios de búsqueda puramente continuos con pocas dimensiones, los GPs ofrecen la mejor incertidumbre calibrada. Para espacios mixtos (continuos + categóricos) o de alta dimensionalidad, TPE (el motor de Optuna) es la opción más pragmática. Los Random Forests (SMAC) brillan en problemas de configuración de algoritmos con muchas variables condicionales. Las BNNs son más experimentales pero prometedoras para problemas con cientos de dimensiones.

📚

Referencias clave de optimización bayesiana:

⚙️ Optimización bayesiana en la práctica

Aplicar BO en un proyecto real de deep learning requiere considerar varios aspectos prácticos que van más allá del algoritmo teórico.

Definir el espacio de búsqueda

Elegir bien el espacio de búsqueda \(\Lambda\) es crucial. Consejos:

  • Escala logarítmica para el learning rate: buscar en \([10^{-5}, 10^{-1}]\) en escala log, no en escala lineal. Lo mismo para weight decay.
  • Rango informado: usar conocimiento previo para acotar. Si sabes que un learning rate de \(10^{-1}\) diverge siempre, no lo incluyas.
  • Variables condicionales: si solo usas dropout cuando hay más de 3 capas, define el espacio de forma condicional (Optuna lo soporta nativamente).
def objective(trial):
    # ── Arquitectura ─────────────────────────────────────
    n_layers = trial.suggest_int("n_layers", 2, 6)
    hidden_dim = trial.suggest_categorical(
        "hidden_dim", [64, 128, 256, 512]
    )
    activation = trial.suggest_categorical(
        "activation", ["relu", "gelu", "silu"]
    )

    # ── Regularización (condicional) ─────────────────────
    use_dropout = trial.suggest_categorical("use_dropout", [True, False])
    if use_dropout:
        dropout_rate = trial.suggest_float("dropout_rate", 0.1, 0.5)

    # ── Entrenamiento ────────────────────────────────────
    lr = trial.suggest_float("lr", 1e-5, 1e-2, log=True)  # ← escala log!
    weight_decay = trial.suggest_float("wd", 1e-6, 1e-2, log=True)
    batch_size = trial.suggest_categorical(
        "batch_size", [32, 64, 128, 256]
    )

    # ── Construir y entrenar modelo ──────────────────────
    model = build_model(n_layers, hidden_dim, activation,
                        use_dropout, dropout_rate if use_dropout else 0)
    val_loss = train_and_evaluate(model, lr, weight_decay, batch_size)

    return val_loss  # Optuna minimiza por defecto

Early stopping y pruning

Una técnica clave para acelerar la BO: detener entrenamientos malos antes de que acaben. Si después de 5 épocas la pérdida es peor que cualquier configuración previa a las 5 épocas, probablemente no va a mejorar. Esto se llama pruning.

Ahorro típico: Con pruning agresivo (como el Median Pruner de Optuna), se puede reducir el tiempo total de HPO en un 50-80%, ya que las configuraciones malas se descartan tras pocas épocas.

Warm-starting y transfer learning en HPO

Si has optimizado hiperparámetros para un problema similar antes, puedes usar esos resultados como punto de partida (warm-starting). Algunos frameworks (Optuna, BoTorch) permiten inicializar el surrogate model con observaciones de estudios anteriores.

Multi-fidelity: Hyperband y BOHB

Las técnicas multi-fidelity entrenan con presupuestos variados (pocas épocas, subsets de datos) para descartar rápidamente las configuraciones malas:

Successive Halving y Hyperband

Successive Halving: Comienza con \(N\) configuraciones y un presupuesto mínimo (ej., 1 época). Entrena todas, descarta la mitad peor, duplica el presupuesto, y repite. Al final, solo la mejor configuración ha recibido el presupuesto completo.

Hyperband (Li et al., 2017): Ejecuta múltiples rondas de Successive Halving con diferentes trade-offs entre \(N\) y el presupuesto mínimo. Algunos brackets empiezan con muchas configuraciones y poco presupuesto; otros con pocas configuraciones y mucho presupuesto.

BOHB: Bayesian Optimization + Hyperband

BOHB (Falkner et al., 2018) combina lo mejor de ambos mundos: usa un modelo bayesiano (TPE con kernel density estimation) para guiar qué configuraciones muestrear, y Hyperband para decidir cuánto presupuesto dar a cada una. Es actualmente uno de los algoritmos de HPO más eficientes.

La combinación de estas técnicas — BO informada con pruning multi-fidelity — representa el estado del arte actual en HPO para deep learning. Herramientas como Optuna implementan muchas de estas ideas de forma accesible, permitiendo a los practicantes beneficiarse de décadas de investigación en optimización con solo unas pocas líneas de código.

📚

Referencias — Multi-fidelity y HPO moderna:

🧪 Pon todo esto en práctica: prueba la optimización bayesiana paso a paso →

📚 Librerías de HPO para Deep Learning

El ecosistema de librerías para HPO ha madurado enormemente. Aquí presentamos las más utilizadas en la práctica, con sus fortalezas y casos de uso ideales.

Optuna
⭐ Más popular TPE + CMA-ES

Framework japonés de HPO con una API define-by-run muy elegante: defines el espacio de búsqueda dentro de la función objetivo, lo que permite espacios condicionales de forma natural.

  • Algoritmos: TPE (defecto), CMA-ES, Grid, Random, GP
  • Pruning: MedianPruner, HyperbandPruner, PercentilePruner
  • Dashboard: optuna-dashboard para monitorear estudios
  • Integración: PyTorch Lightning, Keras, XGBoost, LightGBM
  • Distribución: Soporte nativo para ejecución distribuida con SQL/Redis
import optuna

def objective(trial):
    lr = trial.suggest_float("lr", 1e-5, 1e-2, log=True)
    n_layers = trial.suggest_int("n_layers", 2, 5)
    dropout = trial.suggest_float("dropout", 0.1, 0.5)

    model = build_model(n_layers, dropout)
    val_acc = train(model, lr)
    return val_acc

study = optuna.create_study(direction="maximize")
study.optimize(objective, n_trials=100)

print(f"Best: {study.best_value:.4f}")
print(f"Params: {study.best_params}")
Ray Tune
🔧 Escalable Multi-backend

Parte del ecosistema Ray para computación distribuida. Ideal para HPO a gran escala con clusters de GPUs.

  • Algoritmos: Integra Optuna, Hyperopt, BayesOpt, Ax, BOHB, etc.
  • Schedulers: ASHA (Hyperband async), PBT (Population Based Training)
  • Escala: De laptop a cluster multi-nodo sin cambiar código
  • Fault tolerance: Recuperación automática si falla un worker
  • Integración: PyTorch, TensorFlow, Hugging Face Transformers
from ray import tune
from ray.tune.schedulers import ASHAScheduler

search_space = {
    "lr": tune.loguniform(1e-5, 1e-2),
    "batch_size": tune.choice([32, 64, 128]),
    "n_layers": tune.randint(2, 6),
}

scheduler = ASHAScheduler(
    max_t=100,          # max epochs
    grace_period=5,     # mínimo de épocas antes de podar
    reduction_factor=3,  # conservar top 1/3
)

result = tune.run(
    train_fn,
    config=search_space,
    num_samples=50,
    scheduler=scheduler,
    resources_per_trial={"gpu": 1},
)
Keras Tuner
🧩 Simple TensorFlow

Librería oficial del equipo de Keras para HPO. La más sencilla de usar si trabajas con el ecosistema TensorFlow/Keras.

  • Algoritmos: Random, Hyperband, Bayesian (GP)
  • API: Similar a construir modelos Keras (HyperModel class)
  • Oracle: Motor de búsqueda extensible
  • Ideal para: Proyectos Keras simples a medianos
W&B Sweeps
📊 Visual Cloud

Weights & Biases ofrece HPO integrado con su plataforma de tracking. Ideal si ya usas W&B para logging de experimentos.

  • Algoritmos: Grid, Random, Bayesian (GP)
  • Visualización: Parallel coordinates, importance plots en el dashboard
  • Early termination: Hyperband integrado
  • Configuración: YAML declarativo o Python API
BoTorch / Ax
🔬 Research Meta/PyTorch

BoTorch es el framework de BO de Meta, construido sobre PyTorch y GPyTorch. Ax es la capa de alto nivel sobre BoTorch.

  • GP flexibles: Kernels custom, multi-task, multi-objective
  • Acquisition functions: EI, KG, multi-fidelity, paralelo
  • Ideal para: Investigadores, HPO multi-objetivo, problemas complejos
  • Limitación: Curva de aprendizaje más pronunciada

¿Cuál elegir?

🗺️

Guía rápida de decisión:

  • Primera opción general: Optuna — API limpia, eficiente, bien documentada
  • Cluster de GPUs: Ray Tune — escalabilidad sin cambiar código
  • Ecosistema Keras/TF: Keras Tuner — la más simple si usas Keras
  • Ya usas W&B: W&B Sweeps — integración nativa con tracking
  • Investigación / multi-objetivo: BoTorch/Ax — máxima flexibilidad

Comparación de librerías

LibreríaAlgoritmo principalPruningDistribuidoDificultad
Optuna TPE ✅ Excelente ✅ SQL/Redis ⭐ Fácil
Ray Tune Multi-backend ✅ ASHA/PBT ✅ Ray cluster ⭐⭐ Media
Keras Tuner Bayesian/Hyperband ✅ Hyperband ⚠️ Limitado ⭐ Fácil
W&B Sweeps Bayesian (GP) ✅ Hyperband ✅ Cloud ⭐ Fácil
BoTorch/Ax GP (BoTorch) ⚠️ Manual ✅ Ax + scheduler ⭐⭐⭐ Avanzada

Todas estas librerías pueden optimizar los hiperparámetros más importantes de tu pipeline de entrenamiento, incluyendo la elección del optimizador y del scheduler de learning rate. Para entender en profundidad qué optimizadores y schedulers existen y cuándo usar cada uno, consulta el submódulo de Optimizers y Schedulers, donde cubrimos desde SGD hasta AdamW y desde Step Decay hasta Cosine Annealing con Warmup.

🏁 Resumen y mejores prácticas

La optimización de hiperparámetros es una disciplina esencial que puede marcar la diferencia entre un modelo mediocre y uno excelente. Aquí resumimos las lecciones clave:

1️⃣
Nunca optimices con el test set. Usa train/validation/test split o cross-validation. El test set es sagrado.
2️⃣
Empieza con Random Search. Es simple, parallelizable y sorprendentemente efectivo. 60 evaluaciones cubren el 95% del espacio.
3️⃣
Usa Bayesian Optimization para refinar. Cuando cada evaluación cuesta horas, la BO encuentra mejores configuraciones con menos evaluaciones.
4️⃣
Usa escala logarítmica para learning rate y weight decay. La sensibilidad del modelo a estos parámetros es exponencial.
5️⃣
Activa pruning/early stopping. Descarta configuraciones malas rápido. Puede ahorrar un 50-80% del tiempo total.
6️⃣
Prioriza los hiperparámetros que más importan: learning rate > batch size > profundidad > regularización > otros.
🎓

Receta práctica para empezar:

  1. Instala Optuna: pip install optuna
  2. Define tu función objetivo con trial.suggest_*
  3. Activa el MedianPruner para early stopping
  4. Ejecuta 50-100 trials
  5. Analiza la importancia de hiperparámetros con optuna.visualization
  6. Entrena el modelo final con los mejores hiperparámetros en train+validation
  7. Evalúa una sola vez en el test set y reporta
📚

Lecturas recomendadas:

🧪 Herramientas interactivas