Skip to content

Commit

Permalink
Merge 4861b42 into 5429c3e
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Schalk committed Nov 18, 2019
2 parents 5429c3e + 4861b42 commit e9d6d35
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 44 deletions.
32 changes: 8 additions & 24 deletions src/compboost.cpp
Expand Up @@ -57,47 +57,31 @@ void Compboost::train (const unsigned int& trace, std::shared_ptr<loggerlist::Lo
Rcpp::stop("Could not train without any registered base-learner.");
}

arma::mat blearner_pred_temp;

bool stop_the_algorithm = false;
// Bool to indicate whether the stop criteria (stopc) is reached or not:
bool is_stopc_reached = false;
unsigned int k = 1;

// Main Algorithm. While the stop criteria isn't fulfilled, run the
// algorithm:
while (! stop_the_algorithm) {
while (! is_stopc_reached) {

actual_iteration = blearner_track.getBaselearnerVector().size() + 1;

sh_ptr_response->setActualIteration(actual_iteration);
sh_ptr_response->updatePseudoResiduals(sh_ptr_loss);

// Cast integer k to string for baselearner identifier:
std::string temp_string = std::to_string(k);
std::shared_ptr<blearner::Baselearner> sh_ptr_blearner_selected = sh_ptr_optimizer->findBestBaselearner(temp_string,
sh_ptr_response, used_baselearner_list.getMap());

// Prediction is needed more often, use a temp vector to avoid multiple computations:
blearner_pred_temp = sh_ptr_blearner_selected->predict();

sh_ptr_optimizer->calculateStepSize(sh_ptr_loss, sh_ptr_response, blearner_pred_temp);

// Insert new base-learner to vector of selected base-learner. The parameter are estimated here, hence
// the contribution to the old parameter is the estimated parameter times the learning rate times
// the step size. Therefore we have to pass the step size which changes in each iteration:
blearner_track.insertBaselearner(sh_ptr_blearner_selected, sh_ptr_optimizer->getStepSize(actual_iteration));
sh_ptr_response->updatePrediction(learning_rate, sh_ptr_optimizer->getStepSize(actual_iteration), blearner_pred_temp);
sh_ptr_optimizer->optimize(actual_iteration, learning_rate, sh_ptr_loss, sh_ptr_response, blearner_track,
used_baselearner_list);

// Log the current step:
// The last term has to be the prediction or anything like that. This is
// important to track the risk (inbag or oob)!!!!
logger_list->logCurrent(actual_iteration, sh_ptr_response, sh_ptr_blearner_selected, learning_rate, sh_ptr_optimizer->getStepSize(actual_iteration));
logger_list->logCurrent(actual_iteration, sh_ptr_response, blearner_track.getBaselearnerVector().back(),
learning_rate, sh_ptr_optimizer->getStepSize(actual_iteration), sh_ptr_optimizer);

// Calculate and log risk:
risk.push_back(sh_ptr_response->calculateEmpiricalRisk(sh_ptr_loss));

// Get status of the algorithm (is the stopping criteria reached?). The negation here
// seems a bit weird, but it makes the while loop easier to read:
stop_the_algorithm = ! logger_list->getStopperStatus(stop_if_all_stopper_fulfilled);
is_stopc_reached = ! logger_list->getStopperStatus(stop_if_all_stopper_fulfilled);

if (helper::checkTracePrinter(actual_iteration, trace)) logger_list->printLoggerStatus(risk.back());
k += 1;
Expand Down
14 changes: 9 additions & 5 deletions src/logger.cpp
Expand Up @@ -79,7 +79,8 @@ LoggerIteration::LoggerIteration (const std::string& logger_id0, const bool& is_
*/

void LoggerIteration::logStep (const unsigned int& current_iteration, std::shared_ptr<response::Response> sh_ptr_response,
std::shared_ptr<blearner::Baselearner> sh_ptr_blearner, const double& learning_rate, const double& step_size)
std::shared_ptr<blearner::Baselearner> sh_ptr_blearner, const double& learning_rate, const double& step_size,
std::shared_ptr<optimizer::Optimizer> sh_ptr_optimizer)
{
iterations.push_back(current_iteration);
}
Expand Down Expand Up @@ -226,7 +227,8 @@ LoggerInbagRisk::LoggerInbagRisk (const std::string& logger_id0, const bool& is_
*/

void LoggerInbagRisk::logStep (const unsigned int& current_iteration, std::shared_ptr<response::Response> sh_ptr_response,
std::shared_ptr<blearner::Baselearner> sh_ptr_blearner, const double& learning_rate, const double& step_size)
std::shared_ptr<blearner::Baselearner> sh_ptr_blearner, const double& learning_rate, const double& step_size,
std::shared_ptr<optimizer::Optimizer> sh_ptr_optimizer)
{
// Calculate empirical risk. Calculateion of the temporary vector ensures
// // that stuff like auc logging is possible:
Expand Down Expand Up @@ -394,7 +396,8 @@ LoggerOobRisk::LoggerOobRisk (const std::string& logger_id0, const bool& is_a_st
*/

void LoggerOobRisk::logStep (const unsigned int& current_iteration, std::shared_ptr<response::Response> sh_ptr_response,
std::shared_ptr<blearner::Baselearner> sh_ptr_blearner, const double& learning_rate, const double& step_size)
std::shared_ptr<blearner::Baselearner> sh_ptr_blearner, const double& learning_rate, const double& step_size,
std::shared_ptr<optimizer::Optimizer> sh_ptr_optimizer)
{
if (current_iteration == 1) {
sh_ptr_oob_response->constantInitialization(sh_ptr_response->getInitialization());
Expand All @@ -413,7 +416,7 @@ void LoggerOobRisk::logStep (const unsigned int& current_iteration, std::shared_

// Predict this data using the selected baselearner:
arma::mat temp_oob_prediction = sh_ptr_blearner->predict(oob_blearner_data);
sh_ptr_oob_response->updatePrediction(learning_rate, step_size, temp_oob_prediction);
sh_ptr_oob_response->updatePrediction(sh_ptr_optimizer->calculateUpdate(learning_rate, step_size, temp_oob_prediction));
}


Expand Down Expand Up @@ -591,7 +594,8 @@ LoggerTime::LoggerTime (const std::string& logger_id0, const bool& is_a_stopper0
*/

void LoggerTime::logStep (const unsigned int& current_iteration, std::shared_ptr<response::Response> sh_ptr_response,
std::shared_ptr<blearner::Baselearner> sh_ptr_blearner, const double& learning_rate, const double& step_size)
std::shared_ptr<blearner::Baselearner> sh_ptr_blearner, const double& learning_rate, const double& step_size,
std::shared_ptr<optimizer::Optimizer> sh_ptr_optimizer)
{
if (current_time.size() == 0) {
init_time = std::chrono::steady_clock::now();
Expand Down
16 changes: 11 additions & 5 deletions src/logger.h
Expand Up @@ -50,6 +50,7 @@
#include "loss.h"
#include "baselearner.h"
#include "response.h"
#include "optimizer.h"

namespace logger
{
Expand Down Expand Up @@ -82,7 +83,8 @@ class Logger

/// Log current step of compboost iteration dependent on the child class
virtual void logStep (const unsigned int&, std::shared_ptr<response::Response>,
std::shared_ptr<blearner::Baselearner>, const double&, const double&) = 0;
std::shared_ptr<blearner::Baselearner>, const double&, const double&,
std::shared_ptr<optimizer::Optimizer>) = 0;

/// Class dependent check if the stopping criteria is fulfilled
virtual bool reachedStopCriteria () = 0;
Expand Down Expand Up @@ -145,7 +147,8 @@ class LoggerIteration : public Logger

/// Log current step of compboost iteration of class `LoggerIteration`
void logStep (const unsigned int&, std::shared_ptr<response::Response>,
std::shared_ptr<blearner::Baselearner>, const double&, const double&);
std::shared_ptr<blearner::Baselearner>, const double&, const double&,
std::shared_ptr<optimizer::Optimizer>);

/// Stop criteria is fulfilled if the current iteration exceed `max_iteration`
bool reachedStopCriteria ();
Expand Down Expand Up @@ -201,7 +204,8 @@ class LoggerInbagRisk : public Logger

/// Log current step of compboost iteration for class `LoggerInbagRisk`
void logStep (const unsigned int&, std::shared_ptr<response::Response>,
std::shared_ptr<blearner::Baselearner>, const double&, const double&);
std::shared_ptr<blearner::Baselearner>, const double&, const double&,
std::shared_ptr<optimizer::Optimizer>);

/// Stop criteria is fulfilled if the relative improvement falls below `eps_for_break`
bool reachedStopCriteria ();
Expand Down Expand Up @@ -270,7 +274,8 @@ class LoggerOobRisk : public Logger

/// Log current step of compboost iteration for class `LoggerOobRisk`
void logStep (const unsigned int&, std::shared_ptr<response::Response>,
std::shared_ptr<blearner::Baselearner>, const double&, const double&);
std::shared_ptr<blearner::Baselearner>, const double&, const double&,
std::shared_ptr<optimizer::Optimizer>);

/// Stop criteria is fulfilled if the relative improvement falls below `eps_for_break`
bool reachedStopCriteria ();
Expand Down Expand Up @@ -330,7 +335,8 @@ class LoggerTime : public Logger

/// Log current step of compboost iteration for class `LoggerTime`
void logStep (const unsigned int&, std::shared_ptr<response::Response>,
std::shared_ptr<blearner::Baselearner>, const double&, const double&);
std::shared_ptr<blearner::Baselearner>, const double&, const double&,
std::shared_ptr<optimizer::Optimizer>);

/// Stop criteria is fulfilled if the passed time exceeds `max_time`
bool reachedStopCriteria ();
Expand Down
11 changes: 6 additions & 5 deletions src/loggerlist.cpp
Expand Up @@ -96,7 +96,8 @@ std::pair<std::vector<std::string>, arma::mat> LoggerList::getLoggerData () cons
}

void LoggerList::logCurrent (const unsigned int& current_iteration, std::shared_ptr<response::Response> sh_ptr_response,
std::shared_ptr<blearner::Baselearner> sh_ptr_blearner, const double& learning_rate, const double& step_size)
std::shared_ptr<blearner::Baselearner> sh_ptr_blearner, const double& learning_rate, const double& step_size,
std::shared_ptr<optimizer::Optimizer> sh_ptr_optimizer)
{
// Think about how to implement this the best way. I think the computations
// e.g. for the risk should be done within the logger object. If so, the
Expand All @@ -111,7 +112,7 @@ void LoggerList::logCurrent (const unsigned int& current_iteration, std::shared_
// data specified by initializing the logger list.
for (logger_map::iterator it = log_list.begin(); it != log_list.end(); ++it) {
it->second->logStep(current_iteration, sh_ptr_response, sh_ptr_blearner,
learning_rate, step_size);
learning_rate, step_size, sh_ptr_optimizer);
}
}
// Print logger:
Expand All @@ -133,19 +134,19 @@ void LoggerList::printLoggerStatus (const double& current_risk) const

void LoggerList::prepareForRetraining (const unsigned int& new_max_iters)
{
bool iters_in_list = false;
bool has_iteration_logger = false;
for (auto& it : log_list) {
it.second->is_a_stopper = false;
if (it.second->getLoggerType() == "iteration") {
std::static_pointer_cast<logger::LoggerIteration>(it.second)->updateMaxIterations(new_max_iters);
it.second->is_a_stopper = true;
iters_in_list = true;
has_iteration_logger = true;
}
if (it.second->getLoggerType() == "time") {
std::static_pointer_cast<logger::LoggerTime>(it.second)->reInitializeTime();
}
}
if (! iters_in_list) {
if (! has_iteration_logger) {
std::shared_ptr<logger::Logger> new_logger = std::make_shared<logger::LoggerIteration>("iters_re", true, new_max_iters);
log_list.insert(std::pair<std::string, std::shared_ptr<logger::Logger>>("_iteration", new_logger));
}
Expand Down
4 changes: 3 additions & 1 deletion src/loggerlist.h
Expand Up @@ -27,6 +27,7 @@

#include "logger.h"
#include "response.h"
#include "optimizer.h"

typedef std::map<std::string, std::shared_ptr<logger::Logger>> logger_map;

Expand Down Expand Up @@ -70,7 +71,8 @@ class LoggerList
// Log the current step (structure <iteration, actual time, actual risk>).
// This is given to the instantiated logger:
void logCurrent (const unsigned int&, std::shared_ptr<response::Response>,
std::shared_ptr<blearner::Baselearner>, const double&, const double&);
std::shared_ptr<blearner::Baselearner>, const double&, const double&,
std::shared_ptr<optimizer::Optimizer>);

// Print the logger status:
void printLoggerStatus (const double&) const;
Expand Down
25 changes: 25 additions & 0 deletions src/optimizer.cpp
Expand Up @@ -148,6 +148,31 @@ std::shared_ptr<blearner::Baselearner> OptimizerCoordinateDescent::findBestBasel
}
}

arma::mat OptimizerCoordinateDescent::calculateUpdate (const double& learning_rate, const double& step_size,
const arma::mat& blearner_pred) const
{
return learning_rate * step_size * blearner_pred;
}

void OptimizerCoordinateDescent::optimize (const unsigned int& actual_iteration, const double& learning_rate, const std::shared_ptr<loss::Loss> sh_ptr_loss, const std::shared_ptr<response::Response> sh_ptr_response,
blearnertrack::BaselearnerTrack& blearner_track, const blearnerlist::BaselearnerFactoryList& blearner_list)
{
std::string temp_string = std::to_string(actual_iteration);
std::shared_ptr<blearner::Baselearner> sh_ptr_blearner_selected = findBestBaselearner(temp_string,
sh_ptr_response, blearner_list.getMap());

// Prediction is needed more often, use a temp vector to avoid multiple computations:
arma::mat blearner_pred_temp = sh_ptr_blearner_selected->predict();

calculateStepSize(sh_ptr_loss, sh_ptr_response, blearner_pred_temp);

// Insert new base-learner to vector of selected base-learner. The parameter are estimated here, hence
// the contribution to the old parameter is the estimated parameter times the learning rate times
// the step size. Therefore we have to pass the step size which changes in each iteration:
blearner_track.insertBaselearner(sh_ptr_blearner_selected, getStepSize(actual_iteration));
sh_ptr_response->updatePrediction(calculateUpdate(learning_rate, getStepSize(actual_iteration), blearner_pred_temp));
}

void OptimizerCoordinateDescent::calculateStepSize (std::shared_ptr<loss::Loss> sh_ptr_loss, std::shared_ptr<response::Response> sh_ptr_response,
const arma::vec& baselearner_prediction)
{
Expand Down
9 changes: 7 additions & 2 deletions src/optimizer.h
Expand Up @@ -30,6 +30,7 @@

#include "baselearner.h"
#include "baselearner_factory_list.h"
#include "baselearner_track.h"
#include "loss.h"
#include "line_search.h"
#include "helper.h"
Expand All @@ -50,6 +51,9 @@ class Optimizer

virtual std::shared_ptr<blearner::Baselearner> findBestBaselearner (const std::string&,
std::shared_ptr<response::Response>, const blearner_factory_map&) const = 0;
virtual arma::mat calculateUpdate (const double&, const double&, const arma::mat&) const = 0;
virtual void optimize (const unsigned int&, const double&, const std::shared_ptr<loss::Loss>, const std::shared_ptr<response::Response>,
blearnertrack::BaselearnerTrack&, const blearnerlist::BaselearnerFactoryList&) = 0;

// loss, target, model_prediction, base_learner_prediction (prediction of newly selected base-learner)
virtual void calculateStepSize (std::shared_ptr<loss::Loss>, std::shared_ptr<response::Response>, const arma::vec&) = 0;
Expand Down Expand Up @@ -82,14 +86,15 @@ class OptimizerCoordinateDescent : public Optimizer

std::shared_ptr<blearner::Baselearner> findBestBaselearner (const std::string&, std::shared_ptr<response::Response>,
const blearner_factory_map&) const;
arma::mat calculateUpdate (const double&, const double&, const arma::mat&) const;
void optimize (const unsigned int&, const double&, const std::shared_ptr<loss::Loss>, const std::shared_ptr<response::Response>,
blearnertrack::BaselearnerTrack&, const blearnerlist::BaselearnerFactoryList&);

void calculateStepSize (std::shared_ptr<loss::Loss>, std::shared_ptr<response::Response>, const arma::vec&);
std::vector<double> getStepSize () const;
double getStepSize (const unsigned int&) const;
};

// Coordinate Descent with line search:
// -------------------------------------------
class OptimizerCoordinateDescentLineSearch : public OptimizerCoordinateDescent
{
public:
Expand Down
7 changes: 6 additions & 1 deletion src/response.cpp
Expand Up @@ -65,6 +65,11 @@ void Response::updatePseudoResiduals (std::shared_ptr<loss::Loss> sh_ptr_loss)
}
}

void Response::updatePrediction (const arma::mat& update)
{
prediction_scores += update;
}

void Response::updatePrediction (const double& learning_rate, const double& step_size, const arma::mat& update)
{
prediction_scores += learning_rate * step_size * update;
Expand Down Expand Up @@ -370,4 +375,4 @@ void ResponseFDA::filter (const arma::uvec& idx)
prediction_scores = prediction_scores.elem(idx);
}

} // namespace response
} // namespace response
3 changes: 2 additions & 1 deletion src/response.h
Expand Up @@ -68,6 +68,7 @@ class Response
void checkLossCompatibility (std::shared_ptr<loss::Loss>) const;

void updatePseudoResiduals (std::shared_ptr<loss::Loss>);
void updatePrediction (const arma::mat&);
void updatePrediction (const double&, const double&, const arma::mat&);

void constantInitialization (std::shared_ptr<loss::Loss>);
Expand Down Expand Up @@ -148,4 +149,4 @@ class ResponseFDA : public Response

} // namespace response

#endif // RESPONSE_H_
#endif // RESPONSE_H_

0 comments on commit e9d6d35

Please sign in to comment.