Saltar al contenido

# fundamentos-de-scikit-learn

Fundamentos de Scikit-learn

Volver a la portada del curso
Proyecto

Proyecto Final en Scikit-learn

Sección 6 · Proyecto Final

Proyecto final: modelo de entregas tardías de PyEnvíos

Durante el curso transformaste datos, entrenaste y comparaste modelos, mediste con las métricas correctas, validaste con pliegues y buscaste hiperparámetros. Ahora vas a juntar todo en un modelo completo, guardado en disco y listo para recibir pedidos nuevos. Se usan Python 3.12 o superior, scikit-learn 1.8, pandas y joblib. El notebook proyecto-entregas-tardias contiene una solución de referencia: consúltalo al terminar, no antes.

Contexto

PyEnvíos, el servicio de reparto de PyShop, promete entregar en 60 minutos. Cuando no cumple, el cliente se entera tarde y reclama. El equipo quiere un modelo que, al recibir un pedido, estime la probabilidad de que llegue tarde para avisar al cliente con tiempo. Una tardía sin aviso cuesta más que una falsa alarma, pero demasiadas falsas alarmas hacen que los clientes dejen de creer en los avisos.

Datos

Copia la función generar_entregas y las listas NUMERICAS y CATEGORICAS de la primera celda de cualquier notebook del curso, y genera los datos con otra semilla:

df = generar_entregas(n=2000, semilla=2026)
print(df.shape, df["tarde"].sum())
print(df.isna().sum()[lambda s: s > 0].to_dict())
# (2000, 11) 530
# {'peso_kg': 106, 'zona': 63}

Si no obtienes 530 entregas tardías (26.5 %), revisa la semilla. Las columnas son distancia_km, peso_kg, articulos, zona, transporte, dia, hora, lluvia, valor_mxn, minutos y tarde. El objetivo es tarde. minutos no se conoce al recibir el pedido: no puede ser una columna de entrada. Todas las demás cifras debes obtenerlas tú.

Requisitos mínimos

  1. Partición. train_test_split con test_size=0.25, stratify=y y random_state=42. El test no se toca hasta el requisito 6.
  2. Preprocesamiento. Un ColumnTransformer que impute y escale las numéricas e impute y codifique con one-hot las categóricas (handle_unknown="ignore"), todo dentro de un Pipeline con el modelo.
  3. Línea base y comparación. Un DummyClassifier y al menos tres modelos distintos (por ejemplo, regresión logística, bosque aleatorio y HistGradientBoostingClassifier), comparados con cross_validate y StratifiedKFold(5, shuffle=True, random_state=42). Reporta media y desviación de AUC, recall y exactitud en una tabla.
  4. Búsqueda de hiperparámetros. GridSearchCV o RandomizedSearchCV sobre el mejor candidato, con scoring="roc_auc". Justifica los rangos y reporta el número de ajustes, best_params_ y best_score_.
  5. Umbral de decisión. Con predicciones de validación cruzada sobre train (cross_val_predict(..., method="predict_proba")), elige el umbral más alto que detecte al menos el 80 % de las tardías. Muestra precision y recall en tres umbrales y explica la elección.
  6. Evaluación final, una vez. En test: AUC, matriz de confusión, precision y recall con tu umbral, y la comparación con el Dummy.
  7. Guardar y usar. Guarda el pipeline ajustado y el umbral; cárgalos en un script aparte y predice tres pedidos nuevos, uno con peso_kg faltante y otro con una zona que no existe en los datos.

Pistas de implementación

import joblib

paquete = {"modelo": mejor, "umbral": umbral}
joblib.dump(paquete, "modelo_entregas.joblib")

cargado = joblib.load("modelo_entregas.joblib")
proba = cargado["modelo"].predict_proba(nuevos)[:, 1]
avisar = proba >= cargado["umbral"]

Carga solo archivos .joblib que generaste tú: deserializar un archivo ajeno puede ejecutar código. Registra la versión de scikit-learn con la que guardaste, porque un modelo guardado no está garantizado entre versiones.

Extras opcionales

  • Regresión de minutos. Predice minutos con el mismo preprocesamiento y compara MAE y $R^2$ contra un DummyRegressor.
  • Importancia por permutación. Usa sklearn.inspection.permutation_importance sobre test y comenta si coincide con las tasas por transporte y lluvia.
  • Estabilidad. Repite la evaluación con cinco semillas de partición y reporta el rango del AUC.

Entregables

  1. proyecto.ipynb, ejecutado de principio a fin sin errores.
  2. modelo_entregas.joblib y predecir.py, que lo carga y predice los tres pedidos.
  3. INFORME.md (una página): la tabla de comparación, los hiperparámetros elegidos, el umbral y su justificación, las cifras de test y dos limitaciones del modelo. Los datos son sintéticos: describe lo que ves sin inventarle causas.

Rúbrica (100 puntos, más 10 de extras)

  • Datos y partición (10 puntos): semilla correcta, sin minutos en la entrada, estratificada.
  • Pipeline de preprocesamiento (15 puntos): todo dentro del pipeline, sin fuga, tolera faltantes y categorías nuevas.
  • Comparación de modelos (20 puntos): Dummy y tres modelos, validación cruzada, tabla clara.
  • Búsqueda de hiperparámetros (20 puntos): rangos razonables, nombres paso__parametro, costo reportado.
  • Umbral y evaluación (20 puntos): umbral elegido sin mirar el test, test usado una sola vez, métricas correctas.
  • Guardado y uso (10 puntos): el script carga el modelo y predice los tres pedidos.
  • Informe (5 puntos): conclusiones con cifras y limitaciones honestas.

Recursos