Wygląda na to, że XGBoost domyślnie używa drzew regresji jako podstawowych uczniów. XGBoost (lub ogólnie zwiększenie gradientu) działa, łącząc wielu spośród tych podstawowych uczniów. Drzewa regresji nie mogą ekstrapolować wzorców w danych treningowych, więc wszelkie dane wejściowe powyżej 3 lub poniżej 1 nie zostaną poprawnie przewidziane w twoim przypadku. Twój model jest przeszkolony do przewidywania wyników dla danych wejściowych w przedziale [1,3]
, dane wejściowe większe niż 3 otrzymają takie same dane wyjściowe jak 3, a dane wejściowe mniejsze niż 1 otrzymają takie same dane wyjściowe jak 1.
Dodatkowo drzewa regresji tak naprawdę nie widzą twoich danych jako linii prostej, ponieważ są to modele nieparametryczne, co oznacza, że mogą teoretycznie pasować do dowolnego kształtu, który jest bardziej skomplikowany niż linia prosta. Z grubsza, drzewo regresji działa, przypisując nowe dane wejściowe do niektórych punktów danych treningowych, które widział podczas treningu i na tej podstawie generuje wyniki.
Jest to w przeciwieństwie do regresorów parametrycznych (takich jak regresja liniowa ), które faktycznie szukają najlepszych parametrów hiperpłaszczyzny (w twoim przypadku linii prostej), aby pasowały do twoich danych. Regresja liniowa robi zobaczyć swoje dane w postaci prostej o nachyleniu oraz przecięcia.
Możesz zmienić podstawowego ucznia swojego modelu XGBoost na GLM (uogólniony model liniowy), dodając "booster":"gblinear"
do swojego modelu 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
Ogólnie, aby debugować, dlaczego Twój model XGBoost zachowuje się w określony sposób, zobacz parametry modelu:
gbm.get_dump()
Jeśli twoim podstawowym uczniem jest model liniowy, wynik get_dump to:
['bias:\n4.49469\nweight:\n7.85942\n']
W powyższym kodzie, ponieważ jesteście bazowymi uczniami, wyniki będą następujące:
['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']
Wskazówka: Właściwie wolę używać klas xgb.XGBRegressor lub xgb.XGBClassifier, ponieważ są one zgodne z interfejsem API uczenia się sci-kit . A ponieważ nauka sci-kit ma tak wiele implementacji algorytmów uczenia maszynowego, użycie XGB jako dodatkowej biblioteki nie zakłóca mojego przepływu pracy tylko wtedy, gdy korzystam z interfejsu sci-kit XGBoost.