Salida de regresión lineal XGBoost incorrecta

10

Soy un novato en XGBoost, así que perdona mi ignorancia. Aquí está el código de Python:

import pandas as pd
import xgboost as xgb

df = pd.DataFrame({'x':[1,2,3], 'y':[10,20,30]})
X_train = df.drop('y',axis=1)
Y_train = df['y']
T_train_xgb = xgb.DMatrix(X_train, Y_train)

params = {"objective": "reg:linear"}
gbm = xgb.train(dtrain=T_train_xgb,params=params)
Y_pred = gbm.predict(xgb.DMatrix(pd.DataFrame({'x':[4,5]})))
print Y_pred

Salida es:

[ 24.126194  24.126194]

Como puede ver, los datos de entrada son simplemente una línea recta. Entonces la salida que espero es [40,50]. ¿Qué estoy haciendo mal aquí?

simplfuzz
fuente
1
Por favor, no publique
mensajes cruzados
2
@ Dawny33 eliminado de SO.
simplfuzz

Respuestas:

21

Parece que XGBoost usa árboles de regresión como aprendices base por defecto. XGBoost (o el aumento de gradiente en general) funciona combinando múltiples de estos aprendices básicos. Los árboles de regresión no pueden extrapolar los patrones en los datos de entrenamiento, por lo que cualquier entrada por encima de 3 o por debajo de 1 no se predecirá correctamente en su caso. Su modelo está entrenado para predecir salidas para entradas en el intervalo [1,3], una entrada mayor que 3 recibirá la misma salida que 3, y una entrada menor que 1 recibirá la misma salida que 1.

Además, los árboles de regresión realmente no ven sus datos como una línea recta, ya que son modelos no paramétricos, lo que significa que teóricamente pueden ajustarse a cualquier forma que sea más complicada que una línea recta. Aproximadamente, un árbol de regresión funciona asignando sus nuevos datos de entrada a algunos de los puntos de datos de entrenamiento que ha visto durante el entrenamiento, y produce el resultado en función de eso.

Esto contrasta con los regresores paramétricos (como la regresión lineal ) que en realidad buscan los mejores parámetros de un hiperplano (línea recta en su caso) para adaptarse a sus datos. La regresión lineal hace ver sus datos como una línea recta con una pendiente y una intersección.

Puede cambiar el alumno base de su modelo XGBoost a un GLM (modelo lineal generalizado) agregando "booster":"gblinear"a su modelo params:

import pandas as pd
import xgboost as xgb

df = pd.DataFrame({'x':[1,2,3], 'y':[10,20,30]})
X_train = df.drop('y',axis=1)
Y_train = df['y']
T_train_xgb = xgb.DMatrix(X_train, Y_train)

params = {"objective": "reg:linear", "booster":"gblinear"}
gbm = xgb.train(dtrain=T_train_xgb,params=params)
Y_pred = gbm.predict(xgb.DMatrix(pd.DataFrame({'x':[4,5]})))
print Y_pred

En general, para depurar por qué su modelo XGBoost se comporta de una manera particular, vea los parámetros del modelo:

gbm.get_dump()

Si su alumno base es un modelo lineal, la salida get_dump es:

['bias:\n4.49469\nweight:\n7.85942\n']

En su código anterior, dado que los alumnos base del árbol, la salida será:

['0:[x<3] yes=1,no=2,missing=1\n\t1:[x<2] yes=3,no=4,missing=3\n\t\t3:leaf=2.85\n\t\t4:leaf=5.85\n\t2:leaf=8.85\n',
 '0:[x<3] yes=1,no=2,missing=1\n\t1:[x<2] yes=3,no=4,missing=3\n\t\t3:leaf=1.995\n\t\t4:leaf=4.095\n\t2:leaf=6.195\n',
 '0:[x<3] yes=1,no=2,missing=1\n\t1:[x<2] yes=3,no=4,missing=3\n\t\t3:leaf=1.3965\n\t\t4:leaf=2.8665\n\t2:leaf=4.3365\n',
 '0:[x<3] yes=1,no=2,missing=1\n\t1:[x<2] yes=3,no=4,missing=3\n\t\t3:leaf=0.97755\n\t\t4:leaf=2.00655\n\t2:leaf=3.03555\n',
 '0:[x<3] yes=1,no=2,missing=1\n\t1:[x<2] yes=3,no=4,missing=3\n\t\t3:leaf=0.684285\n\t\t4:leaf=1.40458\n\t2:leaf=2.12489\n',
 '0:[x<3] yes=1,no=2,missing=1\n\t1:[x<2] yes=3,no=4,missing=3\n\t\t3:leaf=0.478999\n\t\t4:leaf=0.983209\n\t2:leaf=1.48742\n',
 '0:[x<3] yes=1,no=2,missing=1\n\t1:[x<2] yes=3,no=4,missing=3\n\t\t3:leaf=0.3353\n\t\t4:leaf=0.688247\n\t2:leaf=1.04119\n',
 '0:[x<3] yes=1,no=2,missing=1\n\t1:[x<2] yes=3,no=4,missing=3\n\t\t3:leaf=0.23471\n\t\t4:leaf=0.481773\n\t2:leaf=0.728836\n',
 '0:[x<3] yes=1,no=2,missing=1\n\t1:[x<2] yes=3,no=4,missing=3\n\t\t3:leaf=0.164297\n\t\t4:leaf=0.337241\n\t2:leaf=0.510185\n',
 '0:[x<2] yes=1,no=2,missing=1\n\t1:leaf=0.115008\n\t2:[x<3] yes=3,no=4,missing=3\n\t\t3:leaf=0.236069\n\t\t4:leaf=0.357129\n']

Consejo: en realidad prefiero usar las clases xgb.XGBRegressor o xgb.XGBClassifier, ya que siguen la API de aprendizaje de sci-kit . Y debido a que sci-kit learn tiene tantas implementaciones de algoritmos de aprendizaje automático, usar XGB como una biblioteca adicional no perturba mi flujo de trabajo solo cuando uso la interfaz sci-kit de XGBoost.

MohamedEzz
fuente
¿Cómo configurar a "booster":"gblinear"través dexgb.XGBRegressor
yosemite_k
¿Es mejor ejecutar la normalización de funciones cuando se usa el gblinearrefuerzo?
salpicado el