Ich experimentierte mit der einstufigen inkrementellen XGBoost-Ensemble-Konstruktion. Wenn der Booster von der xgboost.train-Funktion ( Python-Bibliothek ) erstellt wird, scheint alles gut zu funktionieren.
Wenn ich jedoch den Booster erstelle und mit Booster.update wie
```python
booster_ = xgboost.Booster({'objektiv': '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)
Die letzte Zeile verursacht einen Segmentierungsfehler. Ich hänge den Absturzbericht für Python 2.7.13 an
Ich möchte klarstellen, was ich von inkrementellen Aktualisierungen eines leeren Booster-Objekts erwarte, das von . zurückgegeben wird
booster_ = xgboost.Booster({'objective': 'reg:linear', 'max_depth': 1})
Gemäß dem allgemeinen Gradienten-Boosting-Algorithmus habe ich erwartet, dass nach der Aktualisierung eines Samples (X, y) in DMatrix dtrain
mit
booster_.update(dtrain, 1)
der leere Booster würde entweder f_0(x)
-- die konstante Vorhersage oder f_1(x)
-- Vorhersage nach einem Schritt des Gradienten-Boostens werden, wie unten gezeigt (von Hastie, Tibshirani, Friedman; 2013 10th ed page 361).
Ich habe es geschafft, das Problem auf einen leeren RegTree::FVec.data
Vektor in dem bereitgestellten Reproduktionsbeispiel zurückzuführen. Der (manuelle) Ablauf des zweiten Aufrufs von booster_.update
sieht wie folgt aus:
this->UpdateOneIter(...);
this->PredictRaw(train, &preds_);
gbm_->Predict(data, out_preds, ntree_limit=0);
PredLoopInternal<GBTree>(p_fmat, out_preds, 0, ntree_limit, true);
PredValue(inst, gid, info.GetRoot(ridx), &feats, tree_begin, tree_end);
int tid = trees[i]->GetLeafIndex(*p_feats, root_index);
scheitert hier:
include/xgboost/tree_model.h:#L528
..., feat.fvalue(split_index), feat.is_missing(split_index), ...
es scheint, dass feat.data.size() == 0
. Ich weiß nicht, warum dieser Vektor nach dem ersten Aufruf von .update()
immer noch leer ist, aber nach dem alternativen Aufruf von .train()
nicht leer.
Ich habe herausgefunden, was die Wurzel des Problems war. Es stellte sich heraus, dass durch Anrufen ein leerer Booster erstellt wurde
booster_ = xgboost.Booster({'objective': 'reg:linear'})
initialisiert den GBtree-Booster nur teilweise. Insbesondere der entscheidende Parameter num_feature
ist standardmäßig auf 0 gesetzt und wird durch einen nachfolgenden .update()
Aufruf nicht auf die richtige Anzahl von Funktionen aktualisiert.
Die Übergabe eines expliziten Werts für num_feature
behebt jedoch den Segmentierungsfehler:
booster_ = xgboost.Booster({'objective': 'reg:linear', 'num_feature': dtrain.num_col()})
Ich denke, dass xgboost.Booster()
eine Warnung ausgeben sollte, wenn entweder cache=()
leer ist oder
'num_feature'
wird nicht explizit im params
Argument festgelegt.
Hilfreichster Kommentar
Ich habe herausgefunden, was die Wurzel des Problems war. Es stellte sich heraus, dass durch Anrufen ein leerer Booster erstellt wurde
initialisiert den GBtree-Booster nur teilweise. Insbesondere der entscheidende Parameter
num_feature
ist standardmäßig auf 0 gesetzt und wird durch einen nachfolgenden
.update()
Aufruf nicht auf die richtige Anzahl von Funktionen aktualisiert.Die Übergabe eines expliziten Werts für
num_feature
behebt jedoch den Segmentierungsfehler:Ich denke, dass
xgboost.Booster()
eine Warnung ausgeben sollte, wenn entwedercache=()
leer ist oder'num_feature'
wird nicht explizit imparams
Argument festgelegt.