@@ -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
810810void 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 {
0 commit comments