Clasificaci贸n de conjunto / votaci贸n en Python con Scikit-Learn

    Introducci贸n

    Modelos de clasificaci贸n de conjuntos pueden ser potentes herramientas de Machine Learning capaces de lograr un rendimiento excelente y generalizar bien a conjuntos de datos nuevos e invisibles.

    El valor de un clasificador de conjunto es que, al unir las predicciones de m煤ltiples clasificadores, puede corregir los errores cometidos por cualquier clasificador individual, lo que conduce a una mejor precisi贸n en general. Echemos un vistazo a los diferentes m茅todos de clasificaci贸n de conjuntos y veamos c贸mo se pueden implementar estos clasificadores en Scikit-Learn.

    驴Qu茅 son los modelos de conjuntos en el Machine Learning?

     

    Cr茅dito: Pixabay

    Los modelos de conjunto son un m茅todo de aprendizaje de conjunto que combina diferentes algoritmos. En este sentido, es un meta-algoritmo m谩s que un algoritmo en s铆 mismo. Los m茅todos de aprendizaje por conjuntos son valiosos porque pueden mejorar el rendimiento de un modelo predictivo.

    Los m茅todos de aprendizaje por conjuntos se basan en la idea de que unir las predicciones de m煤ltiples clasificadores conducir谩 a un mejor rendimiento ya sea mejorando la precisi贸n de la predicci贸n o reduciendo aspectos como el sesgo y la varianza.

    En general, un modelo de conjunto se clasifica en una de dos categor铆as: enfoques secuenciales y enfoques paralelos.

    Un modelo de conjunto secuencial opera haciendo que los modelos / aprendices base se generen en secuencia. Los m茅todos de conjunto secuencial se utilizan normalmente para intentar aumentar el rendimiento general, ya que el modelo de conjunto puede compensar las predicciones inexactas volviendo a ponderar los ejemplos que anteriormente se clasificaron err贸neamente. Un ejemplo notable de esto es AdaBoost.

    Un modelo paralelo es, como puede adivinar, m茅todos que se basan en crear y capacitar a los alumnos base en paralelo. Los m茅todos paralelos tienen como objetivo reducir la tasa de error entrenando muchos modelos en paralelo y promediando los resultados juntos. Un ejemplo notable de un m茅todo paralelo es el clasificador de bosque aleatorio.

    Otra forma de pensar sobre esto es una distinci贸n entre aprendices homog茅neos y heterog茅neos. Si bien la mayor铆a de los m茅todos de aprendizaje por conjuntos utilizan alumnos de base homog茅nea (muchos del mismo tipo de alumnos), algunos m茅todos de conjunto utilizan alumnos heterog茅neos (diferentes algoritmos de aprendizaje unidos).

    Recordar:

    • Los modelos secuenciales intentan aumentar el rendimiento volviendo a ponderar los ejemplos y los modelos se generan en secuencia.
    • Los modelos paralelos funcionan promediando los resultados juntos despu茅s de entrenar muchos modelos al mismo tiempo.

    Ahora cubriremos diferentes m茅todos de emplear estos modelos para resolver problemas de clasificaci贸n de Machine Learning.

    Diferentes m茅todos de clasificaci贸n de conjuntos

    Harpillera

     

    Cr茅dito: Wikimedia Commons

    Embolsado, tambi茅n conocido como agregaci贸n de bootstrap, es un m茅todo de clasificaci贸n que tiene como objetivo reducir la varianza de las estimaciones promediando varias estimaciones juntas. El empaquetado crea subconjuntos del conjunto de datos principal en el que se capacita a los alumnos.

    Para que se agreguen las predicciones de los diferentes clasificadores, se usa un promedio para la regresi贸n, o se usa un enfoque de votaci贸n para la clasificaci贸n (basado en la decisi贸n de la mayor铆a).

    Un ejemplo de m茅todo de clasificaci贸n de ensacado es el clasificador de bosques aleatorios. En el caso del clasificador de bosques aleatorios, todos los 谩rboles individuales se entrenan en una muestra diferente del conjunto de datos.

    El 谩rbol tambi茅n se entrena mediante selecciones aleatorias de caracter铆sticas. Cuando los resultados se promedian juntos, la varianza general disminuye y el modelo funciona mejor como resultado.

    Impulsar

    Impulsar algoritmos son capaces de tomar modelos d茅biles y de bajo rendimiento y convertirlos en modelos s贸lidos. La idea detr谩s de los algoritmos de impulso es que se asignan muchos modelos de aprendizaje d茅biles a los conjuntos de datos, y luego se ajustan las ponderaciones de los ejemplos mal clasificados durante las rondas posteriores de aprendizaje.

    Las predicciones de los clasificadores se agregan y luego las predicciones finales se realizan mediante una suma ponderada (en el caso de regresiones), o un voto mayoritario ponderado (en el caso de clasificaci贸n).

    AdaBoost es un ejemplo de un m茅todo de clasificador de refuerzo, como lo es Gradient Boosting, que se deriv贸 del algoritmo mencionado anteriormente.

    Si desea leer m谩s sobre Gradient Boosting y la teor铆a detr谩s de 茅l, ya lo hemos cubierto en un art铆culo anterior.

    Apilado

     

    Cr茅dito: Wikimedia Commons

    Algoritmos de apilamiento son un m茅todo de aprendizaje por conjuntos que combina la decisi贸n de diferentes algoritmos de regresi贸n o clasificaci贸n. Los modelos de componentes se entrenan en todo el conjunto de datos de entrenamiento. Despu茅s de entrenar estos modelos de componentes, se ensambla un metamodelo a partir de los diferentes modelos y luego se entrena en los resultados de los modelos de componentes. Este enfoque generalmente crea un conjunto heterog茅neo porque los modelos de componentes suelen ser algoritmos diferentes.

    Implementaciones de ejemplo

    Ahora que hemos explorado diferentes m茅todos que podemos usar para crear modelos de conjunto, echemos un vistazo a c贸mo podr铆amos implementar un clasificador usando los diferentes m茅todos.

    Sin embargo, antes de que podamos echar un vistazo a las diferentes formas de implementar clasificadores de conjuntos, debemos seleccionar un conjunto de datos para usar y hacer un preprocesamiento del conjunto de datos.

    Usaremos el conjunto de datos Titanic, que puede ser descargado aqu铆. Hagamos un preprocesamiento de los datos para deshacernos de los valores perdidos y escalar los datos a un rango uniforme. Luego podemos empezar a configurar los clasificadores de conjuntos.

    Preprocesamiento de datos

    Para empezar, comenzaremos importando todas las funciones que necesitamos de sus respectivas bibliotecas. Estaremos usando Pandas y Numpy para cargar y transformar los datos, as铆 como la LabelEncoder y StandardScaler herramientas.

    Tambi茅n necesitaremos las m茅tricas de Machine Learning y train_test_split funci贸n. Finalmente, necesitaremos los clasificadores que queremos usar:

    import pandas as pd
    import numpy as np
    import warnings
    
    from sklearn.preprocessing import LabelEncoder, StandardScaler
    from sklearn.metrics import accuracy_score, f1_score, log_loss
    from sklearn.model_selection import train_test_split, KFold, cross_val_score
    
    from sklearn.svm import SVC
    from sklearn.linear_model import LogisticRegression
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.ensemble import VotingClassifier
    from sklearn.ensemble import BaggingClassifier
    from sklearn.ensemble import AdaBoostClassifier, RandomForestClassifier, ExtraTreesClassifier
    

    Comenzaremos cargando los datos de entrenamiento y prueba y luego crearemos una funci贸n para verificar la presencia de valores nulos:

    training_data = pd.read_csv("train.csv")
    testing_data = pd.read_csv("test.csv")
    
    def get_nulls(training, testing):
        print("Training Data:")
        print(pd.isnull(training).sum())
        print("Testing Data:")
        print(pd.isnull(testing).sum())
    
    get_nulls(training_data, testing_data)
    

    Da la casualidad de que hay muchos valores perdidos en el Age y Cabin categor铆as.

    Training Data:
    PassengerId      0
    Survived         0
    Pclass           0
    Name             0
    Sex              0
    Age            177
    SibSp            0
    Parch            0
    Ticket           0
    Fare             0
    Cabin          687
    Embarked         2
    dtype: int64
    Testing Data:
    PassengerId      0
    Pclass           0
    Name             0
    Sex              0
    Age             86
    SibSp            0
    Parch            0
    Ticket           0
    Fare             1
    Cabin          327
    Embarked         0
    dtype: int64
    

    Comenzaremos eliminando algunas de las columnas que probablemente ser谩n in煤tiles: el Cabin columna y el Ticket columna. los Cabin columna tiene demasiados valores perdidos y el Ticket La columna simplemente se compone de demasiadas categor铆as para ser 煤til.

    Despu茅s de eso, necesitaremos imputar algunos valores perdidos. Cuando lo hacemos, debemos tener en cuenta c贸mo el conjunto de datos est谩 ligeramente sesgado hacia la derecha (las edades j贸venes son un poco m谩s prominentes que las edades mayores). Usaremos los valores de la mediana cuando imputemos los datos porque debido a grandes valores at铆picos, tomar los valores promedio nos dar铆a valores imputados que est谩n lejos del centro del conjunto de datos:

    # Drop the cabin column, as there are too many missing values
    # Drop the ticket numbers too, as there are too many categories
    # Drop names as they won't really help predict survivors
    
    training_data.drop(labels=['Cabin', 'Ticket', 'Name'], axis=1, inplace=True)
    testing_data.drop(labels=['Cabin', 'Ticket', 'Name'], axis=1, inplace=True)
    
    # Taking the mean/average value would be impacted by the skew
    # so we should use the median value to impute missing values
    
    training_data["Age"].fillna(training_data["Age"].median(), inplace=True)
    testing_data["Age"].fillna(testing_data["Age"].median(), inplace=True)
    training_data["Embarked"].fillna("S", inplace=True)
    testing_data["Fare"].fillna(testing_data["Fare"].median(), inplace=True)
    
    get_nulls(training_data, testing_data)
    

    Ahora podemos ver que no hay m谩s valores perdidos:

    Training Data:
    PassengerId    0
    Survived       0
    Pclass         0
    Name           0
    Sex            0
    Age            0
    SibSp          0
    Parch          0
    Fare           0
    Embarked       0
    dtype: int64
    Testing Data:
    PassengerId    0
    Pclass         0
    Name           0
    Sex            0
    Age            0
    SibSp          0
    Parch          0
    Fare           0
    Embarked       0
    dtype: int64
    

    Ahora vamos a necesitar codificar los datos no num茅ricos. Vamos a configurar un LabelEncoder y colocarlo en el Sex caracter铆stica y luego transformar los datos con el codificador. Luego reemplazaremos los valores en el Sex funci贸n con los que se han codificado y luego hacer lo mismo para el Embarked caracter铆stica.

    Finalmente, escalemos los datos usando el StandardScaler, por lo que no hay grandes fluctuaciones en los valores.

    encoder_1 = LabelEncoder()
    # Fit the encoder on the data
    encoder_1.fit(training_data["Sex"])
    
    # Transform and replace training data
    training_sex_encoded = encoder_1.transform(training_data["Sex"])
    training_data["Sex"] = training_sex_encoded
    test_sex_encoded = encoder_1.transform(testing_data["Sex"])
    testing_data["Sex"] = test_sex_encoded
    
    encoder_2 = LabelEncoder()
    encoder_2.fit(training_data["Embarked"])
    
    training_embarked_encoded = encoder_2.transform(training_data["Embarked"])
    training_data["Embarked"] = training_embarked_encoded
    testing_embarked_encoded = encoder_2.transform(testing_data["Embarked"])
    testing_data["Embarked"] = testing_embarked_encoded
    
    # Any value we want to reshape needs be turned into array first
    ages_train = np.array(training_data["Age"]).reshape(-1, 1)
    fares_train = np.array(training_data["Fare"]).reshape(-1, 1)
    ages_test = np.array(testing_data["Age"]).reshape(-1, 1)
    fares_test = np.array(testing_data["Fare"]).reshape(-1, 1)
    
    # Scaler takes arrays
    scaler = StandardScaler()
    
    training_data["Age"] = scaler.fit_transform(ages_train)
    training_data["Fare"] = scaler.fit_transform(fares_train)
    testing_data["Age"] = scaler.fit_transform(ages_test)
    testing_data["Fare"] = scaler.fit_transform(fares_test)
    

    Ahora que nuestros datos han sido preprocesados, podemos seleccionar nuestras caracter铆sticas y etiquetas y luego usar el train_test_split funci贸n para dividir todos nuestros datos de entrenamiento en conjuntos de entrenamiento y prueba:

    # Now to select our training/testing data
    X_features = training_data.drop(labels=['PassengerId', 'Survived'], axis=1)
    y_labels = training_data['Survived']
    
    print(X_features.head(5))
    
    # Make the train/test data from validation
    
    X_train, X_val, y_train, y_val = train_test_split(X_features, y_labels, test_size=0.1, random_state=27)
    

    Ahora estamos listos para comenzar a implementar m茅todos de clasificaci贸n por conjuntos.

    Enfoque de promediado simple

    Antes de entrar en los tres grandes m茅todos de conjunto que cubrimos anteriormente, cubramos un m茅todo muy r谩pido y f谩cil de usar un enfoque de conjunto: promediar predicciones. Simplemente sumamos los diferentes valores predichos de nuestros clasificadores elegidos juntos y luego dividimos por el n煤mero total de clasificadores, usando la divisi贸n de piso para obtener un valor total.

    En este caso de prueba, usaremos regresi贸n log铆stica, un clasificador de 谩rbol de decisi贸n y el clasificador de vectores de soporte. Ajustamos los clasificadores a los datos y luego guardamos las predicciones como variables. Luego, simplemente sumamos las predicciones y dividimos:

    LogReg_clf = LogisticRegression()
    DTree_clf = DecisionTreeClassifier()
    SVC_clf = SVC()
    
    LogReg_clf.fit(X_train, y_train)
    DTree_clf.fit(X_train, y_train)
    SVC_clf.fit(X_train, y_train)
    
    LogReg_pred = LogReg_clf.predict(X_val)
    DTree_pred = DTree_clf.predict(X_val)
    SVC_pred = SVC_clf.predict(X_val)
    
    averaged_preds = (LogReg_pred + DTree_pred + SVC_pred)//3
    acc = accuracy_score(y_val, averaged_preds)
    print(acc)
    

    Aqu铆 est谩 la precisi贸n que obtuvimos con este m茅todo:

    0.8444444444444444
    

    Ejemplo de clasificaci贸n de votaci贸n / apilamiento

    Cuando se trata de crear un clasificador de apilamiento / votaci贸n, Scikit-Learn nos proporciona algunas funciones 煤tiles que podemos usar para lograrlo.

    los VotingClassifier toma una lista de diferentes estimadores como argumentos y un m茅todo de votaci贸n. los hard El m茅todo de votaci贸n utiliza las etiquetas previstas y un sistema de reglas de mayor铆a, mientras que soft El m茅todo de votaci贸n predice una etiqueta basada en argmax / mayor valor predicho de la suma de las probabilidades predichas.

    Despu茅s de proporcionar los clasificadores deseados, necesitamos ajustar el objeto clasificador de conjunto resultante. Luego podemos obtener predicciones y utilizar m茅tricas de precisi贸n:

    voting_clf = VotingClassifier(estimators=[('SVC', SVC_clf), ('DTree', DTree_clf), ('LogReg', LogReg_clf)], voting='hard')
    voting_clf.fit(X_train, y_train)
    preds = voting_clf.predict(X_val)
    acc = accuracy_score(y_val, preds)
    l_loss = log_loss(y_val, preds)
    f1 = f1_score(y_val, preds)
    
    print("Accuracy is: " + str(acc))
    print("Log Loss is: " + str(l_loss))
    print("F1 Score is: " + str(f1))
    

    Esto es lo que dicen las m茅tricas sobre la VotingClassifierrendimiento de:

    Accuracy is: 0.8888888888888888
    Log Loss is: 3.8376684749044165
    F1 Score is: 0.8484848484848486
    

    Ejemplo de clasificaci贸n de ensacado

    A continuaci贸n, se explica c贸mo podemos implementar la clasificaci贸n de ensacado con Scikit-Learn. Sklearn’s Clasificador de ensacado toma en un modelo de clasificaci贸n elegido, as铆 como el n煤mero de estimadores que desea usar; puede usar un modelo como Regresi贸n log铆stica o 脕rboles de decisi贸n.

    Sklearn tambi茅n proporciona acceso a RandomForestClassifier y el ExtraTreesClassifier, que son modificaciones de la clasificaci贸n del 谩rbol de decisiones. Estos clasificadores tambi茅n se pueden utilizar junto con la herramienta de validaci贸n cruzada de K-Folds.

    Compararemos varios enfoques de clasificaci贸n de ensacado diferentes aqu铆, imprimiendo los resultados medios de la puntuaci贸n de validaci贸n cruzada K-fold:

    logreg_bagging_model = BaggingClassifier(base_estimator=LogReg_clf, n_estimators=50, random_state=12)
    dtree_bagging_model = BaggingClassifier(base_estimator=DTree_clf, n_estimators=50, random_state=12)
    random_forest = RandomForestClassifier(n_estimators=100, random_state=12)
    extra_trees = ExtraTreesClassifier(n_estimators=100, random_state=12)
    
    def bagging_ensemble(model):
        k_folds = KFold(n_splits=20, random_state=12)
        results = cross_val_score(model, X_train, y_train, cv=k_folds)
        print(results.mean())
    
    bagging_ensemble(logreg_bagging_model)
    bagging_ensemble(dtree_bagging_model)
    bagging_ensemble(random_forest)
    bagging_ensemble(extra_trees)
    

    Estos son los resultados que obtuvimos de los clasificadores:

    0.7865853658536585
    0.8102439024390244
    0.8002439024390245
    0.7902439024390244
    

    Ejemplo de clasificaci贸n de impulso

    Finalmente, veremos c贸mo usar un m茅todo de clasificaci贸n de impulso. Como se mencion贸, hay un art铆culo separado sobre el tema de Gradient Boosting que puede leer aqu铆.

    Scikit-Learn tiene una funci贸n Clasificador AdaBoost, que toma un n煤mero dado de estimadores como primer argumento. Podemos intentar usar un bucle for para ver c贸mo cambia el rendimiento de la clasificaci贸n en diferentes valores, y tambi茅n podemos combinarlo con la herramienta de validaci贸n cruzada de K-Folds:

    k_folds = KFold(n_splits=20, random_state=12)
    
    num_estimators = [20, 40, 60, 80, 100]
    
    for i in num_estimators:
        ada_boost = AdaBoostClassifier(n_estimators=i, random_state=12)
        results = cross_val_score(ada_boost, X_train, y_train, cv=k_folds)
        print("Results for {} estimators:".format(i))
        print(results.mean())
    

    Estos son los resultados que obtuvimos:

    Results for 20 estimators:
    0.8015243902439024
    Results for 40 estimators:
    0.8052743902439025
    Results for 60 estimators:
    0.8053048780487805
    Results for 80 estimators:
    0.8040243902439024
    Results for 100 estimators:
    0.8027743902439024
    

    Resumiendo

    Hemos cubierto las ideas detr谩s de tres t茅cnicas diferentes de clasificaci贸n de conjuntos: votaci贸n apilamiento, ensacado y refuerzo.

    Scikit-Learn le permite crear f谩cilmente instancias de los diferentes clasificadores de conjuntos. Estos objetos de conjunto se pueden combinar con otras herramientas de Scikit-Learn como la validaci贸n cruzada de K-Folds.

     

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *