Commit eb52262b authored by olofer's avatar olofer Committed by Guolin Ke
Browse files

Customized average fixes (nullptr and network) (#739)

* Created objectives and metrics xentropy and xentropy1

* Some coment and code cleanup.

* Added Kullback-Leibler version of metric. Changed some warning messages.

* Fixed sign error in KL-divergence calc.

* Removed __PRETTY_FUNCTION__.

* Fixed better name for alternative xentropy parameterization.
Documented details on the objectives / metrics in code comments.

* Common code for label interval checks. Cleanups.

* Use common utility for various weight property checks.

* Added code for customizable initial average to boost from.

* Fixed spelling error in aliases.

* Fixed nullptr check error in custom average.

* Added network code for customized init score.

* Restructured so that "standard" and "custom" init auto scores share aux.
function.

* Updated name for aux. automatic initial score fetcher.
parent 1542764d
...@@ -393,13 +393,30 @@ void GBDT::UpdateScoreOutOfBag(const Tree* tree, const int cur_tree_id) { ...@@ -393,13 +393,30 @@ void GBDT::UpdateScoreOutOfBag(const Tree* tree, const int cur_tree_id) {
#endif #endif
} }
double LabelAverage(const float* label, data_size_t num_data) { /* If the custom "average" is implemented it will be used inplace of the label average (if enabled)
double sum_label = 0.0f; *
#pragma omp parallel for schedule(static) reduction(+:sum_label) * An improvement to this is to have options to explicitly choose
for (data_size_t i = 0; i < num_data; ++i) { * (i) standard average
sum_label += label[i]; * (ii) custom average if available
* (iii) any user defined scalar bias (e.g. using a new option "init_score" that overrides (i) and (ii) )
*
* (i) and (ii) could be selected as say "auto_init_score" = 0 or 1 etc..
*
*/
double ObtainAutomaticInitialScore(const ObjectiveFunction* objf, const float* label, data_size_t num_data) {
double init_score = 0.0f;
bool got_custom = false;
if (objf != nullptr) {
got_custom = objf->GetCustomAverage(&init_score);
}
if (!got_custom) {
double sum_label = 0.0f;
#pragma omp parallel for schedule(static) reduction(+:sum_label)
for (data_size_t i = 0; i < num_data; ++i) {
sum_label += label[i];
}
init_score = sum_label / num_data;
} }
double init_score = sum_label / num_data;
if (Network::num_machines() > 1) { if (Network::num_machines() > 1) {
double global_init_score = 0.0f; double global_init_score = 0.0f;
Network::Allreduce(reinterpret_cast<char*>(&init_score), Network::Allreduce(reinterpret_cast<char*>(&init_score),
...@@ -426,20 +443,15 @@ double LabelAverage(const float* label, data_size_t num_data) { ...@@ -426,20 +443,15 @@ double LabelAverage(const float* label, data_size_t num_data) {
} }
bool GBDT::TrainOneIter(const score_t* gradient, const score_t* hessian, bool is_eval) { bool GBDT::TrainOneIter(const score_t* gradient, const score_t* hessian, bool is_eval) {
// boosting from average prediction. It doesn't work well for classification, remove it for now. // boosting from average label; or customized "average" if implemented for the current objective
if (models_.empty() if (models_.empty()
&& gbdt_config_->boost_from_average && gbdt_config_->boost_from_average
&& !train_score_updater_->has_init_score() && !train_score_updater_->has_init_score()
&& num_class_ <= 1 && num_class_ <= 1
&& objective_function_ != nullptr && objective_function_ != nullptr
&& objective_function_->BoostFromAverage()) { && objective_function_->BoostFromAverage()) {
double init_score = 0.0f; auto label = train_data_->metadata().label();
// First try to poll the optional custom average score calculation for the specific objective double init_score = ObtainAutomaticInitialScore(objective_function_, label, num_data_);
if (!objective_function_->GetCustomAverage(&init_score)) {
// otherwise compute a standard label average
auto label = train_data_->metadata().label();
init_score = LabelAverage(label, num_data_);
}
std::unique_ptr<Tree> new_tree(new Tree(2)); std::unique_ptr<Tree> new_tree(new Tree(2));
new_tree->Split(0, 0, BinType::NumericalBin, 0, 0, 0, init_score, init_score, 0, 0, -1, 0, 0, 0); new_tree->Split(0, 0, BinType::NumericalBin, 0, 0, 0, init_score, init_score, 0, 0, -1, 0, 0, 0);
train_score_updater_->AddScore(init_score, 0); train_score_updater_->AddScore(init_score, 0);
......
...@@ -110,7 +110,7 @@ public: ...@@ -110,7 +110,7 @@ public:
if (initscore == nullptr) return false; if (initscore == nullptr) return false;
double suml = 0.0f; double suml = 0.0f;
double sumw = 0.0f; double sumw = 0.0f;
if (weights_ == nullptr) { if (weights_ != nullptr) {
for (data_size_t i = 0; i < num_data_; ++i) { for (data_size_t i = 0; i < num_data_; ++i) {
suml += label_[i] * weights_[i]; suml += label_[i] * weights_[i];
sumw += weights_[i]; sumw += weights_[i];
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment