# machine-learning-en-python
Machine Learning en Python
Volver a la portada del cursoPráctica: regresión y KNN con los clientes de PyShop
Sección 3 · Modelos Supervisados Básicos
Práctica: regresión y KNN con los clientes de PyShop
Esta práctica junta en código todo lo de los modelos supervisados: la regresión lineal para predecir el gasto anual, KNN para predecir quién contrata envío premium y, en una segunda parte, el ajuste de hiperparámetros y la regularización. Descarga los dos notebooks adjuntos, regresion-y-knn y ajuste-y-regularizacion, y ejecútalos celda por celda. Necesitas numpy, pandas, matplotlib y scikit-learn (probados con scikit-learn 1.8 y pandas 3.0).
Los dos son autocontenidos: la primera celda de código genera los 1000 clientes sintéticos de PyShop con una semilla fija y aplica la limpieza de la sección 2 (duplicados fuera, ciudades normalizadas, edades imposibles a nulo e imputación con la mediana). No hay nada que descargar y las cifras salen iguales en cualquier equipo.
Notebook 1: regresión y KNN
Regresión. Con un 80/20 y random_state=42, una regresión con solo compras_12m da un coeficiente de 113.1 pesos por compra, pero R² 0.099 y MAE de 2166 pesos: las compras solas explican muy poco. Con seis variables, R² sube a 0.853 (MAE 693, RMSE 1258). El notebook se detiene en un coeficiente engañoso: visitas_mes sale en −160.8, y no porque visitar haga gastar menos. Al final se añade una variable:
Xtr_i = Xtr.assign(compras_x_ticket=Xtr["compras_12m"] * Xtr["ticket_promedio"])
Xte_i = Xte.assign(compras_x_ticket=Xte["compras_12m"] * Xte["ticket_promedio"])
lr_i = LinearRegression().fit(Xtr_i, ytr)
print(round(r2_score(yte, lr_i.predict(Xte_i)), 3)) # 0.988
R² 0.988 y MAE de 239 pesos. Un modelo lineal suma pero no multiplica; si se le da el producto, el problema se vuelve casi lineal.
KNN. Con 7 variables y partición estratificada, la línea base (todo «no premium») acierta 0.64. KNN con k=5 da 0.81 sin escalar y 0.83 con StandardScaler dentro de un pipeline. Después se recorre k en 1, 3, 5, 11, 21 y 51 con una gráfica de exactitud en entrenamiento y prueba: k=1 memoriza (1.000 contra 0.795) y la prueba llega a 0.855 con k=21. Cierra con la matriz de confusión [[115, 13], [21, 51]]: el modelo detecta 51 de los 72 premium reales.
Notebook 2: ajuste y regularización
Validación cruzada. cross_val_score con cv=5 estima la exactitud sin tocar el conjunto de prueba. Luego GridSearchCV busca n_neighbors y weights sobre un Pipeline, para que el escalador se ajuste dentro de cada bloque y no haya fuga de datos:
pipe = Pipeline([("esc", StandardScaler()), ("knn", KNeighborsClassifier())])
grid = {"knn__n_neighbors": [1, 3, 5, 7, 11, 15, 21, 31, 51],
"knn__weights": ["uniform", "distance"]}
gs = GridSearchCV(pipe, grid, cv=5, scoring="accuracy").fit(Xtr_c, ytr_c)
print(gs.best_params_) # {'knn__n_neighbors': 21, 'knn__weights': 'distance'}
La búsqueda elige k=21 con pesos por distancia: 0.822 en validación cruzada y 0.855 en prueba, que se usa una sola vez al final.
Sobreajuste y regularización. Para provocar sobreajuste se entrena con solo 100 clientes y PolynomialFeatures(3), que convierte 6 variables en 83. LinearRegression da R² 0.999 en entrenamiento y 0.675 en prueba. Ridge con α=1 sube la prueba a 0.889, y el barrido de α (0.01 a 100) muestra que poco castigo deja sobreajuste y mucho castigo deja un modelo rígido (0.798 con α=100). Lasso con α=20 deja 64 de 83 coeficientes en cero, llega a 0.981 en prueba y entre las variables que conserva está compras_12m ticket_promedio: la misma interacción del primer notebook, encontrada sin ayuda. GridSearchCV elige ese α=20 con R² medio de 0.984.
Ejercicios
Cada notebook termina con ejercicios y su solución verificada con assert. Escribe tu versión antes de leer la solución y comprueba que pasa las mismas pruebas.
- Regresión y KNN: R² con solo
ticket_promedio; precisión y recall a partir de la matriz de confusión; KNN conk=21sin escalar y escalado; predecir el gasto y la probabilidad de premium de un cliente nuevo. - Ajuste y regularización: comprobar que
best_score_es la media de la validación cruzada; elegir α de Ridge conGridSearchCVy compararlo con el barrido sobre el test; contar cuántos coeficientes anula Lasso con α=100.
Trampas comunes
- Interpretar un coeficiente aislado. Con variables relacionadas entre sí, el signo puede contradecir la intuición.
- Olvidar la línea base. Un 0.83 solo vale algo comparado con el 0.64 de no hacer nada.
- Escalar fuera del pipeline. Ajustar el escalador con todos los datos filtra información del test.
- Regularizar sin escalar. La penalización trata igual a todas las columnas; si están en escalas distintas, castiga de forma desigual.
- Elegir α o k mirando el test. El barrido de Ridge sobre el test favorece α=0.1, pero la validación cruzada elige α=1; el ejercicio 2 muestra la diferencia.
Qué hacer con los notebooks
Ejecuta primero regresion-y-knn completo y luego ajuste-y-regularizacion. Después cambia una cosa a la vez: quita el escalador, usa otra semilla en train_test_split o entrena la regresión polinómica con 500 filas en lugar de 100, y anota cómo se mueven las cifras.