Replace the name num_output_group with the number of targets. - #12353
Replace the name num_output_group with the number of targets.#12353trivialfis wants to merge 4 commits into
num_output_group with the number of targets.#12353Conversation
51674eb to
34d4ade
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates XGBoost’s multi-output terminology and indexing to consistently use “targets” (n_targets) instead of “output groups” (previously derived from num_class / num_output_group), and replaces historical misuse of bst_group_t as a target index by using bst_target_t consistently across training, prediction, SHAP, C API shape handling, and tests.
Changes:
- Renames model/output dimension handling from
num_output_group/OutputLength()/Groups()ton_targets/NumTargets()(andNumTreeTargets()for vector-leaf trees). - Propagates the target-index type (
bst_target_t) through GBTree/GBLinear training, predictors (CPU/GPU), and SHAP implementations. - Updates C API prediction shape calculation and test utilities/docs to reflect target-based naming and behavior.
Reviewed changes
Copilot reviewed 40 out of 40 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/cpp/tree/test_tree_stat.cc | Fixes RegTree ctor arg type for number of features vs targets in tests. |
| tests/cpp/test_multi_target.cc | Updates learner API usage from Groups() to NumTargets() in tests. |
| tests/cpp/predictor/test_shap.cc | Aligns model-param construction and persisted metadata to target-based sizing. |
| tests/cpp/predictor/test_predictor.h | Updates helper to commit model groups using target indices. |
| tests/cpp/predictor/test_predictor.cc | Updates vector-leaf sizing APIs from leaf-length to tree-targets. |
| tests/cpp/helpers.h | Adjusts helper APIs/formatting to use n_targets and updated LearnerModelParam ctor. |
| src/predictor/predictor.cc | Switches output sizing/validation from output-groups to targets. |
| src/predictor/interpretability/shap.cu | Updates GPU SHAP dimensioning and indexing to use target count. |
| src/predictor/interpretability/shap.cc | Updates CPU SHAP dimensioning to use target count. |
| src/predictor/gpu_predictor.cu | Renames kernel params/indexing from groups to targets for prediction output. |
| src/predictor/gbtree_view.h | Stores n_targets in model view from LearnerModelParam::NumTargets(). |
| src/predictor/cpu_predictor.cc | Renames and retypes prediction dimensions from groups to targets. |
| src/objective/regression_obj.cu | Renames leaf-update parameter from group index to target index. |
| src/objective/quantile_obj.cu | Renames and applies target-index semantics in quantile leaf update. |
| src/objective/adaptive.h | Updates adaptive objective helpers to take bst_target_t for label/pred indexing. |
| src/objective/adaptive.cu | Updates CUDA adaptive leaf-update indexing to use target index naming/types. |
| src/objective/adaptive.cc | Updates CPU adaptive leaf-update indexing to use target index naming/types. |
| src/linear/updater_shotgun.cc | Renames group loops/indexing to target loops/indexing for linear training. |
| src/linear/updater_gpu_coordinate.cu | Updates GPU coordinate updater loops/sizes from groups to targets. |
| src/linear/updater_coordinate.cc | Updates CPU coordinate updater loops/sizes from groups to targets. |
| src/linear/coordinate_common.h | Renames params/docs and updates indexing math from groups to targets. |
| src/learner.cc | Introduces NumTargets() in legacy params and stores n_targets in model params. |
| src/gbm/gbtree.h | Updates GBTree APIs to use target_idx and TreesOneGroup consistently. |
| src/gbm/gbtree.cu | Updates GPU helper signatures/indexing from group to target semantics. |
| src/gbm/gbtree.cc | Updates boosting/pred-cache plumbing to use NumTargets()/NumTreeTargets(). |
| src/gbm/gbtree_model.h | Renames commit API to accept target_idx. |
| src/gbm/gbtree_model.cc | Updates tree-info indptr and commit logic to iterate over targets. |
| src/gbm/gblinear.cc | Updates prediction/contrib loops to iterate over targets. |
| src/gbm/gblinear_model.h | Updates linear model weight layout to be sized/indexed by targets. |
| src/data/data.cc | Renames reshape helper variable from groups to targets for meta matrices. |
| src/c_api/c_api.cu | Updates inplace predict shape calculation to use NumTargets(). |
| src/c_api/c_api.cc | Updates predict shape calculation to use NumTargets(). |
| src/c_api/c_api_utils.h | Renames CalcPredictShape params/docs and shapes to be target-based. |
| python-package/xgboost/testing/shared.py | Updates predict-leaf test validation naming from classes to targets. |
| python-package/xgboost/core.py | Updates user-facing docstring terminology from groups to targets. |
| include/xgboost/predictor.h | Updates predictor contribution-output doc to use n_targets. |
| include/xgboost/objective.h | Updates objective leaf-update doc/param naming to target_idx. |
| include/xgboost/learner.h | Replaces Groups() with NumTargets() and renames model param fields/APIs. |
| include/xgboost/gbm.h | Updates contribution-output doc to use n_targets. |
| demo/guide-python/model_parser.py | Updates demo parser to derive n_targets from num_class/num_target and improves CLI structure. |
Comments suppressed due to low confidence (2)
src/predictor/interpretability/shap.cc:482
- Same shadowing issue as above: the inner
n_targetshides the model-leveln_targets, soCHECK_EQ(n_targets, n_targets)is always true and does not validate that each multi-target tree matches the model target count.
src/gbm/gblinear.cc:260 - In prediction, the per-target margin falls back to
base_score(0)for all targets. This should use the currenttarget_idxso multi-target models with distinct base scores behave correctly.
// Loop over targets.
for (bst_target_t target_idx = 0; target_idx < n_targets; ++target_idx) {
float margin = (base_margin.Size() != 0) ? base_margin(ridx, target_idx) : base_score(0);
this->Pred(batch[i], &preds[ridx * n_targets], target_idx, margin);
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 41 out of 41 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/predictor/interpretability/shap.cc:482
- In the multi-target tree path, this check is now a tautology (
CHECK_EQ(n_targets, n_targets)), so it will never detect a mismatch between the tree’s target count and the model’s declared target count. This looks like a rename oversight fromn_groups->n_targets.
|
As a suggestion, could we establish the vocabulary first along these lines?
// K-output scalar-leaf model
NumOutputs() == K;
LeafOutputSize() == 1;
NumOutputBlocks() == K;
// K-output vector-leaf model
NumOutputs() == K;
LeafOutputSize() == K;
NumOutputBlocks() == 1;
// Single-output model
NumOutputs() == 1;
LeafOutputSize() == 1;
NumOutputBlocks() == 1;Here, NumOutputBlocks() == NumOutputs() / LeafOutputSize();
NumTreesPerIteration() ==
NumOutputBlocks() * num_parallel_tree;With this vocabulary, branches such as the one in auto const n_outputs = mparam.NumOutputs();
auto const leaf_output_size = mparam.LeafOutputSize();
auto const n_output_blocks = mparam.NumOutputBlocks();
CHECK_EQ(n_outputs, n_output_blocks * leaf_output_size);
for (output_block = 0; output_block < n_output_blocks; ++output_block) {
auto output_begin = output_block * leaf_output_size;
auto output_end = output_begin + leaf_output_size;
gradients = CopyGradients(all_gradients, output_begin, output_end);
for (parallel_tree = 0; parallel_tree < num_parallel_tree; ++parallel_tree) {
tree = BoostNewTree(gradients, leaf_output_size);
new_trees[output_block].push_back(tree);
}
}The scalar-leaf case naturally loops over K output blocks, while the vector-leaf case loops over one. |
|
Some areas that might be worth looking into after establishing the naming:
|
After the multi-output implementation, we have concepts for groups and targets, the group was derived from the
num_classparameter. In this PR, we unify them under then_targetsname.In addition, due to historical reasons, the
bst_group_tis misused as a target index. This PR usesbst_target_tconsistently.