Xgboost: A atualização em uma etapa do xgboost.Booster do python falha com um segfault

Criado em 22 mar. 2017  ·  3Comentários  ·  Fonte: dmlc/xgboost

Eu estava fazendo experiências com a construção incremental do conjunto XGBoost em uma etapa. Quando o Booster é criado pela função xgboost.train ( biblioteca python ), tudo parece funcionar bem.
No entanto, quando eu crio o booster e o atualizo usando Booster.update assim:
`` `python
booster_ = xgboost.Booster ({'objetivo': 'reg: linear'})
booster_.update (dtrain, 1)

the python process fails with a segmentation fault.

## Environment info
Operating System:
* **python 3.6** Mac OS X 10.10.5 (Darwin 14.5.0), Ubuntu 14.04.5 LTS (GNU/Linux 3.19.0-25-generic x86_64);
* **python 2.7** Mac OS X 10.10.6 (Darwin 15.6.0);

Compiler:
* **python 3.6** used `pip install xgboost`;
* **python 2.7** gcc (6.3.0 --without-multilib);

`xgboost` version used:
* **python 3.6** version 0.6 from pip;
* **python 2.7.13** git HEAD 4a63f4ab43480adaaf13bde2485d5bfedd952520;

## Steps to reproduce
```python
import xgboost
dtrain = xgboost.DMatrix(data=[[-1.0], [0.0], [1.0]], label=[0.0, -1.0, 1.0])

booster_ = xgboost.Booster({'objective': 'reg:linear', 'max_depth': 1})
booster_.update(dtrain, 1)

booster_.update(dtrain, 1)

A última linha causa falha de segmentação. Anexei o relatório de falha para python 2.7.13

Comentários muito úteis

Eu descobri qual era a raiz do problema. Acontece que a criação de um booster vazio chamando

booster_ = xgboost.Booster({'objective': 'reg:linear'})

inicializa apenas parcialmente o Booster GBTree. Em particular, o parâmetro crucial num_feature
é definido por padrão como 0 e não é atualizado para um número adequado de recursos por uma chamada .update() subsequente.

No entanto, passar um valor explícito para num_feature resolve a falha de segmentação:

booster_ = xgboost.Booster({'objective': 'reg:linear', 'num_feature': dtrain.num_col()})

Acho que xgboost.Booster() deve emitir um aviso se cache=() estiver vazio, ou
'num_feature' não está explicitamente definido no argumento params .

Todos 3 comentários

Gostaria de esclarecer qual é a minha expectativa de fazer atualizações incrementais do objeto Booster vazio retornado por

booster_ = xgboost.Booster({'objective': 'reg:linear', 'max_depth': 1})

De acordo com o algoritmo de aumento de gradiente geral, eu esperava que depois de atualizar em uma amostra (X, y) na DMatrix dtrain com

booster_.update(dtrain, 1)

o impulsionador vazio se tornaria f_0(x) - a previsão constante, ou f_1(x) - previsão após uma etapa de aumento de gradiente, conforme mostrado abaixo (de Hastie, Tibshirani, Friedman; página

screen shot 2017-03-21 at 18 07 07

Consegui rastrear o problema até um vetor RegTree::FVec.data vazio no exemplo de reprodução fornecido. O rastreamento (manual) da segunda chamada para booster_.update é o seguinte:

falha aqui:
inclua / xgboost / tree_model.h: # L528
..., feat.fvalue(split_index), feat.is_missing(split_index), ...

parece que feat.data.size() == 0 . Não sei por que, após a primeira chamada para .update() esse vetor ainda está vazio, mas não está vazio após a chamada alternativa para .train() .

Eu descobri qual era a raiz do problema. Acontece que a criação de um booster vazio chamando

booster_ = xgboost.Booster({'objective': 'reg:linear'})

inicializa apenas parcialmente o Booster GBTree. Em particular, o parâmetro crucial num_feature
é definido por padrão como 0 e não é atualizado para um número adequado de recursos por uma chamada .update() subsequente.

No entanto, passar um valor explícito para num_feature resolve a falha de segmentação:

booster_ = xgboost.Booster({'objective': 'reg:linear', 'num_feature': dtrain.num_col()})

Acho que xgboost.Booster() deve emitir um aviso se cache=() estiver vazio, ou
'num_feature' não está explicitamente definido no argumento params .

Esta página foi útil?
0 / 5 - 0 avaliações