CatBoost contra LightGBM contra XGBoost, ¡quién es el más fuerte!

Los algoritmos de impulso son una clase de algoritmos de aprendizaje automático que construyen un clasificador sólido entrenando iterativamente una serie de clasificadores débiles (generalmente árboles de decisión). En cada ronda de iteraciones, se diseñan nuevos clasificadores para corregir los errores de rondas de clasificadores anteriores, mejorando así gradualmente el rendimiento general de la clasificación.

A pesar del auge y la popularidad de las redes neuronales, los algoritmos de impulso siguen siendo bastante prácticos. Porque todavía funcionan bien con datos de entrenamiento limitados, tiempo de entrenamiento corto, falta de experiencia en el ajuste de parámetros, etc.

Los algoritmos de impulso incluyen AdaBoost, CatBoost, LightGBM, XGBoost, etc.

imagen

En este artículo, nos centraremos en CatBoost, LightGBM y XGBoost. incluirá:

  • Diferencia estructural;

  • Cómo maneja cada algoritmo las variables categóricas;

  • comprender los parámetros;

  • practicar con conjuntos de datos;

  • rendimiento de cada algoritmo.

Dado que XGBoost (a menudo denominado GBM Killer) ha existido en el aprendizaje automático durante mucho tiempo y hay muchos artículos dedicados a él, este artículo se centrará más en CatBoost y LGBM.

1. Diferencias estructurales entre LightGBM y XGBoost

LightGBM utiliza una novedosa técnica de muestreo de un lado basada en gradientes (GOSS) para filtrar instancias de datos cuando se buscan valores divididos, mientras que XGBoost utiliza un algoritmo preordenado y un algoritmo basado en histograma (algoritmo basado en histograma) para calcular la división óptima. .

Los casos anteriores se refieren a observaciones/muestras.

Primero, comprendamos cómo funciona la división previa al ordenamiento de XGBoost:

  • Para cada nodo, enumere todas las características;

  • Para cada característica, ordene las instancias por valor de característica;

  • Utilice un escaneo lineal para determinar la mejor división de la característica según la ganancia de información;

  • Seleccione la mejor solución de división entre todas las funciones.

En términos simples, los algoritmos basados ​​​​en histogramas dividen todos los puntos de datos de una característica en contenedores discretos y utilizan estos contenedores para encontrar los valores de división del histograma. Aunque es más eficiente en el entrenamiento de velocidad que el algoritmo de clasificación previa, que necesita enumerar todos los puntos de división posibles en los valores propios preclasificados, todavía está por detrás de GOSS en términos de velocidad.

Entonces, ¿qué hace que el método GOSS sea eficiente?

En AdaBoost, los pesos de las muestras se pueden utilizar como un buen indicador de la importancia de la muestra. Sin embargo, en el árbol de decisión impulsado por gradiente (GBDT), no existe un peso de muestra nativo, por lo que no se puede aplicar directamente al método de muestreo propuesto por AdaBoost. Esto introduce métodos de muestreo basados ​​en gradientes.

El gradiente representa la pendiente de la tangente a la función de pérdida, por lo que, en cierto sentido, si el gradiente de los puntos de datos es grande, estos puntos son importantes para encontrar el mejor punto de división porque tienen un error mayor.

GOSS mantiene todas las instancias con gradientes grandes y muestra aleatoriamente instancias con gradientes pequeños. Por ejemplo, supongamos que tengo 500.000 filas de datos, 10.000 de las cuales tienen grandes gradientes. Entonces mi algoritmo elegirá (10k filas con grandes gradientes + x% de selección aleatoria de las 490k filas restantes). Suponiendo que x es 10%, el número total de filas seleccionadas es 59k, en función de las cuales se encuentran los valores divididos.

La suposición básica aquí es que las instancias de entrenamiento con gradientes más pequeños tienen errores de entrenamiento más pequeños y ya están bien entrenadas. Para mantener la misma distribución de datos, al calcular la ganancia de información, GOSS introduce un multiplicador constante para instancias de datos con gradientes más pequeños. Por lo tanto, GOSS logra un buen equilibrio entre reducir la cantidad de instancias de datos y mantener la precisión de los árboles de decisiones de aprendizaje.

imagen

LGBM crece más en hojas con gradientes/errores más grandes

2. ¿Cómo maneja cada modelo las variables categóricas?

2.1 CatBoost

CatBoost tiene la flexibilidad de proporcionar índices en columnas categóricas para que puedan codificarse usando codificación one-hot, usando el parámetro one_hot_max_size (use codificación one-hot para todas las características con una cantidad de valores distintos menor o igual al dado valor del parámetro).

Si no se pasa nada en el parámetro cat_features, CatBoost tratará todas las columnas como variables numéricas.

Nota: CatBoost generará un error si no se proporciona una columna que contiene valores de cadena en cat_features. Además, las columnas que por defecto son de tipo int se tratarán como numéricas de forma predeterminada. Si desea tratarlas como variables categóricas, debe especificarlas en cat_features.

imagen

Para las columnas categóricas restantes, donde el número de categorías únicas es mayor que one_hot_max_size, CatBoost utiliza un método de codificación eficiente similar a la codificación media pero que reduce el sobreajuste. El proceso es el siguiente:

  • Random permuta el conjunto de observaciones de entrada en un orden aleatorio, generando múltiples permutaciones aleatorias;

  • Convierta valores de etiquetas de flotantes o categorías a números enteros;

  • Convierta todos los valores de características categóricas a valores numéricos usando la siguiente fórmula:

imagen

Entre ellos, countInClass indica el número de apariciones del valor de característica de clasificación actual en objetos con un valor de etiqueta igual a "1", prior es el valor preliminar del numerador, determinado por el parámetro de inicio, y totalCount es el número total de objetos. antes del objeto actual que tiene un número de valor de característica de clasificación actual coincidente.

Matemáticamente se puede expresar mediante la siguiente ecuación:

imagen

imagen

2.2 GBM ligero

Al igual que CatBoost, LightGBM también puede manejar funciones categóricas ingresando nombres de funciones. No convierte a codificación one-hot y es mucho más rápida que la codificación one-hot. LGBM utiliza un algoritmo especial para encontrar valores divididos para características categóricas.

imagen

imagen

Nota: Antes de crear el conjunto de datos LGBM, debe convertir las características categóricas a tipos enteros. No acepta un valor de cadena aunque se pase a través del parámetro categorical_feature.

2.3 XGBoost

A diferencia de CatBoost o LGBM, XGBoost por sí solo no puede manejar características categóricas, solo acepta datos numéricos similares a Random Forest. Por lo tanto, es necesario realizar varias codificaciones, como codificación de etiquetas, codificación media o codificación one-hot, antes de enviar datos categóricos a XGBoost.

3. Comprender los parámetros

Todos estos modelos tienen muchos parámetros para ajustar, pero solo analizamos los importantes. A continuación se muestra una lista de estos parámetros, según su función y sus parámetros correspondientes en los diferentes modelos.

imagen

imagen

4. Implementación en el conjunto de datos.

Utilicé el conjunto de datos de Kaggle sobre retrasos de vuelos en 2015 porque contiene características tanto categóricas como numéricas. Con aproximadamente 5 millones de filas de datos, este conjunto de datos es bueno para evaluar el rendimiento de cada tipo de modelo de impulso en términos de velocidad y precisión. Usaré un subconjunto del 10% de estos datos, aproximadamente 500.000 filas.

Las siguientes características se utilizan para modelar:

  • MES, DÍA, DAY_OF_WEEK: tipo de datos int

  • AIRLINE y FLIGHT_NUMBER: tipo de datos int

  • ORIGIN_AIRPORT y DESTINATION_AIRPORT: cadena de tipo de datos

  • DEPARTURE_TIME: tipo de datos flotante

  • ARRIVAL_DELAY: esta será la variable de destino y se convertirá a un valor booleano que representa un retraso de más de 10 minutos.

  • DISTANCE y AIR_TIME: tipo de datos flotante

import pandas as pd, numpy as np, time
from sklearn.model_selection import train_test_split

data = pd.read_csv("./data/flights.csv")
data = data.sample(frac = 0.1, random_state=10)

data = data[["MONTH","DAY","DAY_OF_WEEK","AIRLINE","FLIGHT_NUMBER","DESTINATION_AIRPORT",
                 "ORIGIN_AIRPORT","AIR_TIME", "DEPARTURE_TIME","DISTANCE","ARRIVAL_DELAY"]]
data.dropna(inplace=True)

data["ARRIVAL_DELAY"] = (data["ARRIVAL_DELAY"]>10)*1

cols = ["AIRLINE","FLIGHT_NUMBER","DESTINATION_AIRPORT","ORIGIN_AIRPORT"]
for item in cols:
    data[item] = data[item].astype("category").cat.codes + 1

train, test, y_train, y_test = train_test_split(data.drop(["ARRIVAL_DELAY"], axis=1), data["ARRIVAL_DELAY"],random_state=10, test_size=0.25)

4.1 XGBoost

import xgboost as xgb
from sklearn import metrics
from sklearn.model_selection import GridSearchCV

def auc(m, train, test): 
    return (metrics.roc_auc_score(y_train,m.predict_proba(train)[:,1]),
                            metrics.roc_auc_score(y_test,m.predict_proba(test)[:,1]))

# Parameter Tuning
model = xgb.XGBClassifier()
param_dist = {
    
    "max_depth": [10,30,50],
              "min_child_weight" : [1,3,6],
              "n_estimators": [200],
              "learning_rate": [0.05, 0.1,0.16],}
grid_search = GridSearchCV(model, param_grid=param_dist, cv = 3, 
                                   verbose=10, n_jobs=-1)
grid_search.fit(train, y_train)

grid_search.best_estimator_

model = xgb.XGBClassifier(max_depth=50, min_child_weight=1,  n_estimators=200,\
                          n_jobs=-1 , verbose=1,learning_rate=0.16)
model.fit(train,y_train)
auc(model, train, test)

4.2 GBM ligero

import lightgbm as lgb
from sklearn import metrics

def auc2(m, train, test): 
    return (metrics.roc_auc_score(y_train,m.predict(train)),
                            metrics.roc_auc_score(y_test,m.predict(test)))

lg = lgb.LGBMClassifier(verbose=0)
param_dist = {
    
    "max_depth": [25,50, 75],
              "learning_rate" : [0.01,0.05,0.1],
              "num_leaves": [300,900,1200],
              "n_estimators": [200]
             }
grid_search = GridSearchCV(lg, n_jobs=-1, param_grid=param_dist, cv = 3, scoring="roc_auc", verbose=5)
grid_search.fit(train,y_train)
grid_search.best_estimator_

d_train = lgb.Dataset(train, label=y_train)
params = {
    
    "max_depth": 50, "learning_rate" : 0.1, "num_leaves": 900,  "n_estimators": 300}

# Without Categorical Features
model2 = lgb.train(params, d_train)
auc2(model2, train, test)

# With Catgeorical Features
cate_features_name = ["MONTH","DAY","DAY_OF_WEEK","AIRLINE","DESTINATION_AIRPORT",
                 "ORIGIN_AIRPORT"]
model2 = lgb.train(params, d_train, categorical_feature = cate_features_name)
auc2(model2, train, test)

4.3 Impulso de gato

Al ajustar los parámetros de CatBoost, es difícil pasar el índice de características categóricas. Así que ajusté los parámetros sin pasar características categóricas y evalué dos modelos: uno con características categóricas y otro sin ellas. Sintonicé one_hot_max_size solo ya que no afecta a otros parámetros.

import catboost as cb
cat_features_index = [0,1,2,3,4,5,6]

def auc(m, train, test): 
    return (metrics.roc_auc_score(y_train,m.predict_proba(train)[:,1]),
                            metrics.roc_auc_score(y_test,m.predict_proba(test)[:,1]))

params = {
    
    'depth': [4, 7, 10],
          'learning_rate' : [0.03, 0.1, 0.15],
         'l2_leaf_reg': [1,4,9],
         'iterations': [300]}
cb = cb.CatBoostClassifier()
cb_model = GridSearchCV(cb, params, scoring="roc_auc", cv = 3)
cb_model.fit(train, y_train)

With Categorical features
clf = cb.CatBoostClassifier(eval_metric="AUC", depth=10, iterations= 500, l2_leaf_reg= 9, learning_rate= 0.15)
clf.fit(train,y_train)
auc(clf, train, test)

With Categorical features
clf = cb.CatBoostClassifier(eval_metric="AUC",one_hot_max_size=31, \
                            depth=10, iterations= 500, l2_leaf_reg= 9, learning_rate= 0.15)
clf.fit(train,y_train, cat_features= cat_features_index)
auc(clf, train, test)

5. Conclusión

imagen

Al evaluar un modelo, debemos considerar el rendimiento del modelo en términos de velocidad y precisión.

Teniendo esto en cuenta, CatBoost es el ganador, con la mayor precisión en el conjunto de prueba (0,816), el menor sobreajuste (precisión cercana en los conjuntos de entrenamiento y prueba) y el tiempo de predicción y ajuste más corto. Pero esto se debe únicamente a que consideramos variables categóricas y ajustamos one_hot_max_size. Si no aprovechamos estas características de CatBoost, su precisión es de sólo 0,752, que es el peor rendimiento. Por tanto, concluimos que CatBoost sólo funciona bien cuando hay variables categóricas en los datos y las ajustamos correctamente.

Nuestro próximo modelo que funcionará bien es XGBoost. Incluso ignorando el hecho de que teníamos variables categóricas en los datos y las convertimos en variables numéricas para que las usara XGBoost, su precisión aún estaba bastante cerca de CatBoost. Sin embargo, el único problema de XGBoost es que es demasiado lento. Es realmente frustrante ajustar sus parámetros, especialmente con GridSearchCV (me tomó 6 horas ejecutar GridSearchCV, ¡muy mala idea!). Un mejor enfoque es ajustar los parámetros individualmente en lugar de utilizar GridSearchCV. Lea esta publicación de blog para aprender cómo ajustar los parámetros.

Finalmente, LightGBM ocupa el último lugar. Una cosa a tener en cuenta aquí es que cuando se usa cat_features no funciona bien en términos de velocidad y precisión. Creo que la razón por la que funciona mal es que utiliza algún tipo de codificación media modificada en los datos categóricos, lo que conduce a un sobreajuste (precisión de entrenamiento muy alta: 0,999 en comparación con una precisión de prueba baja). Sin embargo, si se usa normalmente como XGBoost, puede lograr una precisión similar (o incluso mayor) (LGBM - 0,785, XGBoost - 0,789) mucho más rápido que XGBoost.

Finalmente, debo decir que estas observaciones se aplican a este conjunto de datos en particular y pueden o no ser válidas para otros conjuntos de datos. Sin embargo, en general, es un hecho que XGBoost es más lento que los otros dos algoritmos.

Supongo que te gusta

Origin blog.csdn.net/qq_34160248/article/details/132679278
Recomendado
Clasificación