Skip to content

Commit 25a18fa

Browse files
updating intercept gradually in each step
1 parent 3df7b6d commit 25a18fa

File tree

2 files changed

+58
-70
lines changed

2 files changed

+58
-70
lines changed

cpp/APLRRegressor.h

Lines changed: 57 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,8 @@ class APLRRegressor
3535
double neg_gradient_nullmodel_errors_sum;
3636
size_t best_term;
3737
double lowest_error_sum;
38-
double error_after_updating_intercept;
3938
VectorXd linear_predictor_update;
4039
VectorXd linear_predictor_update_validation;
41-
double intercept_test;
4240
size_t number_of_eligible_terms;
4341
std::vector<std::vector<size_t>> distributed_terms;
4442
std::vector<Term> interactions_to_consider;
@@ -64,7 +62,7 @@ class APLRRegressor
6462
void estimate_split_points_for_interactions_to_consider();
6563
void sort_errors_for_interactions_to_consider();
6664
void add_promising_interactions_and_select_the_best_one();
67-
void consider_updating_intercept();
65+
void update_intercept(size_t boosting_step);
6866
void select_the_best_term_and_update_errors(size_t boosting_step);
6967
void update_gradient_and_errors();
7068
void add_new_term(size_t boosting_step);
@@ -506,15 +504,30 @@ void APLRRegressor::execute_boosting_steps()
506504

507505
void APLRRegressor::execute_boosting_step(size_t boosting_step)
508506
{
507+
update_intercept(boosting_step);
509508
find_best_split_for_each_eligible_term();
510509
consider_interactions();
511-
consider_updating_intercept();
512510
select_the_best_term_and_update_errors(boosting_step);
513511
if(abort_boosting) return;
514512
update_term_eligibility();
515513
print_summary_after_boosting_step(boosting_step);
516514
}
517515

516+
void APLRRegressor::update_intercept(size_t boosting_step)
517+
{
518+
double intercept_update;
519+
if(sample_weight_train.size()==0)
520+
intercept_update=v*neg_gradient_current.mean();
521+
else
522+
intercept_update=v*(neg_gradient_current.array()*sample_weight_train.array()).sum()/sample_weight_train.array().sum();
523+
linear_predictor_update=VectorXd::Constant(neg_gradient_current.size(),intercept_update);
524+
linear_predictor_update_validation=VectorXd::Constant(y_validation.size(),intercept_update);
525+
intercept+=intercept_update;
526+
intercept_steps[boosting_step]=intercept;
527+
update_linear_predictor_and_predictors();
528+
update_gradient_and_errors();
529+
}
530+
518531
void APLRRegressor::find_best_split_for_each_eligible_term()
519532
{
520533
best_term=std::numeric_limits<size_t>::max();
@@ -713,78 +726,53 @@ void APLRRegressor::add_promising_interactions_and_select_the_best_one()
713726
}
714727
}
715728

716-
void APLRRegressor::consider_updating_intercept()
717-
{
718-
if(sample_weight_train.size()==0)
719-
intercept_test=neg_gradient_current.mean();
720-
else
721-
intercept_test=(neg_gradient_current.array()*sample_weight_train.array()).sum()/sample_weight_train.array().sum();
722-
intercept_test=intercept_test*v;
723-
linear_predictor_update=VectorXd::Constant(neg_gradient_current.size(),intercept_test);
724-
linear_predictor_update_validation=VectorXd::Constant(y_validation.size(),intercept_test);
725-
error_after_updating_intercept=calculate_sum_error(calculate_errors(neg_gradient_current,linear_predictor_update,sample_weight_train));
726-
}
727-
728729
void APLRRegressor::select_the_best_term_and_update_errors(size_t boosting_step)
729730
{
730-
//If intercept does best
731-
if(std::islessequal(error_after_updating_intercept,lowest_error_sum))
731+
bool no_term_was_selected{best_term == std::numeric_limits<size_t>::max()};
732+
if(no_term_was_selected)
732733
{
733-
//Updating intercept, current predictions, gradient and errors
734-
lowest_error_sum=error_after_updating_intercept;
735-
intercept=intercept+intercept_test;
736-
intercept_steps[boosting_step]=intercept;
737-
update_linear_predictor_and_predictors();
738-
update_gradient_and_errors();
734+
abort_boosting=true;
735+
return;
739736
}
740-
else //Choosing the next term and updating the model
741-
{
742-
bool no_term_was_selected{best_term == std::numeric_limits<size_t>::max()};
743-
if(no_term_was_selected)
744-
{
745-
abort_boosting=true;
746-
return;
747-
}
748737

749-
//Updating current predictions
750-
VectorXd values{terms_eligible_current[best_term].calculate(X_train)};
751-
VectorXd values_validation{terms_eligible_current[best_term].calculate(X_validation)};
752-
linear_predictor_update=values*terms_eligible_current[best_term].coefficient;
753-
linear_predictor_update_validation=values_validation*terms_eligible_current[best_term].coefficient;
754-
double error_after_updating_term=calculate_sum_error(calculate_errors(neg_gradient_current,linear_predictor_update,sample_weight_train));
755-
if(std::isgreaterequal(error_after_updating_term,neg_gradient_nullmodel_errors_sum)) //if no improvement or worse then terminate search
756-
{
757-
abort_boosting=true;
758-
return;
759-
}
760-
else //if improvement
761-
{
762-
//Updating predictions_current, gradient and errors
763-
update_linear_predictor_and_predictors();
764-
update_gradient_and_errors();
738+
//Updating current predictions
739+
VectorXd values{terms_eligible_current[best_term].calculate(X_train)};
740+
VectorXd values_validation{terms_eligible_current[best_term].calculate(X_validation)};
741+
linear_predictor_update=values*terms_eligible_current[best_term].coefficient;
742+
linear_predictor_update_validation=values_validation*terms_eligible_current[best_term].coefficient;
743+
double error_after_updating_term=calculate_sum_error(calculate_errors(neg_gradient_current,linear_predictor_update,sample_weight_train));
744+
bool no_improvement{std::isgreaterequal(error_after_updating_term,neg_gradient_nullmodel_errors_sum)};
745+
if(no_improvement)
746+
{
747+
abort_boosting=true;
748+
return;
749+
}
750+
else
751+
{
752+
update_linear_predictor_and_predictors();
753+
update_gradient_and_errors();
765754

766-
//Has the term been entered into the model before?
767-
if(terms.size()==0) //If nothing is in the model add the term
768-
add_new_term(boosting_step);
769-
else //If at least one term was added before
770-
{
771-
//Searching in existing terms
772-
bool found{false};
773-
for (size_t j = 0; j < terms.size(); ++j)
774-
{
775-
if(terms[j]==terms_eligible_current[best_term]) //if term was found, update coefficient and coefficient_steps
776-
{
777-
terms[j].coefficient+=terms_eligible_current[best_term].coefficient;
778-
terms[j].coefficient_steps[boosting_step]=terms[j].coefficient;
779-
found=true;
780-
break;
781-
}
782-
}
783-
//term was not in the model and is added to the model
784-
if(!found)
755+
//Has the term been entered into the model before?
756+
if(terms.size()==0) //If nothing is in the model add the term
757+
add_new_term(boosting_step);
758+
else //If at least one term was added before
759+
{
760+
//Searching in existing terms
761+
bool found{false};
762+
for (size_t j = 0; j < terms.size(); ++j)
763+
{
764+
if(terms[j]==terms_eligible_current[best_term]) //if term was found, update coefficient and coefficient_steps
785765
{
786-
add_new_term(boosting_step);
787-
}
766+
terms[j].coefficient+=terms_eligible_current[best_term].coefficient;
767+
terms[j].coefficient_steps[boosting_step]=terms[j].coefficient;
768+
found=true;
769+
break;
770+
}
771+
}
772+
//term was not in the model and is added to the model
773+
if(!found)
774+
{
775+
add_new_term(boosting_step);
788776
}
789777
}
790778
}

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='1.5.0',
18+
version='1.6.0',
1919
description='Automatic Piecewise Linear Regression',
2020
ext_modules=[sfc_module],
2121
author="Mathias von Ottenbreit",

0 commit comments

Comments
 (0)