26. Buenas prácticas y siguientes pasos

26.1 Cerrar bien un curso también es importante

Aprender algoritmos es importante, pero no alcanza. En Machine Learning, muchas veces la diferencia entre un trabajo prolijo y uno poco confiable no está en elegir “el modelo más famoso”, sino en aplicar buenas prácticas de manera consistente.

Este último tema resume hábitos que conviene incorporar desde el principio para trabajar mejor con Scikit-learn y para seguir creciendo después de este tutorial.

26.2 Qué entendemos por buenas prácticas

Una buena práctica es una decisión técnica que reduce errores, mejora la reproducibilidad y hace que el proyecto sea más fácil de entender y mantener.

No son adornos. Son parte central del trabajo con datos y modelos.

26.3 Algunas reglas simples que valen mucho

  • separar entrenamiento y prueba;
  • evitar fuga de información;
  • usar Pipeline cuando hay preprocesamiento;
  • fijar random_state para poder reproducir resultados;
  • elegir métricas adecuadas al problema;
  • comparar modelos de manera ordenada;
  • probar con datos nuevos antes de dar un resultado por confiable.

26.4 Qué es la fuga de información

La fuga de información ocurre cuando usamos, directa o indirectamente, datos del conjunto de prueba durante el entrenamiento o durante el preprocesamiento.

Eso genera una ilusión de buen rendimiento. El modelo parece funcionar muy bien, pero en realidad fue “ayudado” con información que no debería conocer.

Por eso el preprocesamiento debe ajustarse con los datos de entrenamiento y aplicarse después a validación, prueba o casos nuevos.

26.5 Por qué reproducibilidad no es un detalle

Si hoy entrenas un modelo y mañana el mismo código da otro resultado, será difícil entender qué cambió. Por eso conviene fijar semillas con random_state siempre que corresponda.

La reproducibilidad ayuda a comparar modelos, depurar problemas y explicar resultados a otras personas.

26.6 Qué conviene hacer antes de confiar en un modelo

  • revisar los datos faltantes;
  • verificar que las columnas usadas en entrenamiento y predicción coincidan;
  • medir rendimiento en datos no vistos;
  • mirar más de una métrica si el problema lo requiere;
  • interpretar el resultado dentro del contexto del problema.

26.7 Ejemplo muy claro: un flujo correcto y reproducible

En este ejemplo reunimos varias buenas prácticas en un solo programa:

  • tratamiento de faltantes;
  • escalado dentro del pipeline;
  • separación entre entrenamiento y prueba;
  • validación cruzada sobre entrenamiento;
  • evaluación final en prueba;
  • predicción para un caso nuevo.
import pandas as pd
from sklearn.impute import SimpleImputer
from sklearn.model_selection import StratifiedKFold, cross_val_score, train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, f1_score

estudiantes = pd.DataFrame({
    "horas_estudio": [1, 2, 3, 4, 5, 6, 7, 8, 2, 4, 6, 8],
    "practicas": [0, 1, 1, 2, 2, 3, 4, 5, None, 2, 3, 5],
    "asistencia": [55, 60, 65, 70, 75, 80, 85, 90, 62, 72, None, 95],
    "aprobo": [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1]
})

X = estudiantes[["horas_estudio", "practicas", "asistencia"]]
y = estudiantes["aprobo"]

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42, stratify=y
)

modelo = Pipeline([
    ("imputador", SimpleImputer(strategy="median")),
    ("escalador", StandardScaler()),
    ("clasificador", LogisticRegression(max_iter=1000, random_state=42))
])

cv = StratifiedKFold(n_splits=3, shuffle=True, random_state=42)
scores = cross_val_score(modelo, X_train, y_train, cv=cv, scoring="accuracy")

print("Exactitud en validacion cruzada:", scores)
print("Promedio en validacion cruzada:", scores.mean())

modelo.fit(X_train, y_train)

y_pred = modelo.predict(X_test)
print("Valores reales:", y_test.values)
print("Predicciones:", y_pred)
print("Exactitud en prueba:", accuracy_score(y_test, y_pred))
print("F1 en prueba:", f1_score(y_test, y_pred))

nuevo_estudiante = pd.DataFrame({
    "horas_estudio": [5],
    "practicas": [3],
    "asistencia": [78]
})

prediccion = modelo.predict(nuevo_estudiante)[0]
probabilidad = modelo.predict_proba(nuevo_estudiante)[0, 1]

print("Prediccion para el nuevo estudiante:", prediccion)
print(f"Probabilidad de aprobar: {probabilidad:.3f}")

Salida resumida esperada:

Exactitud en validacion cruzada: [...]
Promedio en validacion cruzada: ...
Valores reales: [...]
Predicciones: [...]
Exactitud en prueba: ...
F1 en prueba: ...
Prediccion para el nuevo estudiante: ...
Probabilidad de aprobar: ...

26.8 Por qué este ejemplo refleja buenas prácticas

El ejemplo no intenta ser complejo. Justamente por eso es útil: muestra una manera ordenada de trabajar.

Primero se separan los datos de prueba. Luego se construye un pipeline que maneja imputación, escalado y clasificación. Después se usa validación cruzada solo sobre entrenamiento. Recién al final se evalúa en prueba.

Esa secuencia evita varios errores comunes y deja un flujo fácil de repetir.

26.9 Qué errores conviene evitar a partir de ahora

  • Probar demasiadas cosas sobre el conjunto de prueba: terminas ajustándote al test.
  • Preprocesar antes de separar train y test: eso puede introducir fuga de información.
  • No fijar semillas cuando corresponde: complica reproducir y comparar.
  • Elegir una métrica por costumbre: la métrica debe responder al problema.
  • Suponer que más complejidad siempre mejora: muchas veces un modelo simple bien armado funciona mejor.

26.10 Cómo seguir aprendiendo después de este tutorial

Con esta base ya puedes avanzar hacia temas más amplios. Algunos buenos siguientes pasos son:

  • trabajar con datasets reales más grandes;
  • profundizar en selección de variables y ajuste de hiperparámetros;
  • estudiar técnicas de desbalance de clases;
  • explorar modelos más avanzados como gradient boosting;
  • aprender despliegue de modelos en aplicaciones web o APIs;
  • estudiar interpretabilidad y explicabilidad.

26.11 Qué herramientas de Scikit-learn ya deberías reconocer

  • train_test_split para separar datos;
  • Pipeline para encadenar pasos;
  • ColumnTransformer para tratar distintos tipos de columnas;
  • StandardScaler y OneHotEncoder para preprocesar;
  • cross_val_score y GridSearchCV para evaluar y ajustar;
  • métricas como exactitud, precisión, recall y F1 para interpretar resultados.

26.12 Qué deberías retener del curso completo

  • Machine Learning no es solo elegir un algoritmo.
  • Preparar bien los datos es tan importante como entrenar el modelo.
  • Medir correctamente evita conclusiones engañosas.
  • Los pipelines ayudan a trabajar de forma más segura y ordenada.
  • Una base sólida en Scikit-learn permite crecer hacia proyectos reales con mucho más criterio.

26.13 Cierre

Si llegaste hasta aquí, ya tienes un panorama claro de cómo pensar y construir un proyecto introductorio de Machine Learning con Scikit-learn.

El siguiente avance ya no depende tanto de memorizar funciones, sino de practicar con datasets reales, comparar enfoques y aprender a tomar decisiones cada vez más justificadas.