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.