A lo largo del módulo han ido apareciendo pistas: el árbol sin límite de profundidad que clavaba el 100 % en entrenamiento y se hundía en test (06-01), el return_train_score de cross_validate "para diagnosticar overfitting" (06-03), el AUC sospechosamente perfecto que invitaba a buscar fugas (06-04). Esta lección junta todas esas pistas en el diagnóstico central del Machine Learning: ¿mi modelo memoriza (overfitting) o no aprende lo suficiente (underfitting)? Aprenderemos a diagnosticarlo comparando el error de entrenamiento con el de validación, a entender el compromiso sesgo-varianza que hay detrás, y a usar dos herramientas gráficas — curvas de validación y curvas de aprendizaje — que responden a las dos preguntas prácticas por excelencia: ¿cuánta complejidad conviene? y ¿ayudarían más datos? Cerraremos el módulo con una checklist de evaluación honesta que resume todo lo aprendido.
Contenido
- Definiciones y analogía: memorizar el examen vs. no estudiar
- Diagnóstico: error de entrenamiento frente a error de validación
- El compromiso sesgo-varianza
- Curvas de validación: ¿cuánta complejidad?
- Curvas de aprendizaje: ¿ayudarían más datos?
- Remedios del overfitting y del underfitting
- Cierre del módulo: checklist de evaluación honesta
Definiciones y analogía: memorizar el examen vs. no estudiar
Volvamos a la analogía del examen de 06-01, ahora con tres estudiantes:
- El memorión se aprende de carrerilla las soluciones de los ejercicios del libro, coma por coma. En esos ejercicios saca un 10; en el examen (preguntas nuevas), suspende: nunca entendió los conceptos, solo los casos concretos, ruido incluido. Es el overfitting (sobreajuste): el modelo se ajusta tanto a los datos de entrenamiento que captura sus peculiaridades y su ruido, y pierde capacidad de generalizar.
- El que no estudió apenas hojeó el temario. Falla los ejercicios del libro y el examen por igual: no capturó ni siquiera los patrones básicos. Es el underfitting (infraajuste): el modelo es demasiado simple (o las features demasiado pobres) para la estructura real del problema.
- El que entendió la materia hace bien los ejercicios (sin clavarlos todos: no memorizó erratas) y el examen le sale parecido. Es el punto dulce: aprende el patrón, ignora el ruido.
En MercaFresh ya vimos a los tres: el árbol sin podar de 04-03 era el memorión (una hoja por cliente); una regresión logística sobre una única feature pobre sería el que no estudió; el árbol con max_depth=5 del torneo de 06-03 se acercaba al punto dulce.
Diagnóstico: error de entrenamiento frente a error de validación
El diagnóstico se hace con dos números, no uno: el error (o métrica) en entrenamiento y en validación. Los cuatro escenarios posibles:
| Error train | Error validación | Diagnóstico | Ejemplo MercaFresh |
|---|---|---|---|
| Bajo | Bajo (similar) | Punto dulce — buen ajuste | Logística con buenas features RFM: F1 0.66 / 0.63 |
| Bajo | Alto (brecha grande) | Overfitting | Árbol sin límite: F1 1.00 / 0.62 |
| Alto | Alto (similar) | Underfitting | Logística con una sola feature: F1 0.35 / 0.34 |
| Alto | Bajo | Sospecha de bug | Fuga de datos, conjuntos mal construidos, azar en muestras pequeñas |
Reglas de lectura:
- La brecha train − validación mide el sobreajuste: cuanto mayor, más está memorizando el modelo.
- El nivel del error de validación mide la calidad real. Un modelo puede tener brecha cero y ser pésimo (underfitting) o brecha enorme con validación decente (overfitting aprovechable, pero mejorable).
- El cuarto escenario no debería existir: si validación supera con claridad a entrenamiento, revisa el protocolo (¿fuga al revés?, ¿validación demasiado pequeña y con suerte?).
En código, es el return_train_score=True de 06-03:
from sklearn.model_selection import cross_validate
from sklearn.tree import DecisionTreeClassifier
for prof in [None, 5]: # None = sin límite
arbol = DecisionTreeClassifier(max_depth=prof, random_state=42)
res = cross_validate(arbol, X_train, y_train, cv=5,
scoring="f1", return_train_score=True)
print(f"max_depth={prof}: F1 train = {res['train_score'].mean():.2f} | "
f"F1 val = {res['test_score'].mean():.2f}")
# max_depth=None: F1 train = 1.00 | F1 val = 0.58 ← overfitting de manual
# max_depth=5 : F1 train = 0.70 | F1 val = 0.63 ← brecha razonableEl compromiso sesgo-varianza
Detrás de los dos fenómenos hay un compromiso fundamental. A nivel intuitivo, el error de un modelo en datos nuevos tiene dos componentes controlables:
- Sesgo (bias): error por suposiciones demasiado rígidas. Un modelo con alto sesgo (una recta para un fenómeno curvo) falla sistemáticamente igual, se entrene con los datos que se entrene. Es la firma del underfitting.
- Varianza: error por sensibilidad excesiva a los datos concretos de entrenamiento. Un modelo con alta varianza (un árbol profundísimo) cambia drásticamente si cambias unas pocas filas: aprende el ruido de esa muestra. Es la firma del overfitting. (De hecho, la desviación entre folds de 06-03 nos daba ya una medida empírica de esta sensibilidad.)
Al aumentar la complejidad del modelo, el sesgo baja (puede representar patrones más ricos) pero la varianza sube (tiene más libertad para perseguir el ruido). El error total dibuja una U:
flowchart LR
subgraph Eje["Complejidad del modelo →"]
A["Poca complejidad<br/>─────────<br/>Sesgo ALTO<br/>Varianza baja<br/>= UNDERFITTING<br/>(train mal, val mal)"]
B["Complejidad adecuada<br/>─────────<br/>Sesgo moderado<br/>Varianza moderada<br/>= PUNTO DULCE<br/>(error de validación mínimo)"]
C["Mucha complejidad<br/>─────────<br/>Sesgo bajo<br/>Varianza ALTA<br/>= OVERFITTING<br/>(train perfecto, val mal)"]
end
A --> B --> C
Cada algoritmo del módulo 4 tiene sus mandos de complejidad: max_depth y compañía en árboles, el número de vecinos en K-NN (k pequeño = más varianza), el tamaño de las capas en el MLP, la C y el kernel en SVM... Encontrar el punto dulce de esos mandos es, precisamente, para lo que sirve el conjunto de validación de 06-01 — y lo que ahora vamos a visualizar.
Curvas de validación: ¿cuánta complejidad?
La curva de validación dibuja la métrica en train y en validación en función de un hiperparámetro de complejidad. Con validation_curve sobre el max_depth del árbol de churn de 04-03:
from sklearn.model_selection import validation_curve
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
import numpy as np
profundidades = range(1, 16)
train_scores, val_scores = validation_curve(
DecisionTreeClassifier(random_state=42),
X_train, y_train,
param_name="max_depth", param_range=profundidades,
cv=5, scoring="f1",
)
tr_m, va_m = train_scores.mean(axis=1), val_scores.mean(axis=1)
va_s = val_scores.std(axis=1)
plt.plot(profundidades, tr_m, "o-", label="F1 entrenamiento")
plt.plot(profundidades, va_m, "o-", label="F1 validación")
plt.fill_between(profundidades, va_m - va_s, va_m + va_s, alpha=0.2) # ± std (06-03)
plt.axvline(profundidades[np.argmax(va_m)], ls="--", color="gray",
label=f"Óptimo: max_depth={profundidades[np.argmax(va_m)]}")
plt.xlabel("max_depth"); plt.ylabel("F1"); plt.legend(); plt.show()Cómo se lee el gráfico resultante (el patrón es siempre el mismo):
- Zona izquierda (max_depth 1–3): ambas curvas bajas y juntas → underfitting; el árbol es demasiado simple hasta para el train.
- Zona derecha (max_depth > 8): el F1 de train sigue subiendo hacia 1.0 mientras el de validación baja → overfitting; cada nivel extra de profundidad memoriza ruido.
- El máximo de la curva de validación (típicamente por max_depth 4–6 en el churn) es el punto dulce: la complejidad justa. Es la "U" del sesgo-varianza, vista en datos reales.
Esto explica el resultado del ejercicio 3 de la lección 06-03 (3 corto, 10 pasado, 5 ganador). La curva de validación explora un hiperparámetro con los demás fijos; la exploración sistemática de varios a la vez es la optimización de hiperparámetros de 07-05.
Curvas de aprendizaje: ¿ayudarían más datos?
La otra pregunta práctica: si MercaFresh invirtiera en recopilar más historial de clientes, ¿mejoraría el modelo? La curva de aprendizaje dibuja la métrica en train y validación en función del número de ejemplos de entrenamiento:
from sklearn.model_selection import learning_curve
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
pipe = Pipeline([("sc", StandardScaler()),
("clf", LogisticRegression(max_iter=1000))])
tamanos, train_scores, val_scores = learning_curve(
pipe, X_train, y_train,
train_sizes=np.linspace(0.1, 1.0, 8), # del 10 % al 100 % del train
cv=5, scoring="f1",
)
plt.plot(tamanos, train_scores.mean(axis=1), "o-", label="F1 entrenamiento")
plt.plot(tamanos, val_scores.mean(axis=1), "o-", label="F1 validación")
plt.xlabel("Nº de ejemplos de entrenamiento"); plt.ylabel("F1")
plt.legend(); plt.show()Interpretación según la forma de las curvas:
| Forma al llegar al 100 % de los datos | Diagnóstico | ¿Más datos? |
|---|---|---|
| Curvas separadas (train alto, val bajo) y la de validación aún sube | Overfitting con margen | Sí: más datos cerrarían la brecha |
| Curvas ya convergidas (juntas y planas) a nivel alto | Punto dulce estable | No: más datos apenas aportan |
| Curvas convergidas a nivel bajo | Underfitting | No: el problema es el modelo o las features, no el volumen |
Es un gráfico valiosísimo para decidir inversiones: recopilar datos cuesta dinero y meses, y la curva de aprendizaje dice de antemano si servirá de algo.
Remedios del overfitting y del underfitting
Diagnóstico hecho; recetario:
Contra el overfitting (brecha train-validación grande)
- Más datos de entrenamiento — el remedio más fiable cuando la curva de aprendizaje muestra margen: con más ejemplos, el ruido individual pesa menos.
- Reducir la complejidad del modelo: menos profundidad en el árbol, más vecinos en K-NN, menos neuronas en el MLP, o directamente un algoritmo más simple. La curva de validación indica cuánto recortar.
- Menos features / mejores features: eliminar variables ruidosas o redundantes reduce las oportunidades de memorizar (PCA, de 05-03, puede ayudar como reducción previa).
- Regularización: penalizar los pesos grandes del modelo para forzarlo a soluciones más suaves. Es el remedio estrella en modelos lineales y redes, y tiene lección propia — Ridge, Lasso y Elastic Net en 07-01 —, así que aquí solo la dejamos apuntada.
- Early stopping (mencionado): en modelos que entrenan por iteraciones (MLP, y el gradient boosting de 07-03), detener el entrenamiento cuando el error de validación deja de mejorar, aunque el de train siga bajando.
- Ensembles: combinar muchos modelos de alta varianza promedia sus errores individuales (la varianza se cancela). Es la idea del Random Forest y compañía — 07-02.
Contra el underfitting (train y validación mal por igual)
- Aumentar la complejidad: más profundidad, más neuronas, un kernel no lineal en la SVM, un algoritmo más expresivo.
- Mejores features: a menudo el cuello de botella no es el modelo sino la información que recibe. La ingeniería de características de 03-06 (ratios, agregados RFM, interacciones) suele mover más la aguja que cualquier cambio de algoritmo.
- Menos regularización (si la hay) y, en modelos iterativos, entrenar más tiempo.
- Lo que no funciona: añadir más filas. Un modelo que no captura el patrón con 10.000 ejemplos tampoco lo hará con 100.000 — lo confirma la curva de aprendizaje convergida a nivel bajo.
| Diagnóstico | Palancas principales | Dónde se desarrollan |
|---|---|---|
| Overfitting | Más datos, menos complejidad, regularización, early stopping, ensembles | 07-01, 07-02, 07-03 |
| Underfitting | Más complejidad, mejores features, menos regularización | 03-06, módulo 7 |
Cierre del módulo: checklist de evaluación honesta
Este módulo empezó con la pregunta que dejó abierta el módulo 5: "¿es bueno de verdad mi modelo?". Ya podemos responderla con método. La checklist, lección a lección:
- División limpia (06-01): test apartado desde el principio y tocado una sola vez;
stratifycon clases desbalanceadas; división cronológica si hay tiempo; sin duplicados repartidos; ninguna feature que no existiera en el momento de predecir. - Métrica pactada de antemano (06-02): elegida con el negocio según los costes de FP y FN (recall para el churn de MercaFresh), nunca a posteriori; matriz de confusión siempre a la vista.
- Baseline (06-02, retomando 01-04): DummyClassifier/DummyRegressor evaluados con la misma métrica; el modelo debe ganarles con claridad o no hay historia que contar.
- Validación cruzada (06-03): media ± desviación, mismos folds para todos los candidatos, Pipeline dentro de la CV; diferencias entre modelos juzgadas con el escepticismo de 02-04.
- Umbral operativo (06-04): elegido en validación según costes y capacidad, no heredado del 0.5; AUC para comparar, curva para decidir.
- Diagnóstico train vs. validación (06-05): brecha vigilada, curva de validación para la complejidad, curva de aprendizaje antes de pedir más datos.
- Escepticismo final: un resultado demasiado bueno (accuracy 99 %, AUC 0.99) se investiga como un bug — casi siempre lo es (fuga de datos).
Un modelo que pasa esta checklist tiene un rendimiento creíble. La siguiente frontera es hacerlo mejor, y de eso trata el módulo 7.
Errores Comunes y Consejos
- Mirar solo el error de validación e ignorar el de train. Sin los dos números no hay diagnóstico: no sabrás si atacar el sesgo o la varianza, y los remedios son opuestos.
- Tratar todo mal resultado como overfitting. El underfitting es igual de frecuente y se cura con lo contrario (más complejidad, no menos). Diagnostica antes de medicar.
- Perseguir la brecha cero. Una brecha pequeña es normal y sana; un modelo con train = validación exactos suele estar infraajustado. Lo que se optimiza es el error de validación, no la brecha.
- Añadir datos sin mirar la curva de aprendizaje. Si las curvas ya convergieron, esos meses de recolección no moverán la métrica.
- Ajustar la complejidad mirando el test. Las curvas de validación se construyen con CV sobre el train; el test sigue en su caja fuerte hasta el final (06-01).
- Consejo: imprime siempre la pareja (métrica train, métrica validación) en cada experimento, desde el primer día. Es un hábito de una línea de código que detecta el 90 % de los problemas de modelado a la primera.
Ejercicios
Ejercicio 1
Diagnostica cada escenario (overfitting, underfitting, punto dulce o sospecha de bug) y propón la primera acción correctora:
- (a) K-NN con k=1 sobre el churn: F1 train = 0.99, F1 validación = 0.55.
- (b) Regresión lineal del gasto mensual con solo la edad como feature: R² train = 0.12, R² validación = 0.11.
- (c) Logística con features RFM: F1 train = 0.68, F1 validación = 0.64.
- (d) Árbol sobre un dataset con la columna
motivo_baja: F1 train = 0.99, F1 validación = 0.99.
Ejercicio 2
Escribe el código que calcula la curva de validación del hiperparámetro n_neighbors (valores 1 a 30) de un KNeighborsClassifier (con escalado en Pipeline) sobre el churn, con 5-fold CV y scoring="f1", e imprime el k óptimo. Indica qué extremo del rango esperas que sobreajuste y por qué.
Ejercicio 3
La curva de aprendizaje del modelo de churn muestra: con el 100 % de los datos, F1 train = 0.91, F1 validación = 0.63, y la curva de validación lleva creciendo desde el 40 % de los datos sin aplanarse. MercaFresh puede (a) comprar 6 meses más de historial o (b) pagar una consultoría para probar más algoritmos. ¿Qué opción respalda el gráfico y por qué?
Soluciones
Solución 1.
- (a) Overfitting de libro: k=1 memoriza cada cliente (máxima varianza). Primera acción: aumentar k (la curva de validación sobre
n_neighborsdiría cuánto). - (b) Underfitting: train y validación igual de bajos; la edad sola no explica el gasto. Primera acción: mejores features (las RFM de 03-06), no más complejidad sobre una feature pobre.
- (c) Punto dulce: buen nivel de validación y brecha pequeña (0.04). Acción: ninguna urgente; afinar con las técnicas del módulo 7 si se quiere exprimir más.
- (d) Sospecha de bug: rendimiento casi perfecto también en validación.
motivo_bajasolo se rellena después de la baja: es la fuga de información futura de 06-01. Primera acción: eliminar la columna y reevaluar.
Solución 2.
from sklearn.model_selection import validation_curve
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
import numpy as np
pipe = Pipeline([("sc", StandardScaler()), ("knn", KNeighborsClassifier())])
ks = range(1, 31)
train_sc, val_sc = validation_curve(
pipe, X_train, y_train,
param_name="knn__n_neighbors", # sintaxis paso__parametro del Pipeline
param_range=ks, cv=5, scoring="f1",
)
va_m = val_sc.mean(axis=1)
print(f"k óptimo: {list(ks)[np.argmax(va_m)]} (F1 val = {va_m.max():.3f})")Sobreajusta el extremo k pequeño (k=1 en particular): cada predicción depende de un único vecino, así que el modelo reproduce el ruido individual del train (alta varianza). Con k muy grande ocurre lo contrario: la predicción se parece cada vez más a "la clase mayoritaria del entorno amplio" y aparece underfitting.
Solución 3. El gráfico respalda la opción (a), más datos: hay una brecha grande entre train (0.91) y validación (0.63) — señal de overfitting — y la curva de validación sigue subiendo al añadir datos, es decir, aún no ha convergido: cada ejemplo adicional sigue mejorando la generalización. Probar más algoritmos (b) sin atacar la varianza probablemente reproduciría el mismo patrón. Si la curva de validación estuviera plana desde el 40 %, la respuesta sería la contraria: más historial no aportaría y habría que cambiar de modelo o de features.
Conclusión
Overfitting y underfitting son las dos formas de fracasar de un modelo — memorizar el examen o no estudiarlo — y ya sabemos distinguirlas con la pareja de errores train/validación, entenderlas con el compromiso sesgo-varianza, localizar el punto dulce de complejidad con validation_curve, decidir si más datos ayudarían con learning_curve y aplicar el remedio correcto a cada diagnóstico. Con esta lección se cierra el módulo 6 y su checklist de evaluación honesta: división limpia, métrica pactada, baseline, validación cruzada, umbral con criterio de negocio y diagnóstico de ajuste. La pregunta "¿es bueno de verdad mi modelo?" ya tiene respuesta metodológica; la siguiente es "¿puedo hacerlo aún mejor?", y a eso dedicamos el módulo 7: regularización para domar el overfitting con precisión quirúrgica, ensembles y gradient boosting para combinar modelos, redes profundas y la optimización sistemática de hiperparámetros que automatiza las búsquedas que aquí hicimos a mano.
Curso de Machine Learning
Módulo 1: Introducción al Machine Learning
- ¿Qué es el Machine Learning?
- Historia y evolución del Machine Learning
- Tipos de Machine Learning
- Aplicaciones del Machine Learning
- El flujo de trabajo de un proyecto de Machine Learning
Módulo 2: Fundamentos de Estadística y Probabilidad
- Conceptos básicos de estadística
- Distribuciones de probabilidad
- Correlación y covarianza
- Inferencia estadística
- Teorema de Bayes
Módulo 3: Preprocesamiento de Datos
- Limpieza de datos
- Manejo de datos faltantes
- Transformación de datos
- Codificación de variables categóricas
- Normalización y estandarización
- Ingeniería de características
Módulo 4: Algoritmos de Machine Learning Supervisado
- Regresión lineal
- Regresión logística
- Árboles de decisión
- Máquinas de soporte vectorial (SVM)
- K-Vecinos más cercanos (K-NN)
- Naive Bayes
- Redes neuronales
Módulo 5: Algoritmos de Machine Learning No Supervisado
- Clustering: K-means
- Clustering jerárquico
- Análisis de componentes principales (PCA)
- Análisis de agrupamiento DBSCAN
- Visualización de datos con t-SNE y UMAP
Módulo 6: Evaluación y Validación de Modelos
- División de datos: entrenamiento, validación y prueba
- Métricas de evaluación
- Validación cruzada
- Curva ROC y AUC
- Overfitting y underfitting
Módulo 7: Técnicas Avanzadas y Optimización
- Regularización: Ridge, Lasso y Elastic Net
- Ensemble Learning
- Gradient Boosting
- Redes neuronales profundas (Deep Learning)
- Optimización de hiperparámetros
Módulo 8: Implementación y Despliegue de Modelos
- Frameworks y bibliotecas populares
- Implementación de modelos en producción
- Mantenimiento y monitoreo de modelos
- Consideraciones éticas y de privacidad
Módulo 9: Proyectos Prácticos
- Proyecto 1: Predicción de precios de viviendas
- Proyecto 2: Clasificación de imágenes
- Proyecto 3: Análisis de sentimientos en redes sociales
- Proyecto 4: Detección de fraudes
- Proyecto 5: Segmentación de clientes
