まとめ
- La validación cruzada divide el dataset en pliegues para estimar el rendimiento con mayor estabilidad.
- Compara el enfoque con un único hold-out y observa cómo influye el número de pliegues.
- Revisa consejos prácticos sobre el diseño de pliegues, el coste computacional y la presentación de resultados.
La validación cruzada separa los datos en varias partes, entrena el modelo con una porción y lo evalúa con la restante para comprobar la validez global del análisis. — Validación cruzada (Wikipedia)
1. ¿En qué consiste? #
- Divide los datos en varios “folds” e intercala qué fold actúa como validación.
- Un único
train_test_splitpuede arrojar gran varianza; la validación cruzada promedia el rendimiento. - Las variantes más comunes son k-fold y stratified k-fold (mantiene el balance de clases por fold).
2. Ejemplo básico en Python 3.13 #
Supongamos Python 3.13 y scikit-learn instalados:
python --version # Python 3.13.0
pip install scikit-learn matplotlib
El siguiente ejemplo compara un hold-out simple con una validación cruzada de 5 pliegues en un dataset sintético desequilibrado.
from __future__ import annotations
import numpy as np
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import cross_validate, train_test_split
RANDOM_STATE = 42
def make_dataset() -> tuple[np.ndarray, np.ndarray]:
"""Genera un dataset binario desequilibrado."""
features, labels = make_classification(
n_samples=300,
n_classes=2,
weights=[0.2, 0.8],
n_informative=4,
n_features=6,
n_clusters_per_class=2,
shuffle=True,
random_state=RANDOM_STATE,
)
return features, labels
def holdout_score() -> float:
"""Calcula el ROC-AUC con una sola partición hold-out."""
features, labels = make_dataset()
x_train, x_valid, y_train, y_valid = train_test_split(
features,
labels,
test_size=0.2,
stratify=labels,
random_state=RANDOM_STATE,
)
model = RandomForestClassifier(max_depth=4, random_state=RANDOM_STATE)
model.fit(x_train, y_train)
predictions = model.predict(x_valid)
return roc_auc_score(y_valid, predictions)
def cross_validation_scores() -> dict[str, float]:
"""Ejecuta validación cruzada 5-fold y promedia ROC-AUC y Accuracy."""
features, labels = make_dataset()
model = RandomForestClassifier(max_depth=4, random_state=RANDOM_STATE)
scores = cross_validate(
model,
features,
labels,
cv=5,
scoring=("roc_auc", "accuracy"),
return_train_score=False,
n_jobs=None,
)
return {
"roc_auc": float(np.mean(scores["test_roc_auc"])),
"accuracy": float(np.mean(scores["test_accuracy"])),
}
if __name__ == "__main__":
holdout = holdout_score()
print(f"Hold-out ROC-AUC: {holdout:.3f}")
cv_result = cross_validation_scores()
print(f"ROC-AUC (5 folds): {cv_result['roc_auc']:.3f}")
print(f"Accuracy (5 folds): {cv_result['accuracy']:.3f}")
Salida de ejemplo:
Hold-out ROC-AUC: 0.528
ROC-AUC (5 folds): 0.844
Accuracy (5 folds): 0.858
La partición única produce un ROC-AUC cercano al azar, mientras que la validación cruzada ofrece un estimador mucho más estable.
3. Recomendaciones de diseño #
- Número de pliegues
Cinco o diez son lo habitual. Con datos muy escasos puede usarseLeaveOneOut, aunque el coste se dispara. - Estratificación
Ante clases desequilibradas utilizaStratifiedKFold(o el parámetrostratify) para conservar las proporciones. - Múltiples métricas
scoringacepta una tupla para calcular varias métricas a la vez. Combinar ROC-AUC y Accuracy ayuda a ver compensaciones. - Integración con la búsqueda de hiperparámetros
GridSearchCVyRandomizedSearchCVejecutan validación cruzada internamente, lo que evita sobreajuste durante el tuning.
4. Lista de comprobación #
- ¿La estrategia de partición es adecuada?
Si hay dependencia temporal, recurre aTimeSeriesSpliten lugar de pliegues aleatorios. - ¿Las métricas clave están incluidas?
Añade enscoringlas métricas que importan al negocio para mantener alineadas las decisiones. - ¿Se ha estimado el coste?
La validación cruzada entrena el modelo k veces; planifica el tiempo y recursos. - ¿El experimento es reproducible?
Documenta versión de Python, semillas y configuración de pliegues en tus notebooks o scripts.
Resumen #
- La validación cruzada reduce la varianza y ayuda a medir la capacidad de generalización.
cross_validatede scikit-learn facilita el cálculo simultáneo de varias métricas.- Diseña pliegues, métricas y presupuesto de cómputo con intención y lleva el proceso al entorno productivo.