Medial Code Documentation
Loading...
Searching...
No Matches
gbtree.h
1
7#ifndef XGBOOST_GBM_GBTREE_H_
8#define XGBOOST_GBM_GBTREE_H_
9
10#include <dmlc/omp.h>
11
12#include <algorithm>
13#include <cstdint> // std::int32_t
14#include <map>
15#include <memory>
16#include <string>
17#include <unordered_map>
18#include <utility>
19#include <vector>
20
21#include "../common/common.h"
22#include "../common/timer.h"
23#include "../tree/param.h" // TrainParam
24#include "gbtree_model.h"
25#include "xgboost/base.h"
26#include "xgboost/data.h"
27#include "xgboost/gbm.h"
29#include "xgboost/json.h"
30#include "xgboost/logging.h"
31#include "xgboost/parameter.h"
32#include "xgboost/predictor.h"
34
35namespace xgboost {
36enum class TreeMethod : int {
37 kAuto = 0, kApprox = 1, kExact = 2, kHist = 3,
38 kGPUHist = 5
39};
40
41// boosting process types
42enum class TreeProcessType : int {
43 kDefault = 0,
44 kUpdate = 1
45};
46} // namespace xgboost
47
48DECLARE_FIELD_ENUM_CLASS(xgboost::TreeMethod);
49DECLARE_FIELD_ENUM_CLASS(xgboost::TreeProcessType);
50
51namespace xgboost::gbm {
53struct GBTreeTrainParam : public XGBoostParameter<GBTreeTrainParam> {
55 std::string updater_seq;
57 TreeProcessType process_type;
58 // tree construction method
59 TreeMethod tree_method;
60 // declare parameters
61 DMLC_DECLARE_PARAMETER(GBTreeTrainParam) {
62 DMLC_DECLARE_FIELD(updater_seq).describe("Tree updater sequence.").set_default("");
63 DMLC_DECLARE_FIELD(process_type)
64 .set_default(TreeProcessType::kDefault)
65 .add_enum("default", TreeProcessType::kDefault)
66 .add_enum("update", TreeProcessType::kUpdate)
67 .describe("Whether to run the normal boosting process that creates new trees,"\
68 " or to update the trees in an existing model.");
69 DMLC_DECLARE_ALIAS(updater_seq, updater);
70 DMLC_DECLARE_FIELD(tree_method)
71 .set_default(TreeMethod::kAuto)
72 .add_enum("auto", TreeMethod::kAuto)
73 .add_enum("approx", TreeMethod::kApprox)
74 .add_enum("exact", TreeMethod::kExact)
75 .add_enum("hist", TreeMethod::kHist)
76 .add_enum("gpu_hist", TreeMethod::kGPUHist)
77 .describe("Choice of tree construction method.");
78 }
79};
80
82struct DartTrainParam : public XGBoostParameter<DartTrainParam> {
88 float rate_drop;
92 float skip_drop;
93 // declare parameters
94 DMLC_DECLARE_PARAMETER(DartTrainParam) {
95 DMLC_DECLARE_FIELD(sample_type)
96 .set_default(0)
97 .add_enum("uniform", 0)
98 .add_enum("weighted", 1)
99 .describe("Different types of sampling algorithm.");
100 DMLC_DECLARE_FIELD(normalize_type)
101 .set_default(0)
102 .add_enum("tree", 0)
103 .add_enum("forest", 1)
104 .describe("Different types of normalization algorithm.");
105 DMLC_DECLARE_FIELD(rate_drop)
106 .set_range(0.0f, 1.0f)
107 .set_default(0.0f)
108 .describe("Fraction of trees to drop during the dropout.");
109 DMLC_DECLARE_FIELD(one_drop)
110 .set_default(false)
111 .describe("Whether at least one tree should always be dropped during the dropout.");
112 DMLC_DECLARE_FIELD(skip_drop)
113 .set_range(0.0f, 1.0f)
114 .set_default(0.0f)
115 .describe("Probability of skipping the dropout during a boosting iteration.");
116 }
117};
118
119namespace detail {
120// From here on, layer becomes concrete trees.
121inline std::pair<bst_tree_t, bst_tree_t> LayerToTree(gbm::GBTreeModel const& model,
122 bst_layer_t begin, bst_layer_t end) {
123 CHECK(!model.iteration_indptr.empty());
124 end = end == 0 ? model.BoostedRounds() : end;
125 CHECK_LE(end, model.BoostedRounds()) << "Out of range for tree layers.";
126 bst_tree_t tree_begin = model.iteration_indptr[begin];
127 bst_tree_t tree_end = model.iteration_indptr[end];
128 if (model.trees.size() != 0) {
129 CHECK_LE(tree_begin, tree_end);
130 }
131 return {tree_begin, tree_end};
132}
133
134// Call fn for each pair of input output tree. Return true if index is out of bound.
135template <typename Func>
136bool SliceTrees(bst_layer_t begin, bst_layer_t end, bst_layer_t step, GBTreeModel const& model,
137 Func&& fn) {
138 end = end == 0 ? model.iteration_indptr.size() : end;
139 CHECK_GE(step, 1);
140 if (step > end - begin) {
141 return true;
142 }
143 if (end > model.BoostedRounds()) {
144 return true;
145 }
146
147 bst_layer_t n_layers = (end - begin) / step;
148 bst_layer_t out_l = 0;
149
150 for (bst_layer_t l = begin; l < end; l += step) {
151 auto [tree_begin, tree_end] = detail::LayerToTree(model, l, l + 1);
152 if (tree_end > static_cast<bst_tree_t>(model.trees.size())) {
153 return true;
154 }
155
156 for (bst_tree_t tree_idx = tree_begin; tree_idx < tree_end; ++tree_idx) {
157 fn(tree_idx, out_l);
158 }
159 ++out_l;
160 }
161
162 CHECK_EQ(out_l, n_layers);
163 return false;
164}
165} // namespace detail
166
167// gradient boosted trees
168class GBTree : public GradientBooster {
169 public:
170 explicit GBTree(LearnerModelParam const* booster_config, Context const* ctx)
171 : GradientBooster{ctx}, model_(booster_config, ctx_) {
172 monitor_.Init(__func__);
173 }
174
175 void Configure(Args const& cfg) override;
179 void UpdateTreeLeaf(DMatrix const* p_fmat, HostDeviceVector<float> const& predictions,
180 ObjFunction const* obj, std::int32_t group_idx,
181 std::vector<HostDeviceVector<bst_node_t>> const& node_position,
182 std::vector<std::unique_ptr<RegTree>>* p_trees);
186 void DoBoost(DMatrix* p_fmat, HostDeviceVector<GradientPair>* in_gpair,
187 PredictionCacheEntry* predt, ObjFunction const* obj) override;
188
189 [[nodiscard]] bool UseGPU() const override { return tparam_.tree_method == TreeMethod::kGPUHist; }
190
191 [[nodiscard]] GBTreeTrainParam const& GetTrainParam() const { return tparam_; }
192
193 void Load(dmlc::Stream* fi) override { model_.Load(fi); }
194 void Save(dmlc::Stream* fo) const override {
195 model_.Save(fo);
196 }
197
198 void LoadConfig(Json const& in) override;
199 void SaveConfig(Json* p_out) const override;
200
201 void SaveModel(Json* p_out) const override;
202 void LoadModel(Json const& in) override;
203
204 // slice the trees, out must be already allocated
205 void Slice(bst_layer_t begin, bst_layer_t end, bst_layer_t step, GradientBooster* out,
206 bool* out_of_bound) const override;
207
208 [[nodiscard]] std::int32_t BoostedRounds() const override { return this->model_.BoostedRounds(); }
209 [[nodiscard]] bool ModelFitted() const override {
210 return !model_.trees.empty() || !model_.trees_to_update.empty();
211 }
212
213 void PredictBatchImpl(DMatrix* p_fmat, PredictionCacheEntry* out_preds, bool is_training,
214 bst_layer_t layer_begin, bst_layer_t layer_end) const;
215
216 void PredictBatch(DMatrix* p_fmat, PredictionCacheEntry* out_preds, bool training,
217 bst_layer_t layer_begin, bst_layer_t layer_end) override;
218
219 void InplacePredict(std::shared_ptr<DMatrix> p_m, float missing, PredictionCacheEntry* out_preds,
220 bst_layer_t layer_begin, bst_layer_t layer_end) const override;
221
222 void FeatureScore(std::string const& importance_type, common::Span<int32_t const> trees,
223 std::vector<bst_feature_t>* features,
224 std::vector<float>* scores) const override {
225 // Because feature with no importance doesn't appear in the return value so
226 // we need to set up another pair of vectors to store the values during
227 // computation.
228 std::vector<size_t> split_counts(this->model_.learner_model_param->num_feature, 0);
229 std::vector<float> gain_map(this->model_.learner_model_param->num_feature, 0);
230 std::vector<int32_t> tree_idx;
231 if (trees.empty()) {
232 tree_idx.resize(this->model_.trees.size());
233 std::iota(tree_idx.begin(), tree_idx.end(), 0);
234 trees = common::Span<int32_t const>(tree_idx);
235 }
236
237 auto total_n_trees = model_.trees.size();
238 auto add_score = [&](auto fn) {
239 for (auto idx : trees) {
240 CHECK_LE(idx, total_n_trees) << "Invalid tree index.";
241 auto const& p_tree = model_.trees[idx];
242 p_tree->WalkTree([&](bst_node_t nidx) {
243 auto const& node = (*p_tree)[nidx];
244 if (!node.IsLeaf()) {
245 split_counts[node.SplitIndex()]++;
246 fn(p_tree, nidx, node.SplitIndex());
247 }
248 return true;
249 });
250 }
251 };
252
253 if (importance_type == "weight") {
254 add_score([&](auto const&, bst_node_t, bst_feature_t split) {
255 gain_map[split] = split_counts[split];
256 });
257 } else if (importance_type == "gain" || importance_type == "total_gain") {
258 add_score([&](auto const &p_tree, bst_node_t nidx, bst_feature_t split) {
259 gain_map[split] += p_tree->Stat(nidx).loss_chg;
260 });
261 } else if (importance_type == "cover" || importance_type == "total_cover") {
262 add_score([&](auto const &p_tree, bst_node_t nidx, bst_feature_t split) {
263 gain_map[split] += p_tree->Stat(nidx).sum_hess;
264 });
265 } else {
266 LOG(FATAL)
267 << "Unknown feature importance type, expected one of: "
268 << R"({"weight", "total_gain", "total_cover", "gain", "cover"}, got: )"
269 << importance_type;
270 }
271 if (importance_type == "gain" || importance_type == "cover") {
272 for (size_t i = 0; i < gain_map.size(); ++i) {
273 gain_map[i] /= std::max(1.0f, static_cast<float>(split_counts[i]));
274 }
275 }
276
277 features->clear();
278 scores->clear();
279 for (size_t i = 0; i < split_counts.size(); ++i) {
280 if (split_counts[i] != 0) {
281 features->push_back(i);
282 scores->push_back(gain_map[i]);
283 }
284 }
285 }
286
287 void PredictInstance(const SparsePage::Inst& inst, std::vector<bst_float>* out_preds,
288 uint32_t layer_begin, uint32_t layer_end) override {
289 std::uint32_t _, tree_end;
290 std::tie(_, tree_end) = detail::LayerToTree(model_, layer_begin, layer_end);
291 cpu_predictor_->PredictInstance(inst, out_preds, model_, tree_end);
292 }
293
294 void PredictLeaf(DMatrix* p_fmat,
295 HostDeviceVector<bst_float>* out_preds,
296 uint32_t layer_begin, uint32_t layer_end) override {
297 auto [tree_begin, tree_end] = detail::LayerToTree(model_, layer_begin, layer_end);
298 CHECK_EQ(tree_begin, 0) << "Predict leaf supports only iteration end: (0, "
299 "n_iteration), use model slicing instead.";
300 this->GetPredictor(false)->PredictLeaf(p_fmat, out_preds, model_, tree_end);
301 }
302
304 bst_layer_t layer_begin, bst_layer_t layer_end,
305 bool approximate) override {
306 auto [tree_begin, tree_end] = detail::LayerToTree(model_, layer_begin, layer_end);
307 CHECK_EQ(tree_begin, 0) << "Predict contribution supports only iteration end: (0, "
308 "n_iteration), using model slicing instead.";
309 this->GetPredictor(false)->PredictContribution(p_fmat, out_contribs, model_, tree_end, nullptr,
310 approximate);
311 }
312
313 void PredictInteractionContributions(DMatrix* p_fmat, HostDeviceVector<float>* out_contribs,
314 bst_layer_t layer_begin, bst_layer_t layer_end,
315 bool approximate) override {
316 auto [tree_begin, tree_end] = detail::LayerToTree(model_, layer_begin, layer_end);
317 CHECK_EQ(tree_begin, 0) << "Predict interaction contribution supports only iteration end: (0, "
318 "n_iteration), using model slicing instead.";
319 this->GetPredictor(false)->PredictInteractionContributions(p_fmat, out_contribs, model_,
320 tree_end, nullptr, approximate);
321 }
322
323 [[nodiscard]] std::vector<std::string> DumpModel(const FeatureMap& fmap, bool with_stats,
324 std::string format) const override {
325 return model_.DumpModel(fmap, with_stats, this->ctx_->Threads(), format);
326 }
327
328 protected:
329 void BoostNewTrees(HostDeviceVector<GradientPair>* gpair, DMatrix* p_fmat, int bst_group,
330 std::vector<HostDeviceVector<bst_node_t>>* out_position,
331 std::vector<std::unique_ptr<RegTree>>* ret);
332
333 [[nodiscard]] std::unique_ptr<Predictor> const& GetPredictor(
334 bool is_training, HostDeviceVector<float> const* out_pred = nullptr,
335 DMatrix* f_dmat = nullptr) const;
336
337 // commit new trees all at once
338 virtual void CommitModel(TreesOneIter&& new_trees);
339
340 // --- data structure ---
341 GBTreeModel model_;
342 // training parameter
343 GBTreeTrainParam tparam_;
344 // Tree training parameter
345 tree::TrainParam tree_param_;
346 bool specified_updater_ {false};
347 // the updaters that can be applied to each of tree
348 std::vector<std::unique_ptr<TreeUpdater>> updaters_;
349 // Predictors
350 std::unique_ptr<Predictor> cpu_predictor_;
351 std::unique_ptr<Predictor> gpu_predictor_{nullptr};
352#if defined(XGBOOST_USE_ONEAPI)
353 std::unique_ptr<Predictor> oneapi_predictor_;
354#endif // defined(XGBOOST_USE_ONEAPI)
355 common::Monitor monitor_;
356};
357
358} // namespace xgboost::gbm
359
360#endif // XGBOOST_GBM_GBTREE_H_
interface of stream I/O for serialization
Definition io.h:30
Internal data structured used by XGBoost during training.
Definition data.h:509
Feature map data structure to help text model dump. TODO(tqchen) consider make it even more lightweig...
Definition feature_map.h:22
interface of gradient boosting model.
Definition gbm.h:37
Definition host_device_vector.h:87
Data structure representing JSON format.
Definition json.h:357
interface of objective function
Definition objective.h:29
common::Span< Entry const > Inst
an instance of sparse vector in the batch
Definition data.h:338
span class implementation, based on ISO++20 span<T>. The interface should be the same.
Definition span.h:424
Definition gbtree.h:168
void UpdateTreeLeaf(DMatrix const *p_fmat, HostDeviceVector< float > const &predictions, ObjFunction const *obj, std::int32_t group_idx, std::vector< HostDeviceVector< bst_node_t > > const &node_position, std::vector< std::unique_ptr< RegTree > > *p_trees)
Optionally update the leaf value.
Definition gbtree.cc:174
bool UseGPU() const override
Whether the current booster uses GPU.
Definition gbtree.h:189
void DoBoost(DMatrix *p_fmat, HostDeviceVector< GradientPair > *in_gpair, PredictionCacheEntry *predt, ObjFunction const *obj) override
Carry out one iteration of boosting.
Definition gbtree.cc:199
bool ModelFitted() const override
Whether the model has already been trained.
Definition gbtree.h:209
void PredictContribution(DMatrix *p_fmat, HostDeviceVector< float > *out_contribs, bst_layer_t layer_begin, bst_layer_t layer_end, bool approximate) override
feature contributions to individual predictions; the output will be a vector of length (nfeats + 1) *...
Definition gbtree.h:303
void PredictBatch(DMatrix *p_fmat, PredictionCacheEntry *out_preds, bool training, bst_layer_t layer_begin, bst_layer_t layer_end) override
Generate predictions for given feature matrix.
Definition gbtree.cc:520
void SaveConfig(Json *p_out) const override
Save configuration to JSON object.
Definition gbtree.cc:388
std::int32_t BoostedRounds() const override
Return number of boosted rounds.
Definition gbtree.h:208
void Load(dmlc::Stream *fi) override
load model from stream
Definition gbtree.h:193
void LoadModel(Json const &in) override
load the model from a JSON object
Definition gbtree.cc:416
void Save(dmlc::Stream *fo) const override
save model to stream.
Definition gbtree.h:194
void LoadConfig(Json const &in) override
Load configuration from JSON object.
Definition gbtree.cc:338
void InplacePredict(std::shared_ptr< DMatrix > p_m, float missing, PredictionCacheEntry *out_preds, bst_layer_t layer_begin, bst_layer_t layer_end) const override
Inplace prediction.
Definition gbtree.cc:526
void SaveModel(Json *p_out) const override
saves the model config to a JSON object
Definition gbtree.cc:421
std::vector< std::string > DumpModel(const FeatureMap &fmap, bool with_stats, std::string format) const override
dump the model in the requested format
Definition gbtree.h:323
void Configure(Args const &cfg) override
Set the configuration of gradient boosting. User must call configure once before InitModel and Traini...
Definition gbtree.cc:90
void Slice(bst_layer_t begin, bst_layer_t end, bst_layer_t step, GradientBooster *out, bool *out_of_bound) const override
Slice a model using boosting index.
Definition gbtree.cc:429
Copyright 2014-2023 by XGBoost Contributors.
Copyright 2017-2023, XGBoost Contributors.
A device-and-host vector abstraction layer.
Copyright 2015-2023 by XGBoost Contributors.
Copyright 2015-2023 by XGBoost Contributors.
defines console logging options for xgboost. Use to enforce unified print behavior.
macro for using C++11 enum class as DMLC parameter
#define DECLARE_FIELD_ENUM_CLASS(EnumClass)
Specialization of FieldEntry for enum class (backed by int)
Definition parameter.h:50
detail namespace with internal helper functions
Definition json.hpp:249
Copyright 2019-2023, XGBoost Contributors.
Definition linear_updater.h:23
std::vector< TreesOneGroup > TreesOneIter
Container for all trees built (not update) for one iteration.
Definition gbtree_model.h:35
namespace of xgboost
Definition base.h:90
uint32_t bst_feature_t
Type for data column (feature) index.
Definition base.h:101
std::int32_t bst_node_t
Type for tree node index.
Definition base.h:112
std::int32_t bst_tree_t
Type for indexing trees.
Definition base.h:126
std::int32_t bst_layer_t
Type for indexing boosted layers.
Definition base.h:122
header to handle OpenMP compatibility issues
Copyright 2017-2023 by Contributors.
Runtime context for XGBoost.
Definition context.h:84
std::int32_t Threads() const
Returns the automatically chosen number of threads based on the nthread parameter and the system sett...
Definition context.cc:203
Basic model parameters, used to describe the booster.
Definition learner.h:291
bst_feature_t num_feature
The number of features.
Definition learner.h:303
Contains pointer to input matrix and associated cached predictions.
Definition predictor.h:30
Definition parameter.h:84
training parameters
Definition gbtree.h:82
int normalize_type
type of normalization algorithm
Definition gbtree.h:86
bool one_drop
whether at least one tree should always be dropped during the dropout
Definition gbtree.h:90
int sample_type
type of sampling algorithm
Definition gbtree.h:84
float skip_drop
probability of skipping the dropout during an iteration
Definition gbtree.h:92
float rate_drop
fraction of trees to drop during the dropout
Definition gbtree.h:88
Definition gbtree_model.h:84
std::vector< std::unique_ptr< RegTree > > trees_to_update
for the update process, a place to keep the initial trees
Definition gbtree_model.h:151
std::vector< std::unique_ptr< RegTree > > trees
vector of trees stored in the model
Definition gbtree_model.h:149
training parameters
Definition gbtree.h:53
TreeProcessType process_type
type of boosting process to run
Definition gbtree.h:57
std::string updater_seq
tree updater sequence
Definition gbtree.h:55
training parameters for regression tree
Definition param.h:28
Copyright 2014-2023 by XGBoost Contributors.