in src/boosting/gbdt_model_text.cpp [124:284]
std::string GBDT::ModelToIfElse(int num_iteration) const {
std::stringstream str_buf;
Common::C_stringstream(str_buf);
str_buf << "#include \"gbdt.h\"" << '\n';
str_buf << "#include <LightGBM/utils/common.h>" << '\n';
str_buf << "#include <LightGBM/objective_function.h>" << '\n';
str_buf << "#include <LightGBM/metric.h>" << '\n';
str_buf << "#include <LightGBM/prediction_early_stop.h>" << '\n';
str_buf << "#include <ctime>" << '\n';
str_buf << "#include <sstream>" << '\n';
str_buf << "#include <chrono>" << '\n';
str_buf << "#include <string>" << '\n';
str_buf << "#include <vector>" << '\n';
str_buf << "#include <utility>" << '\n';
str_buf << "namespace LightGBM {" << '\n';
int num_used_model = static_cast<int>(models_.size());
if (num_iteration > 0) {
num_used_model = std::min(num_iteration * num_tree_per_iteration_, num_used_model);
}
// PredictRaw
for (int i = 0; i < num_used_model; ++i) {
str_buf << models_[i]->ToIfElse(i, false) << '\n';
}
str_buf << "double (*PredictTreePtr[])(const double*) = { ";
for (int i = 0; i < num_used_model; ++i) {
if (i > 0) {
str_buf << " , ";
}
str_buf << "PredictTree" << i;
}
str_buf << " };" << '\n' << '\n';
std::stringstream pred_str_buf;
Common::C_stringstream(pred_str_buf);
pred_str_buf << "\t" << "int early_stop_round_counter = 0;" << '\n';
pred_str_buf << "\t" << "std::memset(output, 0, sizeof(double) * num_tree_per_iteration_);" << '\n';
pred_str_buf << "\t" << "for (int i = 0; i < num_iteration_for_pred_; ++i) {" << '\n';
pred_str_buf << "\t\t" << "for (int k = 0; k < num_tree_per_iteration_; ++k) {" << '\n';
pred_str_buf << "\t\t\t" << "output[k] += (*PredictTreePtr[i * num_tree_per_iteration_ + k])(features);" << '\n';
pred_str_buf << "\t\t" << "}" << '\n';
pred_str_buf << "\t\t" << "++early_stop_round_counter;" << '\n';
pred_str_buf << "\t\t" << "if (early_stop->round_period == early_stop_round_counter) {" << '\n';
pred_str_buf << "\t\t\t" << "if (early_stop->callback_function(output, num_tree_per_iteration_))" << '\n';
pred_str_buf << "\t\t\t\t" << "return;" << '\n';
pred_str_buf << "\t\t\t" << "early_stop_round_counter = 0;" << '\n';
pred_str_buf << "\t\t" << "}" << '\n';
pred_str_buf << "\t" << "}" << '\n';
str_buf << "void GBDT::PredictRaw(const double* features, double *output, const PredictionEarlyStopInstance* early_stop) const {" << '\n';
str_buf << pred_str_buf.str();
str_buf << "}" << '\n';
str_buf << '\n';
// PredictRawByMap
str_buf << "double (*PredictTreeByMapPtr[])(const std::unordered_map<int, double>&) = { ";
for (int i = 0; i < num_used_model; ++i) {
if (i > 0) {
str_buf << " , ";
}
str_buf << "PredictTree" << i << "ByMap";
}
str_buf << " };" << '\n' << '\n';
std::stringstream pred_str_buf_map;
Common::C_stringstream(pred_str_buf_map);
pred_str_buf_map << "\t" << "int early_stop_round_counter = 0;" << '\n';
pred_str_buf_map << "\t" << "std::memset(output, 0, sizeof(double) * num_tree_per_iteration_);" << '\n';
pred_str_buf_map << "\t" << "for (int i = 0; i < num_iteration_for_pred_; ++i) {" << '\n';
pred_str_buf_map << "\t\t" << "for (int k = 0; k < num_tree_per_iteration_; ++k) {" << '\n';
pred_str_buf_map << "\t\t\t" << "output[k] += (*PredictTreeByMapPtr[i * num_tree_per_iteration_ + k])(features);" << '\n';
pred_str_buf_map << "\t\t" << "}" << '\n';
pred_str_buf_map << "\t\t" << "++early_stop_round_counter;" << '\n';
pred_str_buf_map << "\t\t" << "if (early_stop->round_period == early_stop_round_counter) {" << '\n';
pred_str_buf_map << "\t\t\t" << "if (early_stop->callback_function(output, num_tree_per_iteration_))" << '\n';
pred_str_buf_map << "\t\t\t\t" << "return;" << '\n';
pred_str_buf_map << "\t\t\t" << "early_stop_round_counter = 0;" << '\n';
pred_str_buf_map << "\t\t" << "}" << '\n';
pred_str_buf_map << "\t" << "}" << '\n';
str_buf << "void GBDT::PredictRawByMap(const std::unordered_map<int, double>& features, double* output, const PredictionEarlyStopInstance* early_stop) const {" << '\n';
str_buf << pred_str_buf_map.str();
str_buf << "}" << '\n';
str_buf << '\n';
// Predict
str_buf << "void GBDT::Predict(const double* features, double *output, const PredictionEarlyStopInstance* early_stop) const {" << '\n';
str_buf << "\t" << "PredictRaw(features, output, early_stop);" << '\n';
str_buf << "\t" << "if (average_output_) {" << '\n';
str_buf << "\t\t" << "for (int k = 0; k < num_tree_per_iteration_; ++k) {" << '\n';
str_buf << "\t\t\t" << "output[k] /= num_iteration_for_pred_;" << '\n';
str_buf << "\t\t" << "}" << '\n';
str_buf << "\t" << "}" << '\n';
str_buf << "\t" << "if (objective_function_ != nullptr) {" << '\n';
str_buf << "\t\t" << "objective_function_->ConvertOutput(output, output);" << '\n';
str_buf << "\t" << "}" << '\n';
str_buf << "}" << '\n';
str_buf << '\n';
// PredictByMap
str_buf << "void GBDT::PredictByMap(const std::unordered_map<int, double>& features, double* output, const PredictionEarlyStopInstance* early_stop) const {" << '\n';
str_buf << "\t" << "PredictRawByMap(features, output, early_stop);" << '\n';
str_buf << "\t" << "if (average_output_) {" << '\n';
str_buf << "\t\t" << "for (int k = 0; k < num_tree_per_iteration_; ++k) {" << '\n';
str_buf << "\t\t\t" << "output[k] /= num_iteration_for_pred_;" << '\n';
str_buf << "\t\t" << "}" << '\n';
str_buf << "\t" << "}" << '\n';
str_buf << "\t" << "if (objective_function_ != nullptr) {" << '\n';
str_buf << "\t\t" << "objective_function_->ConvertOutput(output, output);" << '\n';
str_buf << "\t" << "}" << '\n';
str_buf << "}" << '\n';
str_buf << '\n';
// PredictLeafIndex
for (int i = 0; i < num_used_model; ++i) {
str_buf << models_[i]->ToIfElse(i, true) << '\n';
}
str_buf << "double (*PredictTreeLeafPtr[])(const double*) = { ";
for (int i = 0; i < num_used_model; ++i) {
if (i > 0) {
str_buf << " , ";
}
str_buf << "PredictTree" << i << "Leaf";
}
str_buf << " };" << '\n' << '\n';
str_buf << "void GBDT::PredictLeafIndex(const double* features, double *output) const {" << '\n';
str_buf << "\t" << "int total_tree = num_iteration_for_pred_ * num_tree_per_iteration_;" << '\n';
str_buf << "\t" << "for (int i = 0; i < total_tree; ++i) {" << '\n';
str_buf << "\t\t" << "output[i] = (*PredictTreeLeafPtr[i])(features);" << '\n';
str_buf << "\t" << "}" << '\n';
str_buf << "}" << '\n';
// PredictLeafIndexByMap
str_buf << "double (*PredictTreeLeafByMapPtr[])(const std::unordered_map<int, double>&) = { ";
for (int i = 0; i < num_used_model; ++i) {
if (i > 0) {
str_buf << " , ";
}
str_buf << "PredictTree" << i << "LeafByMap";
}
str_buf << " };" << '\n' << '\n';
str_buf << "void GBDT::PredictLeafIndexByMap(const std::unordered_map<int, double>& features, double* output) const {" << '\n';
str_buf << "\t" << "int total_tree = num_iteration_for_pred_ * num_tree_per_iteration_;" << '\n';
str_buf << "\t" << "for (int i = 0; i < total_tree; ++i) {" << '\n';
str_buf << "\t\t" << "output[i] = (*PredictTreeLeafByMapPtr[i])(features);" << '\n';
str_buf << "\t" << "}" << '\n';
str_buf << "}" << '\n';
str_buf << "} // namespace LightGBM" << '\n';
return str_buf.str();
}