Xgboost: La mise à jour en une étape de xgboost.Booster de python échoue avec une erreur de segmentation

Créé le 22 mars 2017  ·  3Commentaires  ·  Source: dmlc/xgboost

J'expérimentais la construction d'ensembles XGBoost incrémentiels en une étape. Lorsque le Booster est créé par la fonction xgboost.train ( bibliothèque python ), tout semble fonctionner correctement.
Cependant, lorsque je crée le booster et le met à jour en utilisant Booster.update comme ceci :
```python
booster_ = xgboost.Booster({'objective': '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)

La dernière ligne provoque un défaut de segmentation. Je joins le rapport de crash pour python 2.7.13

Commentaire le plus utile

J'ai découvert quelle était la racine du problème. Il s'avère que créer un booster vide en appelant

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

n'initialise que partiellement le booster GBTree. En particulier, le paramètre crucial num_feature
est défini par défaut sur 0 et n'est pas mis à jour avec un nombre approprié de fonctionnalités par un appel .update() ultérieur.

Cependant, passer une valeur explicite pour num_feature résout l'erreur de segmentation :

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

Je pense que xgboost.Booster() devrait émettre un avertissement si cache=() est vide, ou
'num_feature' n'est pas explicitement défini dans l'argument params .

Tous les 3 commentaires

Je voudrais clarifier ce que j'attends des mises à jour incrémentielles de l'objet Booster vide renvoyé par

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

Selon l'algorithme général d'amplification du gradient, je m'attendais à ce qu'après la mise à jour d'un échantillon (X, y) dans DMatrix dtrain avec

booster_.update(dtrain, 1)

le booster vide deviendrait soit f_0(x) -- la prédiction constante, soit f_1(x) -- prédiction après une étape d'amplification du gradient, comme indiqué ci-dessous (de Hastie, Tibshirani, Friedman; 2013 10e ed page 361).

screen shot 2017-03-21 at 18 07 07

J'ai réussi à retracer le problème jusqu'à un vecteur vide RegTree::FVec.data dans l'exemple de reproduction fourni. La trace (manuelle) du deuxième appel à booster_.update est la suivante :

échoue ici :
include/xgboost/tree_model.h:#L528
..., feat.fvalue(split_index), feat.is_missing(split_index), ...

il semble que feat.data.size() == 0 . Je ne sais pas pourquoi après le premier appel à .update() ce vecteur est toujours vide, mais non vide après l'appel alternatif à .train() .

J'ai découvert quelle était la racine du problème. Il s'avère que créer un booster vide en appelant

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

n'initialise que partiellement le booster GBTree. En particulier, le paramètre crucial num_feature
est défini par défaut sur 0 et n'est pas mis à jour avec un nombre approprié de fonctionnalités par un appel .update() ultérieur.

Cependant, passer une valeur explicite pour num_feature résout l'erreur de segmentation :

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

Je pense que xgboost.Booster() devrait émettre un avertissement si cache=() est vide, ou
'num_feature' n'est pas explicitement défini dans l'argument params .

Cette page vous a été utile?
0 / 5 - 0 notes