void SumToOne::DoBuild() { LOG_TRACE(); for (auto& estimate_label : estimate_labels_) { Estimate* estimate = model_->managers().estimate()->GetEstimateByLabel(estimate_label); if (estimate == nullptr) { LOG_ERROR_P(PARAM_ESTIMATE_LABELS) << "Estimate " << estimate_label << " could not be found. Have you defined it?"; return; } else { LOG_FINE() << "transform with objective = " << transform_with_jacobian_ << " estimate transform " << estimate->transform_for_objective() << " together = " << !transform_with_jacobian_ && !estimate->transform_for_objective(); if (!transform_with_jacobian_ && !estimate->transform_for_objective()) { LOG_ERROR_P(PARAM_LABEL) << "You have specified a transformation that does not contribute a jacobian, and the prior parameters do not refer to the transformed estimate, in the @estimate" << estimate_label_ << ". This is not advised, and may cause bias estimation. Please address the user manual if you need help"; } if (estimate->transform_with_jacobian_is_defined()) { if (transform_with_jacobian_ != estimate->transform_with_jacobian()) { LOG_ERROR_P(PARAM_LABEL) << "This parameter is not consistent with the equivalent parameter in the @estimate block " << estimate_label_ << ". please make sure these are both true or both false."; } } estimates_.push_back(estimate); } } // Validate that the parameters sum to one. Double total = 0.0; for (auto& estimate : estimates_) { LOG_FINEST() << "transformation value = " << estimate->value(); total += estimate->value(); } if (total != 1.0) LOG_ERROR_P(PARAM_ESTIMATE_LABELS) << "The estiamtes you supplied to not sum to 1.0, they sum to " << total << ", please check initial values of these parameters"; // Check that the bounds are sensible if (parameters_.Get(PARAM_UPPER_BOUND)->has_been_defined() & parameters_.Get(PARAM_LOWER_BOUND)->has_been_defined()) { for (unsigned i = 0; i < estimates_.size(); ++i) { if (estimates_[i]->lower_bound() < 0.0 || estimates_[i]->lower_bound() > 1.0) LOG_ERROR_P(PARAM_LOWER_BOUND) << "You cannot specify a lower bound less than 0 and greater than 1.0"; if (estimates_[i]->upper_bound() < 0.0 || estimates_[i]->upper_bound() > 1.0) LOG_ERROR_P(PARAM_UPPER_BOUND) << "You cannot specify a upper bound less than 0 and greater than 1.0"; } } LOG_MEDIUM() << "total = " << total; // Turn off the last estimate LOG_FINE() << "Turning off parameter, this won't be estimated, and will be an outcome of other parameters " << estimates_[estimates_.size() - 1]->parameter() << " in the estimation"; estimates_[estimates_.size() - 1]->set_estimated(false); LOG_MEDIUM() << "flagged estimated = " << estimates_[estimates_.size() - 1]->estimated(); }
/** * BuildCV function * populates a #d map of cv's by year, age and time_step */ void AgeLength::BuildCV() { unsigned min_age = model_->min_age(); unsigned max_age = model_->max_age(); unsigned start_year = model_->start_year(); unsigned final_year = model_->final_year(); vector<string> time_steps = model_->time_steps(); LOG_MEDIUM() << ": number of time steps " << time_steps.size(); LOG_MEDIUM() << ": label of first time step " << time_steps[0]; for (unsigned year_iter = start_year; year_iter <= final_year; ++year_iter) { for (unsigned step_iter = 0; step_iter < time_steps.size(); ++step_iter) { if (!parameters_.Get(PARAM_CV_LAST)->has_been_defined()) { // A test that is robust... If cv_last_ is not in the input then assume cv_first_ represents the cv for all age classes i.e constant cv for (unsigned age_iter = min_age; age_iter <= max_age; ++age_iter) cvs_[year_iter][age_iter][step_iter] = (cv_first_); } else { // else Do linear interpolation between cv_first_ and cv_last_ based on age class for (unsigned age_iter = min_age; age_iter <= max_age; ++age_iter) { cvs_[year_iter][age_iter][step_iter] = (cv_first_ + (cv_last_ - cv_first_) * (age_iter - min_age) / (max_age - min_age)); } } } } }
/** * This method is called at the start of the targetted * time step for this observation. * * At this point we need to build our cache for the partition * structure to use with any interpolation */ void ProportionsMigrating::PreExecute() { cached_partition_->BuildCache(); LOG_FINEST() << "Entering observation " << label_; if (cached_partition_->Size() != proportions_[model_->current_year()].size()) { LOG_MEDIUM() << "Cached size " << cached_partition_->Size() << " partition size = " << proportions_[model_->current_year()].size(); LOG_CODE_ERROR() << "cached_partition_->Size() != proportions_[model->current_year()].size()"; } if (partition_->Size() != proportions_[model_->current_year()].size()) LOG_CODE_ERROR() << "partition_->Size() != proportions_[model->current_year()].size()"; }
Double Callback::operator()(const ::dlib::matrix<double, 0, 1>& Parameters) const { // Update our Components with the New Parameters vector<Estimate*> estimates = model_->managers().estimate()->GetIsEstimated(); if (Parameters.size() != (int)estimates.size()) { LOG_CODE_ERROR() << "The number of enabled estimates does not match the number of test solution values"; } double penalty = 0; for (int i = 0; i < Parameters.size(); ++i) { Double value = utilities::math::unscale_value(Parameters(i), penalty, estimates[i]->lower_bound(), estimates[i]->upper_bound()); estimates[i]->set_value(value); } model_->managers().estimate_transformation()->RestoreEstimates(); model_->FullIteration(); LOG_MEDIUM() << "Iteration Complete"; ObjectiveFunction& objective = model_->objective_function(); objective.CalculateScore(); model_->managers().estimate_transformation()->TransformEstimates(); return objective.score() + penalty; }
/** * Calculate our score for the current run */ void ObjectiveFunction::CalculateScore() { LOG_TRACE(); Clear(); /** * Get the scores from each of the observations/likelihoods */ vector<Observation*> observations = model_->managers().observation()->objects(); likelihoods_ = 0.0; for(auto observation : observations) { const map<unsigned, Double>& scores = observation->scores(); bool append_age = scores.size() > 1 ? true : false; for(auto iter = scores.begin(); iter != scores.end(); ++iter) { objective::Score new_score; new_score.label_ = PARAM_OBSERVATION + string("->") + observation->label(); if (append_age) new_score.label_ += string("-") + utilities::ToInline<unsigned, string>(iter->first); new_score.score_ = iter->second; score_list_.push_back(new_score); score_ += new_score.score_; likelihoods_ += AS_DOUBLE(new_score.score_); } } /** * Get the scores from each of the penalties */ penalties_ = 0.0; for (auto penalty : model_->managers().penalty()->objects()) { if (penalty->has_score()) { objective::Score new_score; new_score.label_ = PARAM_PENALTY + string("->") + penalty->label(); new_score.score_ = penalty->GetScore(); score_list_.push_back(new_score); score_ += new_score.score_; penalties_ += AS_DOUBLE(new_score.score_); } } /** * Go through the flagged penalties */ const vector<penalties::Info>& penalties = model_->managers().penalty()->flagged_penalties(); for (penalties::Info penalty : penalties) { objective::Score new_score; new_score.label_ = PARAM_PENALTY + string("->") + penalty.label_; new_score.score_ = penalty.score_; score_list_.push_back(new_score); score_ += new_score.score_; penalties_ += AS_DOUBLE(new_score.score_); } /** * Get the scores from each of the estimate priors */ model_->managers().estimate_transformation()->TransformEstimatesForObjectiveFunction(); vector<Estimate*> estimates = model_->managers().estimate()->objects(); priors_ = 0.0; for (Estimate* estimate : estimates) { if (!estimate->in_objective_function()) continue; objective::Score new_score; if (estimate->label() != "") new_score.label_ = PARAM_PRIOR + string("->") + estimate->label() + "->" + estimate->parameter(); else new_score.label_ = PARAM_PRIOR + string("->") + estimate->parameter(); new_score.score_ = estimate->GetScore(); score_list_.push_back(new_score); score_ += new_score.score_; priors_ += AS_DOUBLE(new_score.score_); } model_->managers().estimate_transformation()->RestoreEstimatesFromObjectiveFunction(); /** * Get the score from each additional prior */ vector<AdditionalPrior*> additional_priors = model_->managers().additional_prior()->objects(); additional_priors_ = 0.0; for (auto prior : additional_priors) { objective::Score new_score; new_score.label_ = PARAM_ADDITIONAL_PRIOR + string("->") + prior->label(); new_score.score_ = prior->GetScore(); score_list_.push_back(new_score); score_ += new_score.score_; additional_priors_ += AS_DOUBLE(new_score.score_); } /** * Get the Jacobian score from estimate_transformations */ auto jacobians = model_->managers().estimate_transformation()->objects(); jacobians_ = 0.0; for (auto jacobian : jacobians) { objective::Score new_score; new_score.label_ = PARAM_JACOBIAN + string("->") + jacobian->label(); new_score.score_ = jacobian->GetScore(); score_list_.push_back(new_score); score_ += new_score.score_; jacobians_ += AS_DOUBLE(new_score.score_); } LOG_MEDIUM() << "objective.score: " << score_; }
/** * Calculate the Jacobian, to offset the bias of the transformation that enters the objective function */ Double SumToOne::GetScore() { LOG_TRACE(); jacobian_ = 0.0; LOG_MEDIUM() << "Jacobian: " << jacobian_; return jacobian_; }