Niepoprawne wyjście regresji liniowej XGBoost


11

Jestem nowicjuszem w XGBoost, więc wybacz moją ignorancję. Oto kod 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

Dane wyjściowe to:

[ 24.126194  24.126194]

Jak widać, dane wejściowe są po prostu linią prostą. Więc oczekiwany wynik to [40,50]. Co robię tutaj źle?


1
Proszę nie przesyłać pocztą
Dawny33

2
@ Dawny33 usunięty z SO.
simplfuzz

Odpowiedzi:


22

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.


Jak ustawić "booster":"gblinear"przezxgb.XGBRegressor
yosemite_k

Czy lepiej jest uruchomić normalizację funkcji, gdy używasz gblinearwzmacniacza?
pieprzył
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.