Validación cruzada anidada: por qué tu puntaje de validación te miente
El problema de la ‘adivinación afortunada’
Pasas horas ajustando tu modelo XGBoost. La precisión de validación alcanza un hermoso 95%, y te sientes como un héroe. Luego lo despliegas o lo ejecutas contra el conjunto de prueba final, y la puntuación cae al 75%.
¿Qué pasó? Lo más probable es que te hayas topado con el Sesgo de Optimización. El ajuste de hiperparámetros es como un examen de opción múltiple en el que sigues adivinando hasta encontrar la respuesta correcta. Prueba 1,000 combinaciones diferentes de configuraciones y una de ellas inevitablemente parecerá buena por pura suerte. No encontraste un modelo que entiende los datos; encontraste uno que tuvo ‘suerte’ en ese conjunto de validación específico.
Tu puntuación de validación ahora es engañosa. Para ver qué tan mal puede llegar a ser esto, aquí hay un código que intenta ‘predecir’ una variable objetivo usando nada más que ruido aleatorio.
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
# Create 100 rows of random noise (100 different 'features')
np.random.seed(42)
X_noise = np.random.normal(size=(100, 100))
y = np.random.randint(0, 2, size=100)
# Let's try to find a single feature that 'predicts' the target
best_score = 0
for i in range(100):
score = cross_val_score(LogisticRegression(), X_noise[:, i:i+1], y, cv=5).mean()
if score > best_score:
best_score = score
print(f"Best 'Lucky' Accuracy: {best_score:.2f}")
# Output will be around 0.65-0.70.
# We found a 'pattern' in pure random noise just by looking long enough!
Cuanto más ajustas, más ‘filtras’ información de tu conjunto de validación hacia tu modelo. Esta es la parte más difícil de aceptar de la inferencia causal y el aprendizaje automático: tu búsqueda del mejor modelo es en sí misma una forma de entrenamiento que puede sobreajustarse.
La solución: una prueba dentro de una prueba
¿Cómo solucionamos esto? Usamos Validación Cruzada Anidada. Piensa en ello como un ‘Examen Secreto.’
La validación cruzada estándar ejecuta un solo ciclo. Divides los datos, entrenas con una parte y validas con el resto. La validación cruzada anidada añade una segunda capa externa.
- El Ciclo Interno: Este es el ‘Examen de Práctica.’ Pruebas diferentes hiperparámetros (como la tasa de aprendizaje o la profundidad) para encontrar las mejores configuraciones.
- El Ciclo Externo: Este es el ‘Examen Final.’ Una vez que el ciclo interno elige lo que cree que es el mejor modelo, probamos ese modelo con datos que nunca ha visto, ni siquiera durante el proceso de ajuste.
La distinción importa. No solo estamos verificando si un modelo específico es bueno. Estamos probando el proceso completo de cómo elegimos los modelos. Si nuestro ajuste es propenso a ‘conjeturas afortunadas’, el ciclo externo lo detecta y muestra una puntuación más baja y más honesta.
Construyámoslo: Optuna se encuentra con Scikit-Learn
Optuna ejecuta el bucle interno como nuestro Buscador Inteligente. En lugar de probar todas las combinaciones como lo hace Grid Search, utiliza la optimización bayesiana para encontrar rápidamente las mejores configuraciones.
El conjunto de datos Wine es pequeño. Esto significa que es fácil causar un sobreajuste por accidente durante el ajuste.
import optuna
import numpy as np
from sklearn.datasets import load_wine
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import KFold, cross_val_score
data = load_wine()
X, y = data.data, data.target
def objective(trial, X_train, y_train):
# The Inner Loop: Suggestions for hyperparameters
n_estimators = trial.suggest_int("n_estimators", 10, 100)
max_depth = trial.suggest_int("max_depth", 2, 32)
clf = RandomForestClassifier(n_estimators=n_estimators, max_depth=max_depth)
# Inner CV to find the best params
score = cross_val_score(clf, X_train, y_train, cv=3).mean()
return score
# The Outer Loop: The Final Exam
outer_cv = KFold(n_splits=5, shuffle=True, random_state=42)
outer_scores = []
print("Starting Nested CV...")
for train_idx, test_idx in outer_cv.split(X):
X_train, X_test = X[train_idx], X[test_idx]
y_train, y_test = y[train_idx], y[test_idx]
# Optimize hyperparameters for THIS specific outer fold
study = optuna.create_study(direction="maximize")
study.optimize(lambda trial: objective(trial, X_train, y_train), n_trials=20)
# Build a model using the best params found
best_model = RandomForestClassifier(**study.best_params)
best_model.fit(X_train, y_train)
# Evaluate on the 'Secret' test set
final_score = best_model.score(X_test, y_test)
outer_scores.append(final_score)
print(f"Nested CV Average Score: {np.mean(outer_scores):.4f}")
Interpretando los números: el momento de la verdad
Al ejecutar el código anterior, es probable que notes que el Nested CV Average Score resulta un poco más bajo de lo que Optuna reportó durante study.optimize.
La conclusión: confía en el número más bajo. Es el honesto.
- El puntaje ingenuo: Lo que Optuna ve. Es optimista, porque elige el mejor de muchos intentos.
- El puntaje anidado: La prueba de realidad. Te dice: ‘Si ejecuto este proceso de ajuste en datos nuevos, así es como se desempeña realmente.’
¿Un puntaje ingenuo de 0.98 frente a un puntaje anidado de 0.85? Tu proceso de ajuste está alucinando. Los hiperparámetros están ajustados al ruido de tu conjunto de validación, no a la señal de los datos.
¿Cuándo deberías usarlo realmente?
La validación cruzada anidada (Nested CV) es computacionalmente costosa. Cinco pliegues externos combinados con cinco pliegues internos significa entrenar tu modelo 25 veces por ejecución.
Entonces, ¿cuándo vale la pena el tiempo de espera adicional? Piénsalo como un seguro. Cuantos menos datos tengas, más seguro necesitarás.
| Tamaño del conjunto de datos | Estrategia | ¿Por qué? |
|---|---|---|
| Pequeño (< 2,000 filas) | Nested CV | Alto riesgo de conjuntos de parámetros ‘afortunados’. |
| Mediano (2k - 20k filas) | Nested CV o CV repetido | Aún propenso a la varianza; vale la pena el cómputo adicional. |
| Grande (> 100k filas) | Train/Val/Test simple | Los datos son abundantes; un solo conjunto hold-out suele ser estable. |
- Ajustar los hiperparámetros es una forma de entrenamiento, por lo que puede haber sobreajuste.
- Las puntuaciones de un CV estándar pueden ser demasiado optimistas debido al ‘Sesgo de optimización’.
- El Nested CV utiliza un bucle externo para proporcionar un ‘Examen final’ que el proceso de ajuste nunca observa.
- Usa Nested CV siempre que tengas un conjunto de datos pequeño y quieras conocer la verdad sobre el rendimiento de tu modelo.
Validar tu proceso genera confianza real. Tu 90% de precisión de hoy seguirá siendo un 90% de precisión mañana.
Comprueba tu comprensión
Las preguntas a continuación avanzan desde el simple recuerdo hasta el diseño abierto, siguiendo aproximadamente la Taxonomía de Bloom.
Recordar ¿Qué es el Sesgo de optimización y por qué el artículo dice que el ajuste de hiperparámetros puede “filtrar” información del conjunto de validación hacia el modelo?
Comprender Explica con tus propias palabras la diferencia entre el bucle interno (“Examen de práctica”) y el bucle externo (“Examen final”) en la Validación Cruzada Anidada, y qué pregunta responde cada bucle.
Aplicar Usando la tabla de tamaño del conjunto de datos de la sección “¿Cuándo deberías usar esto realmente?”, tienes 5,000 filas y estás realizando una búsqueda de ajuste al estilo Kaggle. ¿Qué estrategia recomienda la tabla y contra qué riesgo te estás protegiendo?
Analizar El artículo dice que el “puntaje ingenuo” es sistemáticamente más alto que el “puntaje anidado”. Explica paso a paso por qué elegir el mejor de múltiples pruebas infla el puntaje ingenuo y por qué el bucle externo es inmune a esa inflación.
Evaluar El artículo presenta la Validación Cruzada Anidada (Nested CV) como un “seguro” que implica un costo computacional adicional. Critica esa perspectiva: describe un escenario realista en el que ejecutar Nested CV no valga el costo, y otro en el que claramente sí lo valga, basándote en la lógica del tamaño del conjunto de datos.
Crear Diseña un pequeño experimento (usando el ejemplo de ruido aleatorio como plantilla) que le demuestre el Sesgo de Optimización a un colega escéptico. Describe los datos, el bucle de ajuste y los dos puntajes que compararías para probar que un ajuste agresivo sobre el ruido produce un resultado “afortunado” pero carente de significado.
Esta traducción fue generada automáticamente y puede contener errores. Si el idioma inglés es tu preferencia, puedes leer el artículo original en inglés .
Artículos relacionados
- Aprendizaje Automático En revisión
Validación cruzada anidada: cómo ajustar tu modelo sin engañarte a ti mismo
Aprende cómo la validación cruzada anidada evita el sesgo optimista al ajustar los hiperparámetros, brindándote una estimación honesta del rendimiento del modelo antes de enviarlo a producción.
- Aprendizaje Automático En revisión
¿Qué es la validación cruzada y cómo evitar hacerla mal?
Aprende a hacer validación cruzada de la manera correcta: evita el sobreajuste, previene la fuga de datos con pipelines, lee la desviación estándar y maneja las series de tiempo correctamente.
- Aprendizaje Automático En revisión
Por qué falla tu modelo KNN en alta dimensionalidad: Entendiendo la maldición de la dimensionalidad
Aprende por qué los modelos KNN fallan en alta dimensionalidad debido a la maldición de la dimensionalidad y cómo el PCA o la selección de características pueden restaurar tu precisión predictiva.
- Aprendizaje Automático En revisión
Curvas de aprendizaje: Cómo leer la mente de tu modelo para corregir el sobreajuste y el subajuste
Aprende a leer las curvas de aprendizaje para diagnosticar el sobreajuste y el subajuste, distinguir entre el alto sesgo y la alta varianza, y elegir la solución correcta para potenciar tu modelo.
¿Buscas otra cosa?
Busca en todos los artículos por título, resumen o tema.