David Martínez Jiménez
Kenny Emmanuel Lajara Aquino
Gerardo Mayel Fernández Alamilla
buena idea me gustó
¿Cómo implementar Gradient Boosting con scikit-learn en un dataset de enfermedades cardiacas?
La implementación de modelos de Machine Learning puede parecer intimidante al principio, pero con las herramientas correctas, se vuelve bastante manejable. Scikit-learn es una biblioteca en Python que facilita este proceso con sus modelos pre-construidos y métodos de ensamblado como el Gradient Boosting. En esta guía, aprenderás a aplicar Gradient Boosting para clasificar un dataset de enfermedades cardiacas, obteniendo resultados precisos y significativos.
¿Qué cambios de código son necesarios?
Para comenzar, es fundamental trabajar desde una base de código preexistente. Aquí, se parte de un código que ya procesa un dataset de enfermedades cardíacas. Sin embargo, dado que emplearemos Gradient Boosting, ciertas librerías utilizadas inicialmente ya no serán necesarias:
from sklearn.ensemble import GradientBoostingClassifier
Este es el único cambio de importación necesario. El clasificador Gradient Boosting, basado en árboles de decisión, prescindirá del clasificador K-Nearest Neighbors utilizado previamente.
¿Cómo definimos y entrenamos nuestro clasificador?
Definir el clasificador es simple. Usamos el método GradientBoostingClassifier para crear un modelo que ajustará los datos de entrenamiento. Aquí, establecemos un parámetro clave: el número de árboles en el ensamblado.
# Definimos el clasificador clasificador = GradientBoostingClassifier(n_estimators=50) # Entrenamos con los datos de entrenamiento clasificador.fit(X_train, y_train)
Elegimos utilizar 50 estimadores, y aunque este número es inicialmente arbitrario, puedes ajustarlo según el rendimiento, usando técnicas como validación cruzada (cross-validation) para optimizar los hiperparámetros.
¿Cómo generamos predicciones y evaluamos el modelo?
Una vez tenemos el clasificador entrenado, el siguiente paso es generar predicciones sobre los datos de prueba y evaluar la precisión de nuestro modelo.
# Generamos predicciones predicciones = clasificador.predict(X_test) # Calculamos la precisión from sklearn.metrics import accuracy_score precision = accuracy_score(y_test, predicciones)
Este proceso nos permite medir qué tan bien nuestro modelo está clasificando las instancias del dataset de prueba. En este ejercicio particular, el modelo alcanza una impresionante precisión del 93%, lo que representa una mejora respecto al método previo, el K-Nearest Neighbors.
¿Por qué evaluar múltiples métodos de ensamble?
Si bien en este ejemplo observamos un impresionante aumento en la precisión del 93% con Gradient Boosting, es crucial recordar que los resultados pueden variar según el dataset. Cada modelo de Machine Learning tiene sus fortalezas y debilidades, y es por eso que te recomendamos probar diferentes métodos de ensamble y clasificadores para determinar cuál se adapta mejor a tus necesidades.
Esta práctica te permitirá establecer un enfoque más robusto y adaptado a tu problema específico, asegurando así que el modelo sea no solo preciso, sino también eficiente y relevante.
Cambios en los archivos y ejecución
Finalmente, para mantener la coherencia y la organización del proyecto, renombramos el archivo que contiene este proceso a boosting.py, garantizando que siempre estaremos trabajando con los contenidos correctos en los repositorios de código.
Con este entendimiento de cómo integrar Gradient Boosting en tus proyectos, estarás mejor preparado para enfrentar desafíos más complejos en tus exploraciones de Machine Learning. ¡Sigue aprendiendo y mejorando tus modelos!
David Martínez Jiménez
Kenny Emmanuel Lajara Aquino
Gerardo Mayel Fernández Alamilla
buena idea me gustó
Configurando el boosting de esta manera:
boosting = GradientBoostingClassifier(loss='exponential',learning_rate=0.15, n_estimators=100, max_depth=5).fit(x_train, y_train)
Obtuve un score de: 0.9888579387186629
Henry Mendiburu Díaz
Para determinar el mejor n_estimator
estimators = range(10, 300, 10) total_accuracy = [] best_result = {'result' : 0, 'n_estimator': 1} for i in estimators: boost = GradientBoostingClassifier(n_estimators=i).fit(X_train, y_train) boost_pred = boost.predict(X_test) new_accuracy = accuracy_score(boost_pred, y_test) total_accuracy.append(new_accuracy) if new_accuracy > best_result['result']: best_result['result'] = new_accuracy best_result['n_estimator'] = i print(best_result)
Anabel Chavez Berumen
Mi intento de cross validation, al final deje n_estimators en 3 con 81%.
Paola Alapizco
Daniel Correa
un 0.93 de accuracy no seria overfitting?
Luis Enrique Sanchez Piñerua
No necesariamente, si revisas kaggle.com, puedes encontrar que en varias competencia los usuarios publican sus modelos y muchos pueden llegar hasta un 0.99 de accuracy (algunos hasta 1)
Las pruebas que realiza Kaggle en sus competencias son usando un 50% de los datos de test que suministran y otro 50% que no suministran. Por lo tanto obtienen un modelo muy acertado que no necesariamente se aprendió el dataset de memoria (overfitting)
David Martínez Jiménez
No es overfitting, por que ese 0.93 esta basado sobre los datos de prueba y no de entrenamiento, eso significa que el modelo se comporto muy bien con datos que no conocía :)
Alejandro Zambrano Zabaleta
Entonces, ¿Cuándo podría ser mejor aplicar las técnicas de boosting y bagging?
Sebastian Manassero
Se suelen usar con problemas de clasificacion, el Bagging cuando tenes una alta varianza y el Boosting cuando tenes un alto bias.
Thomas Gonzalez Rodrigues
investoge que es el cross validadtion para encontrar el n_estimators correcto, básicamente es dividir los datos en bloques y utilizar cada bloque como testing y el resto como training en cada iteration, con lo que se obtiene un valor de como se comporta el modelo con cualquier combinacion de los datos.
con este indicador se pueden compara modelos entre si o en este caso valores para un parametro, si quieren profundizar les recomiendo este video.
Luciano Gauchez
KNeighborsClassifier 0.711038961038961
BaggingClassifier 0.7727272727272727
RanfomForestClassifier: 1.0
GradientBoostingClassifier: 0.9448051948051948
Santiago Ahumada Lozano
¿Cómo puedo implementar cross validation para encontrar el mejor número de estimadores?
Antonio Demarco Bonino
Jeinfferson Bernal G
Muy bueno. Gracias
Marcelo Sánchez
Les adjunto mi version del codigo:
import pandas as pd from sklearn.ensemble import GradientBoostingClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score if __name__ == "__main__": path = './Boosting/data/heart.csv' dataset = pd.read_csv(path) print(dataset.head(5)) print('') print(dataset['target'].describe()) x = dataset.drop(['target'], axis=1, inplace=False) y = dataset['target'] x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.35, random_state=42) boost = GradientBoostingClassifier(n_estimators=50).fit(x_train, y_train) boost_pred = boost.predict(x_test) print('') #print('Accuracy GBC:', accuracy_score(y_test, boost_pred)) # este esta bien. print('Accuracy GBC:', accuracy_score(boost_pred, y_test)) # este me parece que esta mal.
Donde el output es el siguiente:
Accuracy GBC: 0.935933147632312
Iván Villarroel
OMG
Mauricio Escobar
qué tal👋 he encontrado cosas muy interesantes del dataset que hemos estado usando: "Heart Disease" – Cleveland database" No es el original.
El que hemos estado usando tiene 1025 filas, cuando en el original es de solo 303. El nuestro de 1025 (o el que al menos yo he estado usando) es una versión modificada/aumentada que circula mucho en Kaggle y otros sitios.
Por lo que alguien tomó el dataset original de 303 filas y lo combinó con datos sintéticos (probablemente generados artificialmente para parecerse al original). Importante hacer un df.drop_duplicates() y un df.duplicated().sum() antes para confirmar la cantidad de duplicados. Si no los borramos podría existir el mismo paciente varias veces, por lo que es probable que aparezca tanto en entrenamiento como en test, generando data leakage.
Esto quiere decir que hay 700 ocurrencias que deben sacarse. Y es la razón por la que hemos obtenido una precisión tan alta.
En adición, varias columnas 'ca', 'thal', etc. No son numéricas continuas, sino categóricas.
siendo:
dada su naturaleza (columna categórica) lo mejor sería imputarlos por la moda. Encontré que son MCAR, por lo que no agregamos tanto ruido al imputar.
Claudio Chavarría Altamirano
Tomas Dale
Un aporte abajo me parecio muy interesante
boosting = GradientBoostingClassifier(loss='exponential',learning_rate=0.15, n_estimators=100, max_depth=5).fit(x_train, y_train)
Le agrego el parametro "loss='exponential' me hubiera gustado haber ahondado mas, quiza es la funcion de perdida????
Juan José Mamani Tarqui
Jhon Freddy Tavera Blandon
LinearSVC Accuracy: 0.8133704735376045 ==================================================================== SVC Accuracy: 0.6880222841225627 ==================================================================== SGDClassifier Accuracy: 0.6796657381615598 ==================================================================== DecisionTreeClassifier Accuracy: 0.9554317548746518 ==================================================================== GradientBoostingClassifier Accuracy: 0.9331476323119777
Juan R. Vergara M.
Otra gran clase 🥇🚀🔥
Andres Sanchez
24. Implementación de Boosting
import pandas as pd from sklearn.ensemble import GradientBoostingClassifier from sklearn.neighbors import KNeighborsClassifier from sklearn.ensemble import BaggingClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score if __name__ == '__main__': # Load the dataset df = pd.read_csv('./data/heart.csv') print(df['target'].describe()) # Split the dataset into features (X) and target (y) X = df.drop(['target'], axis=1) y = df['target'] # Split the dataset into training and testing sets X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.35, random_state=42) # Fit a Gradient Boosting classifier to the training data and evaluate its performance on the testing data boost = GradientBoostingClassifier(n_estimators=50).fit(X_train, y_train) boost_pred = boost.predict(X_test) print('=' * 64) print('Gradient Boosting Accuracy: ', accuracy_score(y_test, boost_pred))
Para este método de ensamble, jugue un poco con los estimators:
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.35) estimators = range(10, 200, 10) total_accuracy = [] for i in estimators: boost = GradientBoostingClassifier(n_estimators=i).fit(X_train, y_train) boost_pred = boost.predict(X_test) total_accuracy.append(accuracy_score(y_test, boost_pred)) plt.plot(estimators, total_accuracy) plt.xlabel('Estimators') plt.ylabel('Accuracy') plt.show() plt.savefig('Boost.png') print(np.array(total_accuracy).max())
Accuracy = 0.9749303621169917
Modifiqué tu código para que podamos obtener cuanto es el menor número de estimadores que se necesita para lograr la máxima precisión posible.
estimators = range(10, 200, 10) total_accuracy = {} for i in estimators: boost = GradientBoostingClassifier( n_estimators=i).fit(X_train, y_train) boost_pred = boost.predict(X_test) total_accuracy[i] = accuracy_score(y_test, boost_pred) plt.plot(estimators, total_accuracy.values()) plt.xlabel('Estimators') plt.ylabel('Accuracy') plt.show() plt.savefig('Boost.png') max_accu = np.array(list(total_accuracy.values())).max() best_est_num = {k: v for k, v in total_accuracy.items() if v == max_accu} best_est_num = list(best_est_num) print(best_est_num[0])
👩🏼💻 En lo personal soy una persona bastante visual, y me gusta ver los resultados más haya de los números, así que investigue sobre como podía ver de forma gráfica los resultados del entrenamiento de los tres modelos que vimos en ésta y las dos clases anteriores, y este es el resultado, lo divido en dos partes:
⚠️ Asumiendo que se siguió el código del profesor y que ya se cuenta con las variables X e y; datasets de entrenamiento y pruebas; así como con los modelos
KNeighborsClassifier,BaggingClassifieryGradientBoostingClassifierentrenados. Entonces pueden utilizar el siguiente código en sus notebooks.
Librerías necesarias para el ejemplo:
import matplotlib.pyplot as plt # Gráficos import seaborn as sns import numpy as np # Manejo de matrices y vectors from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA # Modelo para reducir la dimensionalidad from sklearn.metrics import confusion_matrix # Visualizar cuantos aciertos y cuantos errores tuvo cada modelo
Matriz de Confusión
kn_cm = confusion_matrix(y_test, kn_pred) bagg_cm = confusion_matrix(y_test, bagg_pred) boost_cm = confusion_matrix(y_test, boost_pred) fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(16, 6), sharey=True) fig.suptitle("Confusion Matrix") # K-Neighbors sns.heatmap(kn_cm, annot=True, cbar=False, ax=axes[0], cmap="viridis") axes[0].set_title(f"K-Neigbors \n(accuracy: {kn_accuracy:.2%})") axes[0].set_xlabel(f"Real Values") axes[0].set_ylabel(f"Predicted Values") # Bagging Classifier sns.heatmap(bagg_cm, annot=True, cbar=False, ax=axes[1], cmap="viridis") axes[1].set_title(f"BaggingClassifier \n(accuracy: {bagg_accuracy:.2%})") axes[1].set_xlabel(f"Real Values") sns.heatmap(boost_cm, annot=True, cbar=False, ax=axes[2], cmap="viridis") axes[2].set_title(f"GradientBoostingClassifier \n(accuracy: {boost_accuracy:.2%})") axes[2].set_xlabel(f"Real Values") plt.show()
Visualizar la matriz de confusión con los resultados de las predicciones de cada uno de los modelos, podemos corroborar el porcentaje de accuracy de cada uno.
En este ejemplo el ganador definitivo fue GradientBoosting con el menor número de fallos.
Frontera de decisión
Este ejemplo es un poco más complejo, pues solo funciona para modelos que se entrenaron con dos features (2 dimensiones). En el caso de nuestro ejemplo de predecir si un paciente tiene o no una enfermedad cardíaca, utilizamos 13 features, por lo tanto visualizar un gráfico con esas dimensiones no es físicamente posible, así que una solución es hacer una reducción de dimensionalidad y pasar de 13 a 2 features.
👀 La reducción de dimensionalidad a del dataset a 2 features se realiza para visualizar una proyección aproximada de las predicciones realizadas por los modelos.
Pasos para crear visualizar la frontera de decisión:
StandardScaler) en caso de que no se haya realizado este proceso previamente.PCA).Código de la función para crear la visualización:
def plot_decision_boundary_CM(clf, X, y, cm, title): # Limites del gráfico x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1 y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1 # Ejes del grid (o malla) x_axis = np.arange(x_min, x_max, 0.02) y_axis = np.arange(y_min, y_max, 0.02) # Generamos la malla (meshgrid) xx, yy = np.meshgrid(x_axis, y_axis) # Aplanamos y combinamos las coordenadas para generar las predicciones Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) # Reorganizamos las predicciones a la misma forma de la matrix de las mallas xx y xx Z = Z.reshape(xx.shape) # Graficamos fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(16, 6)) ax1.contourf(xx, yy, Z, alpha=0.4, cmap='viridis') ax1.scatter(X[:, 0], X[:, 1], c=y, s=20, edgecolor='k', cmap='viridis') ax1.set_title(title) ax1.set_xlabel('PC1') ax1.set_ylabel('PC2') sns.heatmap(cm, annot=True, cmap="viridis", ax=ax2) ax2.set_title("Matriz de Confusión") ax2.set_xlabel("Valores Reales") ax2.set_ylabel("Valores Predichos") plt.show()
Procedemos con los pasos que nos hacen falta:
# Estandatizamos los datos de entrenamiento y pruebas scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # Reducimos la dimensionalidad de los datos a dos dimensiones pca = PCA(n_components=2) X_train_pca = pca.fit_transform(X_train_scaled) X_test_pca = pca.transform(X_test_scaled) # Entrenamos los modelos secundarios con los datos reducidos a dos dimensiones estimators = { "K-Neighbors": KNeighborsClassifier(), "Bagging": BaggingClassifier(estimator=KNeighborsClassifier(), n_estimators=50, random_state=42), "Boosting": GradientBoostingClassifier(n_estimators=50, random_state=42) } for name, estimator in estimators.items(): estimator.fit(X_train_pca, y_train) prediction = estimator.predict(X_test_pca) accuracy = accuracy_score(y_test, prediction) cm = confusion_matrix(y_test, prediction) # Visualizamos plot_decision_boundary_CM(estimator, X_train_pca, y_train, cm, F"{name} - Frontera de Decisión \n(Accuracy: {accuracy:.4%})")
Resultado:
Espero éste aporte les sea de utilidad 💜.
Les dejó mi notebook con los apuntes de las clases y el ejemplo completo, así como un enlace al notebook en Google Colab.
Cualquier feedback es bienvenido!!
#NuncaParenDeAprender y no dejen de curiosear 🧠.
Me gusta mucho el código que lo que hace es iterar para buscar una mejor respuesta. Por esto es que les dejo este mismo para que lo prueben:
import pandas as pd from sklearn.ensemble import GradientBoostingClassifier from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.metrics import accuracy_score if __name__ == "__main__": # Cargar los datos data = pd.read_csv('./data/heart.csv') # Preparar las variables predictoras y la variable objetivo X = data.drop(['target'], axis=1) Y = data['target'] # Dividir en conjunto de entrenamiento y prueba X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.35, random_state=42) # Definir el rango de valores a probar para los hiperparámetros param_grid = { 'n_estimators': [50, 100, 200], 'learning_rate': [0.01, 0.1, 0.2], 'max_depth': [3, 5, 7] } # Crear un modelo de Gradient Boosting gb_model = GradientBoostingClassifier(random_state=42) # Crear GridSearchCV para buscar la mejor combinación de parámetros grid_search = GridSearchCV(estimator=gb_model, param_grid=param_grid, cv=5, scoring='accuracy') # Entrenar el GridSearchCV grid_search.fit(X_train, Y_train) # Imprimir todos los resultados de las combinaciones results = grid_search.cv_results_ print("Resultados para cada combinación de hiperparámetros de Gradient Boosting:") for mean_score, params in zip(results['mean_test_score'], results['params']): print(f"Parámetros: {params}, Precisión promedio: {mean_score}") # Mejor modelo encontrado best_params = grid_search.best_params_ print(f"\nMejores parámetros encontrados: {best_params}") # Evaluar el mejor modelo en los datos de prueba best_model = grid_search.best_estimator_ Y_pred = best_model.predict(X_test) accuracy = accuracy_score(Y_test, Y_pred) print(f"\nPrecisión del mejor modelo en los datos de prueba: {accuracy}")
<u>Bagging vs Boosting </u>
Tanto el bagging (agregación por bootstrap) como el boosting son técnicas de aprendizaje ensemble usadas en machine learning para mejorar el rendimiento de un modelo al combinar las predicciones de múltiples modelos más débiles (también llamados estimadores base). Si bien comparten el mismo objetivo, lo logran de formas diferentes:
Bagging (Agregación por Bootstrap):
Boosting (Boosting de gradiente):
Diferencias clave y cuándo elegir cuál:
Aquí algunas pautas generales para elegir entre bagging y boosting:
En última instancia, la mejor opción depende de las características específicas de tus datos y tu problema. Es posible que desees experimentar con bagging y boosting para ver cuál funciona mejor en tu conjunto de datos.