Fix race condition in CPU shap. (#7050)
This commit is contained in:
@@ -213,6 +213,32 @@ void PredictBatchByBlockOfRowsKernel(
|
||||
});
|
||||
}
|
||||
|
||||
float FillNodeMeanValues(RegTree const *tree, bst_node_t nidx, std::vector<float> *mean_values) {
|
||||
bst_float result;
|
||||
auto &node = (*tree)[nidx];
|
||||
auto &node_mean_values = *mean_values;
|
||||
if (node.IsLeaf()) {
|
||||
result = node.LeafValue();
|
||||
} else {
|
||||
result = FillNodeMeanValues(tree, node.LeftChild(), mean_values) *
|
||||
tree->Stat(node.LeftChild()).sum_hess;
|
||||
result += FillNodeMeanValues(tree, node.RightChild(), mean_values) *
|
||||
tree->Stat(node.RightChild()).sum_hess;
|
||||
result /= tree->Stat(nidx).sum_hess;
|
||||
}
|
||||
node_mean_values[nidx] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
void FillNodeMeanValues(RegTree const* tree, std::vector<float>* mean_values) {
|
||||
size_t num_nodes = tree->param.num_nodes;
|
||||
if (mean_values->size() == num_nodes) {
|
||||
return;
|
||||
}
|
||||
mean_values->resize(num_nodes);
|
||||
FillNodeMeanValues(tree, 0, mean_values);
|
||||
}
|
||||
|
||||
class CPUPredictor : public Predictor {
|
||||
protected:
|
||||
// init thread buffers
|
||||
@@ -396,9 +422,10 @@ class CPUPredictor : public Predictor {
|
||||
}
|
||||
}
|
||||
|
||||
void PredictContribution(DMatrix* p_fmat, HostDeviceVector<float>* out_contribs,
|
||||
const gbm::GBTreeModel& model, uint32_t ntree_limit,
|
||||
std::vector<bst_float>* tree_weights,
|
||||
void PredictContribution(DMatrix *p_fmat,
|
||||
HostDeviceVector<float> *out_contribs,
|
||||
const gbm::GBTreeModel &model, uint32_t ntree_limit,
|
||||
std::vector<bst_float> const *tree_weights,
|
||||
bool approximate, int condition,
|
||||
unsigned condition_feature) const override {
|
||||
const int nthread = omp_get_max_threads();
|
||||
@@ -421,8 +448,9 @@ class CPUPredictor : public Predictor {
|
||||
// allocated one
|
||||
std::fill(contribs.begin(), contribs.end(), 0);
|
||||
// initialize tree node mean values
|
||||
std::vector<std::vector<float>> mean_values(ntree_limit);
|
||||
common::ParallelFor(bst_omp_uint(ntree_limit), [&](bst_omp_uint i) {
|
||||
model.trees[i]->FillNodeMeanValues();
|
||||
FillNodeMeanValues(model.trees[i].get(), &(mean_values[i]));
|
||||
});
|
||||
const std::vector<bst_float>& base_margin = info.base_margin_.HostVector();
|
||||
// start collecting the contributions
|
||||
@@ -443,19 +471,23 @@ class CPUPredictor : public Predictor {
|
||||
feats.Fill(page[i]);
|
||||
// calculate contributions
|
||||
for (unsigned j = 0; j < ntree_limit; ++j) {
|
||||
auto *tree_mean_values = &mean_values.at(j);
|
||||
std::fill(this_tree_contribs.begin(), this_tree_contribs.end(), 0);
|
||||
if (model.tree_info[j] != gid) {
|
||||
continue;
|
||||
}
|
||||
if (!approximate) {
|
||||
model.trees[j]->CalculateContributions(feats, &this_tree_contribs[0],
|
||||
condition, condition_feature);
|
||||
model.trees[j]->CalculateContributions(
|
||||
feats, tree_mean_values, &this_tree_contribs[0], condition,
|
||||
condition_feature);
|
||||
} else {
|
||||
model.trees[j]->CalculateContributionsApprox(feats, &this_tree_contribs[0]);
|
||||
model.trees[j]->CalculateContributionsApprox(
|
||||
feats, tree_mean_values, &this_tree_contribs[0]);
|
||||
}
|
||||
for (size_t ci = 0 ; ci < ncolumns ; ++ci) {
|
||||
p_contribs[ci] += this_tree_contribs[ci] *
|
||||
(tree_weights == nullptr ? 1 : (*tree_weights)[j]);
|
||||
for (size_t ci = 0; ci < ncolumns; ++ci) {
|
||||
p_contribs[ci] +=
|
||||
this_tree_contribs[ci] *
|
||||
(tree_weights == nullptr ? 1 : (*tree_weights)[j]);
|
||||
}
|
||||
}
|
||||
feats.Drop(page[i]);
|
||||
@@ -470,10 +502,11 @@ class CPUPredictor : public Predictor {
|
||||
}
|
||||
}
|
||||
|
||||
void PredictInteractionContributions(DMatrix* p_fmat, HostDeviceVector<bst_float>* out_contribs,
|
||||
const gbm::GBTreeModel& model, unsigned ntree_limit,
|
||||
std::vector<bst_float>* tree_weights,
|
||||
bool approximate) const override {
|
||||
void PredictInteractionContributions(
|
||||
DMatrix *p_fmat, HostDeviceVector<bst_float> *out_contribs,
|
||||
const gbm::GBTreeModel &model, unsigned ntree_limit,
|
||||
std::vector<bst_float> const *tree_weights,
|
||||
bool approximate) const override {
|
||||
const MetaInfo& info = p_fmat->Info();
|
||||
const int ngroup = model.learner_model_param->num_output_group;
|
||||
size_t const ncolumns = model.learner_model_param->num_feature;
|
||||
|
||||
Reference in New Issue
Block a user