Carlos [aka «el tete»] me está enseñando Python y una de las cosas que me ha enseñado es seleccionar de forma iterativa el mejor modelo con GridSearchCV y, por si fuera poco, vamos a emplear el método de clasificación «gradient boosting» para que no caiga in desuso, sobre todo porque es una técnica que, bajo mi punto de vista, ofrece modelos muy estables. El ejemplo para ilustrar el proceso ya es conocido, ya que vamos a estimar la letra O (mi talento no da para mucho más). Recordamos los primeros pasos:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
largo = 10000
df = pd.DataFrame(np.random.uniform(0, 100, size=(largo, 2)), columns=list('XY'))
dependiente1 = np.where(((df.X - 50)**2 / 20**2 + (df.Y - 50)**2 / 40**2 > 1), 1, 0)
dependiente2 = np.where(((df.X - 50)**2 / 30**2 + (df.Y - 50)**2 / 50**2 > 1), 1, 0)
dependiente = dependiente1 - dependiente2
plt.scatter(df.X, df.Y, c=dependiente, marker=".")
plt.show()
Tenemos una letra O fruto de jugar con la ecuación de la elipse, y ahora creamos el conjunto de datos con el que entrenamos el modelo y el conjunto de datos de test para comprobar posteriormente cómo funciona:
# Dividimos en validacion y test
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(df, dependiente,
stratify=dependiente,
test_size=0.5,
random_state=123)
Nada nuevo bajo el sol, pero me gusta poner los ejemplos al completo para que sean reproducibles. Ahora vienen las enseñanzas «del tete»:
# GradientBoostingClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import GridSearchCV
np.random.seed(40)
# Parámetros para iterar
fun_perdida = ('deviance', 'exponential')
profundidad = range(5, 15)
minimo_split = range(5, 10, 1)
learning_rate = [0.01, 0.1, 0.2, 0.3]
modeloGBM = GradientBoostingClassifier(random_state=1, n_estimators=100)
param_grid = dict(max_depth=profundidad,
min_samples_split=minimo_split,
loss=fun_perdida,
learning_rate=learning_rate)
grid = GridSearchCV(modeloGBM, param_grid, cv=10, scoring='roc_auc')
grid.fit(X_train, y_train)
# El mejor modelo tras la búsqueda
mejor_modelo = grid.best_estimator_
Los protagonistas de la entrada son GradientBoostingClassifier, que nos permite ajustar un modelo de clasificación de gradient boosting, y GridSearchCV, que nos permite jugar con los parámetros de nuestros modelos; en este caso, vamos a jugar con la función de pérdida (loss), la profundidad del árbol, los cortes minimo_split del árbol de clasificación y el learning_rate. Una vez fijados los rangos, hacemos la «tabla» de parámetros de entrenamiento de modelos con la función dict(), que recogerá todos los rangos de parámetros que vamos a iterar. Definido esto y definido el modeloGBM, lo entrenamos y, mediante validación cruzada (cv), el proceso se quedará con el mejor modelo de todos los que proponemos en la tabla de parámetros. Ahora solo tenemos que ver cómo funciona este mejor_modelo:
proba = mejor_modelo.predict_proba(X_test)
proba = pd.DataFrame(proba)[1]
plt.scatter(X_test.X, X_test.Y, c=proba, cmap=plt.cm.Blues)
plt.colorbar()
plt.show()

Resultado muy interesante porque es conservador; por eso me gusta: delimita bien los extremos laterales y tiene mucho cuidado con los extremos superiores, y es que un algoritmo que minimiza el error tiene mayor cuidado a la hora de clasificar y procura que estas clasificaciones sean más homogéneas. Saludos.