Métodos de Ensamble para Mejorar Clasificación en Machine Learning
Resumen
¿Cómo abordar el uso de clasificadores KNN y métodos de ensamble?
Sumérgete en la emocionante tarea de mejorar la precisión de los modelos de clasificación utilizando métodos de ensamble. Esta técnica es invaluable cuando un clasificador individual no es suficiente. Aquí, te brindaremos un enfoque detallado para implementar un clasificador K-Nearest Neighbors (KNN) y evaluar su rendimiento mediante métodos de ensamble. Compararemos resultados y subrayaremos el increíble poder de dichos métodos.
¿Cómo implementar el clasificador KNN?
El clasificador KNN es un punto de partida eficaz para comprender y aplicar conceptos básicos de clasificación. Aunque no siempre es el más potente por sí solo, se beneficiará enormemente al combinarse con técnicas de ensamble.
# Implementación del clasificador KNNfrom sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
# Definimos nuestro clasificadorknn_classifier = KNeighborsClassifier()# Entrenamos el clasificador con los datos de entrenamientoknn_classifier.fit(X_train, y_train)# Realizamos predicciones con el clasificador KNNknn_pred = knn_classifier.predict(X_test)# Evaluamos la precisión del clasificadoraccuracy_knn = accuracy_score(y_test, knn_pred)print(f"Precisión del clasificador KNN: {accuracy_knn}")
¿Por qué usar métodos de ensamble?
Los métodos de ensamble son herramientas poderosas capaces de mejorar significativamente el rendimiento de modelos de clasificación, incluso cuando se parte de clasificadores relativamente simples como KNN. Permiten combinar múltiples modelos para obtener una predicción más precisa y confiable.
Mejora de precisión: Combina múltiples modelos débiles para formar un modelo robusto.
Reducción del sobreajuste: Al promediar resultados, se suavizan las predicciones extremas de los modelos individuales.
Versatilidad: Se pueden ajustar y perfeccionar mediante parámetros como el número de estimadores y el tipo de base estimador.
¿Cómo configurar un método de ensamble?
Para configurar un método de ensamble con KNN como base, es fundamental definir los parámetros relevantes, optimizándolos a través de técnicas como la validación cruzada.
# Implementación del clasificador de ensamble Bagging con KNNfrom sklearn.ensemble import BaggingClassifier
# Definimos el clasificador de ensamblebagging_classifier = BaggingClassifier(base_estimator=knn_classifier, n_estimators=50)# Entrenamos el clasificador de ensamblebagging_classifier.fit(X_train, y_train)# Realizamos predicciones utilizando el clasificador de ensamblebagging_pred = bagging_classifier.predict(X_test)# Evaluamos la precisión del clasificador de ensambleaccuracy_bagging = accuracy_score(y_test, bagging_pred)print(f"Precisión del clasificador de ensamble: {accuracy_bagging}")
¿Qué resultados esperar al usar métodos de ensamble?
Comparar los resultados entre un clasificador KNN simple y uno mejorado mediante un método de ensamble ofrece claridad sobre la efectividad de esta técnica. En el ejemplo proporcionado, el método de ensamble aumentó la precisión del clasificador hasta un 77%, reafirmando su utilidad práctica en contextos reales como la asistencia médica en consultorios o clínicas.
La experimentación y la personalización son clave para el éxito de los métodos de ensamble, permitiéndote adecuarlos a tus necesidades y desafíos específicos. Ahora que tienes las bases, ¡sigue adelante y experimenta con estos métodos potencialmente transformadores en tus proyectos de clasificación!
Les paso la versión del código implementando los clasificadores que provee scikit learn
import pandas as pd
from sklearn.neighborsimportKNeighborsClassifierfrom sklearn.ensembleimportBaggingClassifierfrom sklearn.model_selectionimporttrain_test_splitfrom sklearn.metricsimportaccuracy_scorefrom sklearn.svmimportLinearSVCfrom sklearn.svmimportSVCfrom sklearn.linear_modelimportSGDClassifierfrom sklearn.treeimportDecisionTreeClassifierif __name__ =="__main__": path ='./Bagging/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) knn_class =KNeighborsClassifier().fit(x_train, y_train) knn_pred = knn_class.predict(x_test)print('')print('Accuracy KNeighbors:',accuracy_score(knn_pred, y_test))print('') #bag_class =BaggingClassifier(base_estimator=KNeighborsClassifier(), n_estimators=50).fit(x_train, y_train) #bag_pred = bag_class.predict(x_test)#print('')#print('Accuracy Bagging with KNeighbors:',accuracy_score(bag_pred, y_test))#print('') classifier ={'KNeighbors':KNeighborsClassifier(),'LinearSCV':LinearSVC(),'SVC':SVC(),'SGDC':SGDClassifier(),'DecisionTree':DecisionTreeClassifier()}for name, estimator in classifier.items(): bag_class =BaggingClassifier(base_estimator=estimator, n_estimators=5).fit(x_train, y_train) bag_pred = bag_class.predict(x_test)print('Accuracy Bagging with {}:'.format(name),accuracy_score(bag_pred, y_test))print('')
Donde este es el output del código:
Accuracy KNeighbors: 0.6908077994428969
Accuracy Bagging with KNeighbors: 0.7437325905292479
Accuracy Bagging with SVC: 0.9164345403899722
Accuracy Bagging with SGDC: 0.5988857938718662
Accuracy Bagging with DecisionTree: 0.9610027855153204
Excelente aporte. Gracias Marcelo.
MIL MIL MIL GRACIAS
Hola, comparto el código con varios de los algoritmos de sklearn para clasificación:
import pandas as pd
from sklearn.neighborsimportKNeighborsClassifierfrom sklearn.ensembleimportBaggingClassifierfrom sklearn.linear_modelimportLogisticRegressionfrom sklearn.svmimportSVCfrom sklearn.svmimportLinearSVCfrom sklearn.linear_modelimportSGDClassifierfrom sklearn.treeimportDecisionTreeClassifierfrom sklearn.ensembleimportRandomForestClassifierfrom sklearn.model_selectionimporttrain_test_splitfrom sklearn.metricsimport accuracy_score
import warnings
warnings.filterwarnings("ignore")if __name__ =='__main__': dt_heart = pd.read_csv('./datasets/heart.csv')#print(dt_heart['target'].describe()) x = dt_heart.drop(['target'], axis=1) y = dt_heart['target'] x_train, x_test, y_train, y_test =train_test_split(x, y, test_size=0.35, random_state=1) knn_class =KNeighborsClassifier().fit(x_train, y_train) knn_prediction = knn_class.predict(x_test)print('='*64)print('SCORE con KNN: ',accuracy_score(knn_prediction, y_test))'''bag_class =BaggingClassifier(base_estimator=KNeighborsClassifier(), n_estimators=50).fit(x_train, y_train) # base_estimator pide el estimador en el que va a estar basado nuestro metodo || n_estimators nos pide cuantos de estos modelos vamos a utilizar
bag_pred = bag_class.predict(x_test)print('='*64)print(accuracy_score(bag_pred, y_test))'''
estimators ={'LogisticRegression':LogisticRegression(),'SVC':SVC(),'LinearSVC':LinearSVC(),'SGD':SGDClassifier(loss="hinge", penalty="l2", max_iter=5),'KNN':KNeighborsClassifier(),'DecisionTreeClf':DecisionTreeClassifier(),'RandomTreeForest':RandomForestClassifier(random_state=0)}for name, estimator in estimators.items(): bag_class =BaggingClassifier(base_estimator=estimator, n_estimators=50).fit(x_train, y_train) bag_predict = bag_class.predict(x_test)print('='*64)print('SCORE Bagging with {} : {}'.format(name,accuracy_score(bag_predict, y_test)))
Output:
buenisimo
Muy bueno tu codigo, agregue otra comparativa que fue validacion cruzada, que la comenta el profesor en la clase, mas no lla usa, y consegui 100% en los dos ultimos modelos, y mejore las metricas de casi todos los demas.
estimators ={'LogisticRegression':LogisticRegression(),'SVC':SVC(),'LinearSVC':LinearSVC(),'SGD':SGDClassifier(loss="hinge", penalty="l2", max_iter=5),'KNN':KNeighborsClassifier(),'DecisionTreeClf':DecisionTreeClassifier(),'RandomTreeForest':RandomForestClassifier(random_state=0)}for name, estimator in estimators.items(): bag_class =BaggingClassifier(base_estimator=estimator, n_estimators=50).fit(X_train, y_train) bag_predict = bag_class.predict(X_test)print('='*64)print(f'SCORE Bagging with {name} : {round(accuracy_score(bag_predict, y_test), 2)}')for name, estimator in estimators.items(): scores =cross_val_score(estimator,X, y, cv=50)print('='*64)print(f'Cross val score with {name} : {round(scores.mean(), 2)} accuracy with a standard deviation of {round(scores.std(), 2)}')
New in version 1.2:base_estimator was renamed to estimator
Gracias Caballero... Me has salvado :)
Excelentes esas gráficas. Hubieras compartido el código.
XD
Sin embargo, en la practica supongo para problemas relacionados con la salud o sector financiero, se requiere una precisión de los modelos "más alta", por ser temáticas demasiado sensibles.
¿Se usaría R en esos cálculos al ser mas preciso que python?
Porque tendria R que ser mas preciso que python? (mito)
Si los modelos matematicos implementados en ambos son los mismos.
WTF
Ojo, del 2024 en adelante, hay un cambio. POr si les sale error en la línea (24 del código del profesor): "base_estimator".
Solo se debe poner "estimator" en lugar debase_estimator: En versiones recientes de scikit-learn, el argumento base_estimator ha sido renombrado a estimator en el BaggingClassifier. Este cambio es parte de una serie de actualizaciones para hacer más consistentes los nombres de los argumentos a lo largo de toda la biblioteca.
gracias!, crei me estaba volviendo loco por tener este error jaja
técnicamente estas haciendo random forest cuando utilizas bagging en el tree of desition, también por eso es que al random forest le va tan mal ya que estas dividiendo demaciado los datos lo que no deja que los arboles del random forest aprendan.
usando arboles de decisión, obtuve un accuracy de 0.9902597402597403
Excelente clase, solo tengo una cosa para decir, vivan los modelos tree.
Agregue random forest y decision tree, dejo el código como guía
Agregué el clasificador RandomForestClassifier() de Scikit-Learn y mi Accuracy Score fue de 0.9832869080779945.
Así se importa:
rom sklearn.ensembleimportRandomForestClassifier
Comparto mis resultados de diferentes clasificadores con la diferencia de que algunos de ellos los use como estimador para que sean usando en el Bagging.
Aquí tambien dejo las matrices de confusiones y quiero que observen que los modelos de Bagging-Tree y RandomForest son iguales en cuanto al rendimiento en métricas y clasificación de ambas clases. Esto se debe a que por defecto ambos usan modelos como estimadores al DecisionTreeClassifier por lo que aquí la única diferencia es que el Bagging puede cambiar el estimador por otros pero el RandomForest no puede hacerlo.
Con este código no solo logré mejores resultados, sino que pude verificar la variabilidad de resultados que me daba combinando neighbors y estimators:
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import BaggingClassifier
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 para n_neighbors y n_estimators param_grid ={'n_neighbors':[3,5,7,10],'n_estimators':[50,100,200]}# Definir el modelo base (KNeighborsClassifier) y BaggingClassifier knn = KNeighborsClassifier() bagging_model = BaggingClassifier(estimator=knn, random_state=42)# Crear GridSearchCV para buscar la mejor combinación de parámetros grid_search = GridSearchCV( estimator=bagging_model, param_grid={'estimator__n_neighbors': param_grid['n_neighbors'],'n_estimators': param_grid['n_estimators']}, scoring='accuracy', cv=5)# 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 'n_neighbors' y 'n_estimators':")for mean_score, params inzip(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}")
Hola!
Pregunto esto porque el resultados de mi respuesta varia un poco, una décima en la segunda casa o posición, osea si dio 0,71 para mi es 0,69.
Partiendo del mismo data set, con el mismo código, no debería obtener la misma respuesta?
El train_test_split() no hizo la separación de la misma manera, es aleatoria, en esta clase el profesor no le da un random_state
En caso de que quieran usar varios modelos en lugar de uno, pueden usar sklearn.ensemble.StackingClassifier(). Esto lo que les permite es utilizar varios modelos y luego pasar los resultados de estos por un estimador final. Aquí les dejo el enlace de la documentación
Si antes del SPLIT se normalizan los datos, los ACCURACY de los modelos aumentan.
# Normalizamos los datos
df_features =StandardScaler().fit_transform(df_features)
Comparto el comentario de una persona de otra clase:
>El train_test_split se debe hacer antes de realizar el standardscaler ya que sino se hace en ese orden se estaría filtrando información al modelo. lo que se conoce como "data leakage". Esto se debe a que la estandarización implica calcular estadísticas como media y desviación estándar usando todos los datos lo que puede incluir información del conjunto de prueba.
Implementando los clasificadores que tiene sklearne
Para el problema de KNeighbors si primero normalzamos los datos como se vio en la clase 10 tenemos lo siguiente
Como se observa normalizando se obtiene un score mas alto que incluso usando una función de emsable, sin embargo cuando usamos el BaggingClasiffier nuestro score baja, lo cual muestra la importancia de primero normalizar los datos ( esto solo se hace en clasficaciones de acuerdo a lo mencionado en la clase 23 del curso de ML aplicado a python
Una pequeña corrección al código:
Si chequeamos en el la página de sklearn, primero debe ir la variable target con los valores reales, y luego los predichos: