html
Dominando GridSearchCV para Modelos de Aprendizaje Automático Óptimos: Una Guía Integral
Tabla de Contenidos
- Introducción a GridSearchCV
- Comprendiendo el Conjunto de Datos
- Preprocesamiento de Datos
- Manejo de Datos Faltantes
- Codificación de Variables Categóricas
- Selección de Características
- Escalado de Características
- Implementando GridSearchCV
- Configuración de Validación Cruzada con StratifiedKFold
- Parámetros de GridSearchCV Explicados
- Construyendo y Ajustando Modelos de Aprendizaje Automático
- K-Nearest Neighbors (KNN)
- Regresión Logística
- Gaussian Naive Bayes
- Support Vector Machines (SVM)
- Árboles de Decisión
- Random Forest
- AdaBoost
- XGBoost
- Análisis de Rendimiento
- Optimizando GridSearchCV
- Conclusión y Próximos Pasos
1. Introducción a GridSearchCV
GridSearchCV es una técnica en aprendizaje automático utilizada para la optimización de hiperparámetros. Los hiperparámetros son parámetros cruciales que gobiernan el proceso de entrenamiento y la estructura del modelo. A diferencia de los parámetros regulares, los hiperparámetros se establecen antes de que comience la fase de entrenamiento y pueden influir significativamente en el rendimiento del modelo.
GridSearchCV funciona realizando una búsqueda exhaustiva a través de una cuadrícula de parámetros especificada, evaluando cada combinación utilizando validación cruzada e identificando la combinación que produce el mejor rendimiento basado en una métrica elegida (por ejemplo, F1-score, precisión).
¿Por qué GridSearchCV?
- Búsqueda Integral: Evalúa todas las combinaciones posibles de hiperparámetros.
- Validación Cruzada: Garantiza que el rendimiento del modelo sea robusto y no solo adaptado a un subconjunto específico de datos.
- Automatización: Simplifica el proceso de ajuste, ahorrando tiempo y recursos computacionales.
Sin embargo, es esencial notar que GridSearchCV puede ser intensivo computacionalmente, especialmente con grandes conjuntos de datos y cuadrículas de parámetros extensas. Esta guía explora estrategias para manejar estos desafíos de manera efectiva.
2. Comprendiendo el Conjunto de Datos
Para esta demostración, utilizamos un conjunto de datos enfocado en la satisfacción de pasajeros de aerolíneas. El conjunto de datos originalmente comprende más de 100,000 registros, pero se ha reducido a 5,000 registros para la viabilidad en este ejemplo. Cada registro abarca 23 características, incluyendo información demográfica, detalles del vuelo y niveles de satisfacción.
Muestra del Conjunto de Datos
Género
Tipo de Cliente
Edad
Tipo de Viaje
Clase
Distancia del Vuelo
...
Satisfacción
Fem
Cliente Leal
41
Viaje Personal
Eco Plus
746
...
Neutral o Insatisfecho
Masculino
Cliente Leal
53
Viaje de Negocios
Business
3095
...
Satisfecho
Masculino
Cliente Desleal
21
Viaje de Negocios
Eco
125
...
Satisfecho
...
...
...
...
...
...
...
...
La variable objetivo es Satisfacción, categorizada como "Satisfecho" o "Neutral o Insatisfecho."
3. Preprocesamiento de Datos
Un preprocesamiento de datos efectivo es fundamental para asegurar que los modelos de aprendizaje automático funcionen óptimamente. Los pasos incluyen el manejo de datos faltantes, la codificación de variables categóricas, la selección de características y el escalado de características.
Manejo de Datos Faltantes
Datos Numéricos: Los valores faltantes en columnas numéricas se abordan utilizando la estrategia de imputación de la media.
123456789101112
from sklearn.impute import SimpleImputerimport numpy as np # Initialize imputer for numeric dataimp_mean = SimpleImputer(missing_values=np.nan, strategy='mean') # Identify numerical columnsnumerical_cols = list(np.where((X.dtypes == np.int64) | (X.dtypes == np.float64))[0]) # Fit and transform the dataimp_mean.fit(X.iloc[:, numerical_cols])X.iloc[:, numerical_cols] = imp_mean.transform(X.iloc[:, numerical_cols])
Datos Categóricos: Para columnas basadas en cadenas, se emplea la estrategia de imputación del valor más frecuente.
123456789
# Initialize imputer for categorical dataimp_freq = SimpleImputer(missing_values=np.nan, strategy='most_frequent') # Identify string columnsstring_cols = list(np.where((X.dtypes == object))[0]) # Fit and transform the dataimp_freq.fit(X.iloc[:, string_cols])X.iloc[:, string_cols] = imp_freq.transform(X.iloc[:, string_cols])
Codificación de Variables Categóricas
Las variables categóricas se transforman a un formato numérico utilizando Label Encoding y One-Hot Encoding.
123456789101112131415161718192021222324252627282930
from sklearn.preprocessing import LabelEncoder, OneHotEncoderfrom sklearn.compose import ColumnTransformer def LabelEncoderMethod(series): le = LabelEncoder() return le.fit_transform(series) def OneHotEncoderMethod(indices, data): columnTransformer = ColumnTransformer( [('encoder', OneHotEncoder(), indices)], remainder='passthrough' ) return columnTransformer.fit_transform(data) def EncodingSelection(X, threshold=10): string_cols = list(np.where((X.dtypes == object))[0]) one_hot_encoding_indices = [] for col in string_cols: unique_vals = len(pd.unique(X[X.columns[col]])) if unique_vals == 2 or unique_vals > threshold: X[X.columns[col]] = LabelEncoderMethod(X[X.columns[col]]) else: one_hot_encoding_indices.append(col) X = OneHotEncoderMethod(one_hot_encoding_indices, X) return X # Apply encodingX = EncodingSelection(X)
Selección de Características
Para mejorar el rendimiento del modelo y reducir la complejidad computacional, se utiliza SelectKBest con la estadística Chi-Cuadrado (χ²) para seleccionar las 10 mejores características.
123456789101112
from sklearn.feature_selection import SelectKBest, chi2from sklearn.preprocessing import MinMaxScaler # Initialize SelectKBestkbest = SelectKBest(score_func=chi2, k=10) # Scale featuresscaler = MinMaxScaler()X_scaled = scaler.fit_transform(X) # Fit SelectKBestX_selected = kbest.fit_transform(X_scaled, y)
Escalado de Características
El escalado de características asegura que todas las características contribuyan por igual al rendimiento del modelo.
123456789
from sklearn.preprocessing import StandardScaler # Initialize StandardScalersc = StandardScaler(with_mean=False) # Fit and transform the training datasc.fit(X_train)X_train = sc.transform(X_train)X_test = sc.transform(X_test)
4. Implementando GridSearchCV
Con los datos preprocesados, el siguiente paso involucra configurar GridSearchCV para ajustar los hiperparámetros de varios modelos de aprendizaje automático.
Configuración de Validación Cruzada con StratifiedKFold
StratifiedKFold asegura que cada pliegue de la validación cruzada mantenga la misma proporción de etiquetas de clase, lo cual es crucial para conjuntos de datos desequilibrados.
1234
from sklearn.model_selection import StratifiedKFold # Initialize StratifiedKFoldcv = StratifiedKFold(n_splits=2)
Parámetros de GridSearchCV Explicados
- Estimator: El modelo de aprendizaje automático a ajustar.
- Param_grid: Un diccionario que define los hiperparámetros y sus respectivos valores a explorar.
- Verbose: Controla la verbosidad; establecido en 1 para mostrar el progreso.
- Scoring: La métrica de rendimiento a optimizar, por ejemplo, 'f1'.
- n_jobs: Número de núcleos de CPU a utilizar; establecerlo en -1 utiliza todos los núcleos disponibles.
123456789101112131415161718192021
from sklearn.model_selection import GridSearchCV # Example: Setting up GridSearchCV for KNNfrom sklearn.neighbors import KNeighborsClassifier model = KNeighborsClassifier()params = { 'n_neighbors': [4, 5, 6, 7], 'leaf_size': [1, 3, 5], 'algorithm': ['auto', 'kd_tree'], 'weights': ['uniform', 'distance']} grid_search_cv = GridSearchCV( estimator=model, param_grid=params, verbose=1, cv=cv, scoring='f1', n_jobs=-1)
5. Construyendo y Ajustando Modelos de Aprendizaje Automático
5.1 K-Nearest Neighbors (KNN)
KNN es un algoritmo simple pero efectivo para tareas de clasificación. GridSearchCV ayuda a seleccionar el número óptimo de vecinos, tamaño de hoja, algoritmo y esquema de ponderación.
123456
# Fit GridSearchCVgrid_search_cv.fit(X_train, y_train) # Best parametersprint("Best Estimator", grid_search_cv.best_estimator_)print("Best score", grid_search_cv.best_score_)
Salida:
12
Best Estimator KNeighborsClassifier(leaf_size=1)Best score 0.8774673417446253
5.2 Regresión Logística
La Regresión Logística modela la probabilidad de un resultado binario. GridSearchCV ajusta el tipo de solucionador, penalización y fuerza de regularización.
123456789101112131415161718192021
from sklearn.linear_model import LogisticRegression model = LogisticRegression()params = { 'solver': ['newton-cg', 'lbfgs', 'liblinear'], 'penalty': ['l1', 'l2'], 'C': [100, 10, 1.0, 0.1, 0.01]} grid_search_cv = GridSearchCV( estimator=model, param_grid=params, verbose=1, cv=cv, scoring='f1', n_jobs=-1) grid_search_cv.fit(X_train, y_train)print("Best Estimator", grid_search_cv.best_estimator_)print("Best score", grid_search_cv.best_score_)
Salida:
12
Best Estimator LogisticRegression(C=0.01, solver='newton-cg')Best score 0.8295203666687819
5.3 Gaussian Naive Bayes
Gaussian Naive Bayes asume que las características siguen una distribución normal. Tiene menos hiperparámetros, lo que lo hace menos intensivo para GridSearchCV.
123456789
from sklearn.naive_bayes import GaussianNBfrom sklearn.metrics import accuracy_score, classification_report model_GNB = GaussianNB()model_GNB.fit(X_train, y_train)y_pred = model_GNB.predict(X_test) print(accuracy_score(y_pred, y_test))print(classification_report(y_pred, y_test))
Salida:
123456789
0.84 precision recall f1-score support 0 0.86 0.86 0.86 564 1 0.82 0.81 0.82 436 accuracy 0.84 1000 macro avg 0.84 0.84 0.84 1000weighted avg 0.84 0.84 0.84 1000
5.4 Support Vector Machines (SVM)
Las SVM son clasificadores versátiles que funcionan bien para datos lineales y no lineales. GridSearchCV ajusta el tipo de kernel, el parámetro de regularización C
, el grado, el coeficiente coef0
y el coeficiente del kernel gamma
.
1234567891011121314151617181920212223
from sklearn.svm import SVC model = SVC()params = { 'kernel': ['linear', 'poly', 'rbf', 'sigmoid'], 'C': [1, 5, 10], 'degree': [3, 8], 'coef0': [0.01, 10, 0.5], 'gamma': ['auto', 'scale']} grid_search_cv = GridSearchCV( estimator=model, param_grid=params, verbose=1, cv=cv, scoring='f1', n_jobs=-1) grid_search_cv.fit(X_train, y_train)print("Best Estimator", grid_search_cv.best_estimator_)print("Best score", grid_search_cv.best_score_)
Salida:
12
Best Estimator SVC(C=5, coef0=0.01)Best score 0.9168629045108148
5.5 Árboles de Decisión
Los Árboles de Decisión particionan los datos basados en los valores de las características para hacer predicciones. GridSearchCV optimiza parámetros como el número máximo de nodos hoja y el número mínimo de muestras requeridas para dividir un nodo interno.
1234567891011121314151617181920
from sklearn.tree import DecisionTreeClassifier model = DecisionTreeClassifier()params = { 'max_leaf_nodes': list(range(2, 100)), 'min_samples_split': [2, 3, 4]} grid_search_cv = GridSearchCV( estimator=model, param_grid=params, verbose=1, cv=cv, scoring='f1', n_jobs=-1) grid_search_cv.fit(X_train, y_train)print("Best Estimator", grid_search_cv.best_estimator_)print("Best score", grid_search_cv.best_score_)
Salida:
12
Best Estimator DecisionTreeClassifier(max_leaf_nodes=29, min_samples_split=4)Best score 0.9098148654372425
5.6 Random Forest
Random Forests agregan múltiples árboles de decisión para mejorar el rendimiento y controlar el sobreajuste. GridSearchCV ajusta parámetros como el número de estimadores, la profundidad máxima, el número de características y las divisiones de muestra.
123456789101112131415161718192021222324
from sklearn.ensemble import RandomForestClassifier model = RandomForestClassifier()params = { 'bootstrap': [True], 'max_depth': [80, 90, 100, 110], 'max_features': [2, 3], 'min_samples_leaf': [3, 4, 5], 'min_samples_split': [8, 10, 12], 'n_estimators': [100, 200, 300, 1000]} grid_search_cv = GridSearchCV( estimator=model, param_grid=params, verbose=1, cv=cv, scoring='f1', n_jobs=-1) grid_search_cv.fit(X_train, y_train)print("Best Estimator", grid_search_cv.best_estimator_)print("Best score", grid_search_cv.best_score_)
Salida:
12
Best Estimator RandomForestClassifier(max_leaf_nodes=82, min_samples_split=4)Best score 0.9225835186933584
5.7 AdaBoost
AdaBoost combina múltiples clasificadores débiles para formar un clasificador fuerte. GridSearchCV ajusta el número de estimadores y la tasa de aprendizaje.
1234567891011121314151617181920
from sklearn.ensemble import AdaBoostClassifier model = AdaBoostClassifier()params = { 'n_estimators': np.arange(10, 300, 10), 'learning_rate': [0.01, 0.05, 0.1, 1]} grid_search_cv = GridSearchCV( estimator=model, param_grid=params, verbose=1, cv=cv, scoring='f1', n_jobs=-1) grid_search_cv.fit(X_train, y_train)print("Best Estimator", grid_search_cv.best_estimator_)print("Best score", grid_search_cv.best_score_)
Salida:
12
Best Estimator AdaBoostClassifier(learning_rate=1, n_estimators=30)Best score 0.8938313525749858
5.8 XGBoost
XGBoost es una implementación altamente eficiente y escalable del gradient boosting. Debido a su amplio espacio de hiperparámetros, GridSearchCV puede ser muy laborioso.
1234567891011121314151617181920212223242526
import xgboost as xgb model = xgb.XGBClassifier()params = { 'min_child_weight': [1, 5, 10], 'gamma': [0.5, 1, 1.5, 2, 5], 'subsample': [0.6, 0.8, 1.0], 'colsample_bytree': [0.6, 0.8, 1.0], 'max_depth': [3, 4, 5], 'n_estimators': [100, 500, 1000], 'learning_rate': [0.01, 0.3, 0.5, 0.1], 'reg_lambda': [1, 2]} grid_search_cv = GridSearchCV( estimator=model, param_grid=params, verbose=1, cv=cv, scoring='f1', n_jobs=-1) grid_search_cv.fit(X_train, y_train)print("Best Estimator", grid_search_cv.best_estimator_)print("Best score", grid_search_cv.best_score_)
Salida:
123456789
Best Estimator XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1, colsample_bynode=1, colsample_bytree=0.8, gamma=0.5, gpu_id=-1, importance_type='gain', interaction_constraints='', learning_rate=0.01, max_delta_step=0, max_depth=5, min_child_weight=1, missing=nan, monotone_constraints='()', n_estimators=500, n_jobs=12, num_parallel_tree=1, random_state=0, reg_alpha=0, reg_lambda=1, scale_pos_weight=1, subsample=1.0, tree_method='exact', validate_parameters=1, verbosity=None)Best score 0.9267223852716081
Nota: La ejecución de GridSearchCV para XGBoost consume notablemente mucho tiempo debido a la gran cantidad de combinaciones de hiperparámetros.
6. Análisis de Rendimiento
Después del ajuste, cada modelo presenta diferentes niveles de rendimiento basados en los mejores F1-scores alcanzados:
- KNN: 0.877
- Regresión Logística: 0.830
- Gaussian Naive Bayes: 0.840
- SVM: 0.917
- Árbol de Decisión: 0.910
- Random Forest: 0.923
- AdaBoost: 0.894
- XGBoost: 0.927
Interpretación
- XGBoost y Random Forest exhiben los F1-scores más altos, indicando un rendimiento superior en el conjunto de datos.
- SVM también demuestra un rendimiento robusto.
- KNN y AdaBoost proporcionan resultados competitivos con F1-scores ligeramente inferiores.
- Regresión Logística y Gaussian Naive Bayes, aunque más simples, aún ofrecen métricas de rendimiento respetables.
7. Optimizando GridSearchCV
Dada la intensidad computacional de GridSearchCV, especialmente con grandes conjuntos de datos o cuadrículas de parámetros extensas, es crucial explorar estrategias de optimización:
7.1 RandomizedSearchCV
A diferencia de GridSearchCV, RandomizedSearchCV muestrea un número fijo de configuraciones de parámetros de distribuciones especificadas. Este enfoque puede reducir significativamente el tiempo de cómputo mientras explora un conjunto diverso de hiperparámetros.
1234567891011121314151617
from sklearn.model_selection import RandomizedSearchCV # Example setup for RandomizedSearchCVrandom_search_cv = RandomizedSearchCV( estimator=model, param_distributions=params, n_iter=100, # Number of parameter settings sampled verbose=1, cv=cv, scoring='f1', n_jobs=-1, random_state=42) random_search_cv.fit(X_train, y_train)print("Best Estimator", random_search_cv.best_estimator_)print("Best score", random_search_cv.best_score_)
7.2 Reduciendo el Tamaño de la Cuadrícula de Parámetros
Enfócate en hiperparámetros que impactan significativamente el rendimiento del modelo. Realiza análisis exploratorios o aprovecha el conocimiento del dominio para priorizar ciertos parámetros sobre otros.
7.3 Utilizando Procesamiento Paralelo
Establecer n_jobs=-1
en GridSearchCV permite el uso de todos los núcleos de CPU disponibles, acelerando el proceso de cómputo.
7.4 Early Stopping
Implementa mecanismos de early stopping para detener la búsqueda una vez que se logra un nivel de rendimiento satisfactorio, evitando cómputos innecesarios.
8. Conclusión y Próximos Pasos
GridSearchCV es una herramienta indispensable para la optimización de hiperparámetros, ofreciendo un enfoque sistemático para mejorar el rendimiento de los modelos de aprendizaje automático. A través de un meticuloso preprocesamiento de datos, la formulación estratégica de la cuadrícula de parámetros y el aprovechamiento de optimizaciones computacionales, los científicos de datos pueden aprovechar al máximo el potencial de GridSearchCV.
Próximos Pasos:
- Explorar RandomizedSearchCV para una optimización más eficiente de hiperparámetros.
- Implementar Mejores Prácticas de Validación Cruzada para asegurar la robustez del modelo.
- Integrar Técnicas de Ingeniería de Características para mejorar aún más el rendimiento del modelo.
- Desplegar Modelos Optimizados en escenarios del mundo real, monitoreando su rendimiento a lo largo del tiempo.
Al dominar GridSearchCV y sus optimizaciones, estás bien equipado para construir modelos de aprendizaje automático de alto rendimiento y confiables que resistan las pruebas de diversos entornos de datos.