Skip to content

Commit

Permalink
fix a multi-thread bug in pred_contrib
Browse files Browse the repository at this point in the history
  • Loading branch information
guolinke committed Jan 24, 2018
1 parent 9323758 commit 61fb5ea
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 17 deletions.
3 changes: 2 additions & 1 deletion include/LightGBM/boosting.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,9 @@ class LIGHTGBM_EXPORT Boosting {
/*!
* \brief Initial work for the prediction
* \param num_iteration number of used iteration
* \param is_pred_contrib
*/
virtual void InitPredict(int num_iteration) = 0;
virtual void InitPredict(int num_iteration, bool is_pred_contrib) = 0;

/*!
* \brief Name of submodel
Expand Down
13 changes: 7 additions & 6 deletions include/LightGBM/tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ class Tree {
(*decision_type) |= (input << 2);
}

void RecomputeMaxDepth();

private:

std::string NumericalDecisionIfElse(int node) const;
Expand Down Expand Up @@ -313,8 +315,6 @@ class Tree {

double ExpectedValue() const;

int MaxDepth();

/*! \brief This is used fill in leaf_depth_ after reloading a model*/
inline void RecomputeLeafDepths(int node = 0, int depth = 0);

Expand Down Expand Up @@ -390,6 +390,7 @@ class Tree {
/*! \brief Depth for leaves */
std::vector<int> leaf_depth_;
double shrinkage_;
int max_depth_;
};

inline void Tree::Split(int leaf, int feature, int real_feature,
Expand Down Expand Up @@ -468,10 +469,10 @@ inline void Tree::PredictContrib(const double* feature_values, int num_features,
output[num_features] += ExpectedValue();
// Run the recursion with preallocated space for the unique path data
if (num_leaves_ > 1) {
const int max_path_len = MaxDepth() + 1;
PathElement *unique_path_data = new PathElement[(max_path_len*(max_path_len + 1)) / 2];
TreeSHAP(feature_values, output, 0, 0, unique_path_data, 1, 1, -1);
delete[] unique_path_data;
CHECK(max_depth_ >= 0);
const int max_path_len = max_depth_ + 1;
std::vector<PathElement> unique_path_data(max_path_len*(max_path_len + 1) / 2);
TreeSHAP(feature_values, output, 0, 0, unique_path_data.data(), 1, 1, -1);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/application/predictor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class Predictor {
{
num_threads_ = omp_get_num_threads();
}
boosting->InitPredict(num_iteration);
boosting->InitPredict(num_iteration, is_predict_contrib);
boosting_ = boosting;
num_pred_one_row_ = boosting_->NumPredictOneRow(num_iteration, is_predict_leaf_index, is_predict_contrib);
num_feature_ = boosting_->MaxFeatureIdx() + 1;
Expand Down
8 changes: 7 additions & 1 deletion src/boosting/gbdt.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,11 +291,17 @@ class GBDT : public GBDTBase {
*/
inline int NumberOfClasses() const override { return num_class_; }

inline void InitPredict(int num_iteration) override {
inline void InitPredict(int num_iteration, bool is_pred_contrib) override {
num_iteration_for_pred_ = static_cast<int>(models_.size()) / num_tree_per_iteration_;
if (num_iteration > 0) {
num_iteration_for_pred_ = std::min(num_iteration, num_iteration_for_pred_);
}
if (is_pred_contrib) {
#pragma omp parallel for schedule(static)
for (int i = 0; i < static_cast<int>(models_.size()); ++i) {
models_[i]->RecomputeMaxDepth();
}
}
}

inline double GetLeafValue(int tree_idx, int leaf_idx) const override {
Expand Down
22 changes: 14 additions & 8 deletions src/io/tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Tree::Tree(int max_leaves)
num_cat_ = 0;
cat_boundaries_.push_back(0);
cat_boundaries_inner_.push_back(0);
max_depth_ = -1;
}

Tree::~Tree() {
Expand Down Expand Up @@ -584,6 +585,7 @@ Tree::Tree(const char* str, size_t* used_len) {
} else {
shrinkage_ = 1.0f;
}
max_depth_ = -1;
}

void Tree::ExtendPath(PathElement *unique_path, int unique_depth,
Expand Down Expand Up @@ -652,7 +654,7 @@ void Tree::TreeSHAP(const double *feature_values, double *phi,
double parent_one_fraction, int parent_feature_index) const {

// extend the unique path
PathElement *unique_path = parent_unique_path + unique_depth;
PathElement* unique_path = parent_unique_path + unique_depth;
if (unique_depth > 0) std::copy(parent_unique_path, parent_unique_path + unique_depth, unique_path);
ExtendPath(unique_path, unique_depth, parent_zero_fraction,
parent_one_fraction, parent_feature_index);
Expand Down Expand Up @@ -706,14 +708,18 @@ double Tree::ExpectedValue() const {
return exp_value;
}

int Tree::MaxDepth() {
if (leaf_depth_.size() == 0) RecomputeLeafDepths();
if (num_leaves_ == 1) return 0;
int max_depth = 0;
for (int i = 0; i < num_leaves(); ++i) {
if (max_depth < leaf_depth_[i]) max_depth = leaf_depth_[i];
void Tree::RecomputeMaxDepth() {
if (num_leaves_ == 1) {
max_depth_ = 0;
} else {
if (leaf_depth_.size() == 0) {
RecomputeLeafDepths(0, 0);
}
max_depth_ = leaf_depth_[0];
for (int i = 1; i < num_leaves(); ++i) {
if (max_depth_ < leaf_depth_[i]) max_depth_ = leaf_depth_[i];
}
}
return max_depth;
}

} // namespace LightGBM

0 comments on commit 61fb5ea

Please sign in to comment.