Muchos modelos de Machine Learning tienen parámetros que debemos definir antes del entrenamiento. Por ejemplo:
C en SVM.Esos valores no se aprenden automáticamente a partir del dataset. Debemos elegirlos nosotros. A esos valores se los llama hiperparámetros.
Conviene distinguir dos ideas:
Por ejemplo, en KNN el valor de n_neighbors es un hiperparámetro. El algoritmo no lo descubre solo: nosotros debemos decidirlo.
Podríamos entrenar un modelo con distintos valores y anotar resultados. Pero ese enfoque se vuelve desordenado rápidamente:
Scikit-learn ofrece una herramienta para sistematizar este proceso: GridSearchCV.
GridSearchCV prueba automáticamente varias combinaciones de hiperparámetros y evalúa cada una con validación cruzada.
La idea general es:
Cuando el flujo incluye preprocesamiento y modelo, lo más seguro es envolver todo en un Pipeline y aplicar la búsqueda sobre ese flujo completo.
Así, cada combinación de parámetros se evalúa respetando correctamente el preprocesamiento dentro de cada partición de validación cruzada.
Vamos a usar un pipeline con escalado y KNN para predecir si un cliente compra. Probaremos varias combinaciones de:
n_neighbors;weights.Luego veremos cuál fue la mejor y usaremos ese modelo para predecir un nuevo caso.
import pandas as pd
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
clientes = pd.DataFrame({
"paginas_vistas": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 5, 8],
"minutos_sitio": [1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 3, 4],
"compra": [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1]
})
X = clientes[["paginas_vistas", "minutos_sitio"]]
y = clientes["compra"]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, random_state=42, stratify=y
)
pipeline = Pipeline([
("escalador", StandardScaler()),
("knn", KNeighborsClassifier())
])
parametros = {
"knn__n_neighbors": [1, 3, 5],
"knn__weights": ["uniform", "distance"]
}
busqueda = GridSearchCV(
estimator=pipeline,
param_grid=parametros,
cv=3,
scoring="accuracy"
)
busqueda.fit(X_train, y_train)
mejor_modelo = busqueda.best_estimator_
y_pred = mejor_modelo.predict(X_test)
print("Mejores parámetros:", busqueda.best_params_)
print("Mejor score en validación:", busqueda.best_score_)
print("Exactitud en prueba:", accuracy_score(y_test, y_pred))
nuevo_cliente = pd.DataFrame({
"paginas_vistas": [7],
"minutos_sitio": [4]
})
prediccion = mejor_modelo.predict(nuevo_cliente)[0]
probabilidad = mejor_modelo.predict_proba(nuevo_cliente)[0, 1]
print("Predicción para el nuevo cliente:", prediccion)
print(f"Probabilidad de compra: {probabilidad:.3f}")
Salida resumida esperada:
Mejores parámetros: {...}
Mejor score en validación: ...
Exactitud en prueba: ...
Predicción para el nuevo cliente: ...
Probabilidad de compra: ...
El programa no prueba un solo modelo, sino varios. Cada combinación de la grilla se evalúa con validación cruzada y recibe un puntaje medio.
Al final, GridSearchCV guarda la mejor combinación y la expone en best_params_ y best_estimator_.
En la grilla aparece esta notación:
knn__n_neighbors
knn__weights
Eso significa:
knn: nombre del paso dentro del pipeline;n_neighbors o weights: hiperparámetro interno de ese modelo.El doble guion bajo __ es la forma estándar de Scikit-learn para referirse a parámetros dentro de pipelines.
GridSearchCV(...): organiza y ejecuta la búsqueda de combinaciones.param_grid: define la grilla de valores a probar.cv=3: indica cuántas particiones usar en validación cruzada.best_params_: devuelve la mejor combinación encontrada.best_estimator_: devuelve el flujo ya configurado con esos parámetros.Ventajas:
Límites:
GridSearchCV prueba combinaciones de forma sistemática.