Skip to content

Commit 9a9042f

Browse files
bugfix
1 parent f0928ea commit 9a9042f

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

cpp/APLRRegressor.h

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class APLRRegressor
5050
bool pruning_was_done_in_the_current_boosting_step;
5151
MatrixXd other_data_train;
5252
MatrixXd other_data_validation;
53+
bool model_has_changed_in_this_boosting_step;
5354

5455
void validate_input_to_fit(const MatrixXd &X, const VectorXd &y, const VectorXd &sample_weight, const std::vector<std::string> &X_names,
5556
const std::vector<size_t> &validation_set_indexes, const std::vector<size_t> &prioritized_predictors_indexes,
@@ -620,9 +621,6 @@ void APLRRegressor::initialize(const std::vector<size_t> &prioritized_predictors
620621
terms.clear();
621622
terms.reserve(X_train.cols() * reserved_terms_times_num_x);
622623

623-
intercept = 0;
624-
intercept_steps = VectorXd::Constant(m, 0);
625-
626624
terms_eligible_current.reserve(X_train.cols() * reserved_terms_times_num_x);
627625
size_t X_train_cols{static_cast<size_t>(X_train.cols())};
628626
for (size_t i = 0; i < X_train_cols; ++i)
@@ -659,9 +657,11 @@ void APLRRegressor::initialize(const std::vector<size_t> &prioritized_predictors
659657
legal_interaction_combination = remove_duplicate_elements_from_vector(legal_interaction_combination);
660658
}
661659

662-
linear_predictor_current = VectorXd::Constant(y_train.size(), intercept);
663-
linear_predictor_null_model = linear_predictor_current;
664-
linear_predictor_current_validation = VectorXd::Constant(y_validation.size(), intercept);
660+
intercept = 0.0;
661+
intercept_steps = VectorXd::Constant(m, 0.0);
662+
linear_predictor_current = VectorXd::Constant(y_train.size(), 0.0);
663+
linear_predictor_null_model = VectorXd::Constant(y_train.size(), 0.0);
664+
linear_predictor_current_validation = VectorXd::Constant(y_validation.size(), 0.0);
665665
predictions_current = transform_linear_predictor_to_predictions(linear_predictor_current, link_function, calculate_custom_transform_linear_predictor_to_predictions_function);
666666
predictions_current_validation = transform_linear_predictor_to_predictions(linear_predictor_current_validation, link_function, calculate_custom_transform_linear_predictor_to_predictions_function);
667667

@@ -809,6 +809,7 @@ void APLRRegressor::execute_boosting_steps()
809809

810810
void APLRRegressor::execute_boosting_step(size_t boosting_step)
811811
{
812+
model_has_changed_in_this_boosting_step = false;
812813
update_intercept(boosting_step);
813814
bool prioritize_predictors{!abort_boosting && prioritized_predictors_indexes.size() > 0};
814815
if (prioritize_predictors)
@@ -837,6 +838,14 @@ void APLRRegressor::execute_boosting_step(size_t boosting_step)
837838
prune_terms(boosting_step);
838839
}
839840
update_coefficient_steps(boosting_step);
841+
if (!model_has_changed_in_this_boosting_step)
842+
{
843+
abort_boosting = true;
844+
if (verbosity >= 1)
845+
{
846+
std::cout << "No further reduction in training loss was possible. Terminating the boosting procedure.\n";
847+
}
848+
}
840849
if (abort_boosting)
841850
return;
842851
update_term_eligibility();
@@ -850,6 +859,8 @@ void APLRRegressor::update_intercept(size_t boosting_step)
850859
intercept_update = v * neg_gradient_current.mean();
851860
else
852861
intercept_update = v * (neg_gradient_current.array() * sample_weight_train.array()).sum() / sample_weight_train.array().sum();
862+
if (model_has_changed_in_this_boosting_step == false)
863+
model_has_changed_in_this_boosting_step = !is_approximately_equal(intercept_update, 0.0);
853864
linear_predictor_update = VectorXd::Constant(neg_gradient_current.size(), intercept_update);
854865
linear_predictor_update_validation = VectorXd::Constant(y_validation.size(), intercept_update);
855866
update_linear_predictor_and_predictions();
@@ -1164,6 +1175,8 @@ void APLRRegressor::select_the_best_term_and_update_errors(size_t boosting_step)
11641175
if (no_term_was_selected)
11651176
return;
11661177

1178+
if (model_has_changed_in_this_boosting_step == false)
1179+
model_has_changed_in_this_boosting_step = !is_approximately_equal(terms_eligible_current[best_term_index].coefficient, 0.0);
11671180
linear_predictor_update = terms_eligible_current[best_term_index].calculate_contribution_to_linear_predictor(X_train);
11681181
linear_predictor_update_validation = terms_eligible_current[best_term_index].calculate_contribution_to_linear_predictor(X_validation);
11691182
update_linear_predictor_and_predictions();
@@ -1276,6 +1289,7 @@ void APLRRegressor::prune_terms(size_t boosting_step)
12761289
} while (std::islessequal(new_error, best_error) && terms_pruned < terms.size());
12771290
if (terms_pruned > 0)
12781291
{
1292+
model_has_changed_in_this_boosting_step = true;
12791293
remove_ineligibility();
12801294
if (verbosity >= 2)
12811295
{

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
setuptools.setup(
1717
name="aplr",
18-
version="7.5.0",
18+
version="7.5.1",
1919
description="Automatic Piecewise Linear Regression",
2020
ext_modules=[sfc_module],
2121
author="Mathias von Ottenbreit",

0 commit comments

Comments
 (0)