Sortie de régression linéaire XGBoost incorrecte

10

Je suis un débutant pour XGBoost alors pardonnez mon ignorance. Voici le code 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

La sortie est:

[ 24.126194  24.126194]

Comme vous pouvez le voir, les données d'entrée sont simplement une ligne droite. Donc, la sortie que j'attends est [40,50]. Qu'est-ce que je fais mal ici?

simplfuzz
la source
1
S'il vous plaît ne pas cross-post
Dawny33
2
@ Dawny33 supprimé de SO.
simplfuzz

Réponses:

21

Il semble que XGBoost utilise par défaut des arbres de régression comme apprenants de base. XGBoost (ou Gradient boosting en général) fonctionne en combinant plusieurs de ces apprenants de base. Les arbres de régression ne peuvent pas extrapoler les modèles dans les données d'entraînement, donc toute entrée supérieure à 3 ou inférieure à 1 ne sera pas correctement prédite dans votre cas. Votre modèle est formé pour prédire les sorties des entrées dans l'intervalle [1,3], une entrée supérieure à 3 recevra la même sortie que 3 et une entrée inférieure à 1 recevra la même sortie que 1.

De plus, les arbres de régression ne voient pas vraiment vos données comme une ligne droite car ce sont des modèles non paramétriques, ce qui signifie qu'ils peuvent théoriquement s'adapter à n'importe quelle forme plus compliquée qu'une ligne droite. En gros, un arbre de régression fonctionne en affectant vos nouvelles données d'entrée à certains des points de données d'entraînement qu'il a vus pendant l'entraînement et produit la sortie en fonction de cela.

Cela contraste avec les régresseurs paramétriques (comme la régression linéaire ) qui recherchent en fait les meilleurs paramètres d'un hyperplan (ligne droite dans votre cas) pour s'adapter à vos données. La régression linéaire ne voir vos données en ligne droite avec une pente et une interception.

Vous pouvez changer l'apprenant de base de votre modèle XGBoost en GLM (modèle linéaire généralisé) en ajoutant "booster":"gblinear"à votre modèle 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 général, pour déboguer les raisons pour lesquelles votre modèle XGBoost se comporte d'une manière particulière, consultez les paramètres du modèle:

gbm.get_dump()

Si votre apprenant de base est un modèle linéaire, la sortie get_dump est:

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

Dans votre code ci-dessus, puisque vous arborez les apprenants de base, le résultat sera:

['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']

Astuce: je préfère en fait utiliser les classes xgb.XGBRegressor ou xgb.XGBClassifier, car elles suivent l' API d' apprentissage sci-kit . Et comme sci-kit learn possède de nombreuses implémentations d'algorithmes d'apprentissage automatique, l'utilisation de XGB comme bibliothèque supplémentaire ne perturbe pas mon flux de travail uniquement lorsque j'utilise l'interface sci-kit de XGBoost.

MohamedEzz
la source
Comment définissez-vous "booster":"gblinear"viaxgb.XGBRegressor
yosemite_k
Est-il préférable d'exécuter la normalisation des fonctionnalités lors de l'utilisation du gblinearbooster?
poivré