Saída de regressão linear XGBoost incorreta

10

Eu sou um novato no XGBoost, então perdoe minha ignorância. Aqui está o código 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

A saída é:

[ 24.126194  24.126194]

Como você pode ver, os dados de entrada são simplesmente uma linha reta. Então a saída que eu espero é [40,50]. O que eu estou fazendo errado aqui?

simplfuzz
fonte
11
Por favor, não faça postagens
cruzadas
2
@ Dawny33 excluído do SO.
Simplfuzz 23/12/2015

Respostas:

21

Parece que o XGBoost usa árvores de regressão como alunos básicos por padrão. O XGBoost (ou aprimoramento de gradiente em geral) funciona combinando vários desses alunos de base. As árvores de regressão não podem extrapolar os padrões nos dados de treinamento; portanto, qualquer entrada acima de 3 ou abaixo de 1 não será prevista corretamente no seu caso. Seu modelo é treinado para prever saídas para entradas no intervalo [1,3], uma entrada maior que 3 receberá a mesma saída que 3 e uma entrada menor que 1 receberá a mesma saída que 1.

Além disso, as árvores de regressão realmente não veem seus dados como uma linha reta , pois são modelos não paramétricos, o que significa que eles podem, teoricamente, ajustar-se a qualquer forma que seja mais complicada do que uma linha reta. Aproximadamente, uma árvore de regressão funciona atribuindo seus novos dados de entrada a alguns dos pontos de dados de treinamento vistos durante o treinamento e produzindo a saída com base nisso.

Isso contrasta com os regressores paramétricos (como regressão linear ) que, na verdade, procuram os melhores parâmetros de um hiperplano (linha reta no seu caso) para ajustar seus dados. Regressão linear faz ver os seus dados como uma linha reta com uma inclinação e uma interceptação.

Você pode alterar o aluno base do seu modelo XGBoost para um GLM (modelo linear generalizado) adicionando "booster":"gblinear"ao seu 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

Em geral, para depurar por que seu modelo XGBoost está se comportando de uma maneira específica, consulte os parâmetros do modelo:

gbm.get_dump()

Se o aluno básico for um modelo linear, a saída get_dump será:

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

No seu código acima, como você aprende a base de árvores, a saída 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']

Dica: Na verdade, prefiro usar as classes xgb.XGBRegressor ou xgb.XGBClassifier, pois seguem a API de aprendizado do sci-kit . E como o sci-kit learn tem tantas implementações de algoritmos de aprendizado de máquina, o uso do XGB como uma biblioteca adicional não perturba meu fluxo de trabalho somente quando eu uso a interface do sci-kit do XGBoost.

MohamedEzz
fonte
Como você define "booster":"gblinear"viaxgb.XGBRegressor
yosemite_k
É melhor executar a normalização de recursos ao usar o gblinearbooster?
apimentado