Commit 5d022898 authored by Guolin Ke's avatar Guolin Ke Committed by xuehui
Browse files

refine some interface for better expose api. (#52)

parent 66804b93
...@@ -231,9 +231,9 @@ void Metadata::LoadWeights() { ...@@ -231,9 +231,9 @@ void Metadata::LoadWeights() {
num_weights_ = static_cast<data_size_t>(reader.Lines().size()); num_weights_ = static_cast<data_size_t>(reader.Lines().size());
weights_ = new float[num_weights_]; weights_ = new float[num_weights_];
for (data_size_t i = 0; i < num_weights_; ++i) { for (data_size_t i = 0; i < num_weights_; ++i) {
double tmp_weight = 0.0f; float tmp_weight = 0.0f;
Common::Atof(reader.Lines()[i].c_str(), &tmp_weight); Common::Atof(reader.Lines()[i].c_str(), &tmp_weight);
weights_[i] = static_cast<float>(tmp_weight); weights_[i] = tmp_weight;
} }
} }
...@@ -246,7 +246,7 @@ void Metadata::LoadInitialScore() { ...@@ -246,7 +246,7 @@ void Metadata::LoadInitialScore() {
Log::Info("Start loading initial scores"); Log::Info("Start loading initial scores");
num_init_score_ = static_cast<data_size_t>(reader.Lines().size()); num_init_score_ = static_cast<data_size_t>(reader.Lines().size());
init_score_ = new score_t[num_init_score_]; init_score_ = new score_t[num_init_score_];
double tmp = 0.0f; float tmp = 0.0f;
for (data_size_t i = 0; i < num_init_score_; ++i) { for (data_size_t i = 0; i < num_init_score_; ++i) {
Common::Atof(reader.Lines()[i].c_str(), &tmp); Common::Atof(reader.Lines()[i].c_str(), &tmp);
init_score_[i] = static_cast<score_t>(tmp); init_score_[i] = static_cast<score_t>(tmp);
......
...@@ -18,9 +18,9 @@ public: ...@@ -18,9 +18,9 @@ public:
:label_idx_(label_idx) { :label_idx_(label_idx) {
} }
inline void ParseOneLine(const char* str, inline void ParseOneLine(const char* str,
std::vector<std::pair<int, double>>* out_features, double* out_label) const override { std::vector<std::pair<int, float>>* out_features, float* out_label) const override {
int idx = 0; int idx = 0;
double val = 0.0; float val = 0.0f;
int bias = 0; int bias = 0;
*out_label = 0.0f; *out_label = 0.0f;
while (*str != '\0') { while (*str != '\0') {
...@@ -50,9 +50,9 @@ public: ...@@ -50,9 +50,9 @@ public:
:label_idx_(label_idx) { :label_idx_(label_idx) {
} }
inline void ParseOneLine(const char* str, inline void ParseOneLine(const char* str,
std::vector<std::pair<int, double>>* out_features, double* out_label) const override { std::vector<std::pair<int, float>>* out_features, float* out_label) const override {
int idx = 0; int idx = 0;
double val = 0.0; float val = 0.0f;
int bias = 0; int bias = 0;
while (*str != '\0') { while (*str != '\0') {
str = Common::Atof(str, &val); str = Common::Atof(str, &val);
...@@ -83,9 +83,9 @@ public: ...@@ -83,9 +83,9 @@ public:
} }
} }
inline void ParseOneLine(const char* str, inline void ParseOneLine(const char* str,
std::vector<std::pair<int, double>>* out_features, double* out_label) const override { std::vector<std::pair<int, float>>* out_features, float* out_label) const override {
int idx = 0; int idx = 0;
double val = 0.0; float val = 0.0f;
if (label_idx_ == 0) { if (label_idx_ == 0) {
str = Common::Atof(str, &val); str = Common::Atof(str, &val);
*out_label = val; *out_label = val;
......
...@@ -64,7 +64,7 @@ public: ...@@ -64,7 +64,7 @@ public:
data_size_t cur_pos = fast_pair.second; data_size_t cur_pos = fast_pair.second;
data_size_t lte_count = 0; data_size_t lte_count = 0;
data_size_t gt_count = 0; data_size_t gt_count = 0;
for (data_size_t i = 0; i < num_data; i++) { for (data_size_t i = 0; i < num_data; ++i) {
const data_size_t idx = data_indices[i]; const data_size_t idx = data_indices[i];
while (cur_pos < idx && j < num_vals_) { while (cur_pos < idx && j < num_vals_) {
++j; ++j;
...@@ -92,12 +92,12 @@ public: ...@@ -92,12 +92,12 @@ public:
void FinishLoad() override { void FinishLoad() override {
// get total non zero size // get total non zero size
size_t non_zero_size = 0; size_t non_zero_size = 0;
for (size_t i = 0; i < push_buffers_.size(); i++) { for (size_t i = 0; i < push_buffers_.size(); ++i) {
non_zero_size += push_buffers_[i].size(); non_zero_size += push_buffers_[i].size();
} }
// merge // merge
non_zero_pair_.reserve(non_zero_size); non_zero_pair_.reserve(non_zero_size);
for (size_t i = 0; i < push_buffers_.size(); i++) { for (size_t i = 0; i < push_buffers_.size(); ++i) {
non_zero_pair_.insert(non_zero_pair_.end(), push_buffers_[i].begin(), push_buffers_[i].end()); non_zero_pair_.insert(non_zero_pair_.end(), push_buffers_[i].begin(), push_buffers_[i].end());
push_buffers_[i].clear(); push_buffers_[i].clear();
push_buffers_[i].shrink_to_fit(); push_buffers_[i].shrink_to_fit();
...@@ -122,7 +122,7 @@ public: ...@@ -122,7 +122,7 @@ public:
// transform to delta array // transform to delta array
const uint8_t kMaxDelta = 255; const uint8_t kMaxDelta = 255;
data_size_t last_idx = 0; data_size_t last_idx = 0;
for (size_t i = 0; i < non_zero_pair.size(); i++) { for (size_t i = 0; i < non_zero_pair.size(); ++i) {
const data_size_t cur_idx = non_zero_pair[i].first; const data_size_t cur_idx = non_zero_pair[i].first;
const VAL_T bin = non_zero_pair[i].second; const VAL_T bin = non_zero_pair[i].second;
data_size_t cur_delta = cur_idx - last_idx; data_size_t cur_delta = cur_idx - last_idx;
...@@ -198,7 +198,7 @@ public: ...@@ -198,7 +198,7 @@ public:
delta_.clear(); delta_.clear();
vals_.clear(); vals_.clear();
num_vals_ = tmp_num_vals; num_vals_ = tmp_num_vals;
for (data_size_t i = 0; i < num_vals_; i++) { for (data_size_t i = 0; i < num_vals_; ++i) {
delta_.push_back(tmp_delta[i]); delta_.push_back(tmp_delta[i]);
vals_.push_back(tmp_vals[i]); vals_.push_back(tmp_vals[i]);
} }
......
...@@ -23,8 +23,8 @@ Tree::Tree(int max_leaves) ...@@ -23,8 +23,8 @@ Tree::Tree(int max_leaves)
split_feature_ = new int[max_leaves_ - 1]; split_feature_ = new int[max_leaves_ - 1];
split_feature_real_ = new int[max_leaves_ - 1]; split_feature_real_ = new int[max_leaves_ - 1];
threshold_in_bin_ = new unsigned int[max_leaves_ - 1]; threshold_in_bin_ = new unsigned int[max_leaves_ - 1];
threshold_ = new double[max_leaves_ - 1]; threshold_ = new float[max_leaves_ - 1];
split_gain_ = new double[max_leaves_ - 1]; split_gain_ = new float[max_leaves_ - 1];
leaf_parent_ = new int[max_leaves_]; leaf_parent_ = new int[max_leaves_];
leaf_value_ = new score_t[max_leaves_]; leaf_value_ = new score_t[max_leaves_];
...@@ -48,7 +48,7 @@ Tree::~Tree() { ...@@ -48,7 +48,7 @@ Tree::~Tree() {
} }
int Tree::Split(int leaf, int feature, unsigned int threshold_bin, int real_feature, int Tree::Split(int leaf, int feature, unsigned int threshold_bin, int real_feature,
double threshold, score_t left_value, score_t right_value, double gain) { float threshold, score_t left_value, score_t right_value, float gain) {
int new_node_idx = num_leaves_ - 1; int new_node_idx = num_leaves_ - 1;
// update parent info // update parent info
int parent = leaf_parent_[leaf]; int parent = leaf_parent_[leaf];
...@@ -85,10 +85,10 @@ int Tree::Split(int leaf, int feature, unsigned int threshold_bin, int real_feat ...@@ -85,10 +85,10 @@ int Tree::Split(int leaf, int feature, unsigned int threshold_bin, int real_feat
void Tree::AddPredictionToScore(const Dataset* data, data_size_t num_data, score_t* score) const { void Tree::AddPredictionToScore(const Dataset* data, data_size_t num_data, score_t* score) const {
Threading::For<data_size_t>(0, num_data, [this, data, score](int, data_size_t start, data_size_t end) { Threading::For<data_size_t>(0, num_data, [this, data, score](int, data_size_t start, data_size_t end) {
std::vector<BinIterator*> iterators; std::vector<BinIterator*> iterators;
for (int i = 0; i < data->num_features(); i++) { for (int i = 0; i < data->num_features(); ++i) {
iterators.push_back(data->FeatureAt(i)->bin_data()->GetIterator(start)); iterators.push_back(data->FeatureAt(i)->bin_data()->GetIterator(start));
} }
for (data_size_t i = start; i < end; i++) { for (data_size_t i = start; i < end; ++i) {
score[i] += leaf_value_[GetLeaf(iterators, i)]; score[i] += leaf_value_[GetLeaf(iterators, i)];
} }
}); });
...@@ -99,10 +99,10 @@ void Tree::AddPredictionToScore(const Dataset* data, const data_size_t* used_dat ...@@ -99,10 +99,10 @@ void Tree::AddPredictionToScore(const Dataset* data, const data_size_t* used_dat
Threading::For<data_size_t>(0, num_data, Threading::For<data_size_t>(0, num_data,
[this, data, used_data_indices, score](int, data_size_t start, data_size_t end) { [this, data, used_data_indices, score](int, data_size_t start, data_size_t end) {
std::vector<BinIterator*> iterators; std::vector<BinIterator*> iterators;
for (int i = 0; i < data->num_features(); i++) { for (int i = 0; i < data->num_features(); ++i) {
iterators.push_back(data->FeatureAt(i)->bin_data()->GetIterator(used_data_indices[start])); iterators.push_back(data->FeatureAt(i)->bin_data()->GetIterator(used_data_indices[start]));
} }
for (data_size_t i = start; i < end; i++) { for (data_size_t i = start; i < end; ++i) {
score[used_data_indices[i]] += leaf_value_[GetLeaf(iterators, used_data_indices[i])]; score[used_data_indices[i]] += leaf_value_[GetLeaf(iterators, used_data_indices[i])];
} }
}); });
...@@ -114,9 +114,9 @@ std::string Tree::ToString() { ...@@ -114,9 +114,9 @@ std::string Tree::ToString() {
ss << "split_feature=" ss << "split_feature="
<< Common::ArrayToString<int>(split_feature_real_, num_leaves_ - 1, ' ') << std::endl; << Common::ArrayToString<int>(split_feature_real_, num_leaves_ - 1, ' ') << std::endl;
ss << "split_gain=" ss << "split_gain="
<< Common::ArrayToString<double>(split_gain_, num_leaves_ - 1, ' ') << std::endl; << Common::ArrayToString<float>(split_gain_, num_leaves_ - 1, ' ') << std::endl;
ss << "threshold=" ss << "threshold="
<< Common::ArrayToString<double>(threshold_, num_leaves_ - 1, ' ') << std::endl; << Common::ArrayToString<float>(threshold_, num_leaves_ - 1, ' ') << std::endl;
ss << "left_child=" ss << "left_child="
<< Common::ArrayToString<int>(left_child_, num_leaves_ - 1, ' ') << std::endl; << Common::ArrayToString<int>(left_child_, num_leaves_ - 1, ' ') << std::endl;
ss << "right_child=" ss << "right_child="
...@@ -154,8 +154,8 @@ Tree::Tree(const std::string& str) { ...@@ -154,8 +154,8 @@ Tree::Tree(const std::string& str) {
left_child_ = new int[num_leaves_ - 1]; left_child_ = new int[num_leaves_ - 1];
right_child_ = new int[num_leaves_ - 1]; right_child_ = new int[num_leaves_ - 1];
split_feature_real_ = new int[num_leaves_ - 1]; split_feature_real_ = new int[num_leaves_ - 1];
threshold_ = new double[num_leaves_ - 1]; threshold_ = new float[num_leaves_ - 1];
split_gain_ = new double[num_leaves_ - 1]; split_gain_ = new float[num_leaves_ - 1];
leaf_parent_ = new int[num_leaves_]; leaf_parent_ = new int[num_leaves_];
leaf_value_ = new score_t[num_leaves_]; leaf_value_ = new score_t[num_leaves_];
...@@ -165,9 +165,9 @@ Tree::Tree(const std::string& str) { ...@@ -165,9 +165,9 @@ Tree::Tree(const std::string& str) {
Common::StringToIntArray(key_vals["split_feature"], ' ', Common::StringToIntArray(key_vals["split_feature"], ' ',
num_leaves_ - 1, split_feature_real_); num_leaves_ - 1, split_feature_real_);
Common::StringToDoubleArray(key_vals["split_gain"], ' ', Common::StringToFloatArray(key_vals["split_gain"], ' ',
num_leaves_ - 1, split_gain_); num_leaves_ - 1, split_gain_);
Common::StringToDoubleArray(key_vals["threshold"], ' ', Common::StringToFloatArray(key_vals["threshold"], ' ',
num_leaves_ - 1, threshold_); num_leaves_ - 1, threshold_);
Common::StringToIntArray(key_vals["left_child"], ' ', Common::StringToIntArray(key_vals["left_child"], ' ',
num_leaves_ - 1, left_child_); num_leaves_ - 1, left_child_);
...@@ -175,7 +175,7 @@ Tree::Tree(const std::string& str) { ...@@ -175,7 +175,7 @@ Tree::Tree(const std::string& str) {
num_leaves_ - 1, right_child_); num_leaves_ - 1, right_child_);
Common::StringToIntArray(key_vals["leaf_parent"], ' ', Common::StringToIntArray(key_vals["leaf_parent"], ' ',
num_leaves_ , leaf_parent_); num_leaves_ , leaf_parent_);
Common::StringToDoubleArray(key_vals["leaf_value"], ' ', Common::StringToFloatArray(key_vals["leaf_value"], ' ',
num_leaves_ , leaf_value_); num_leaves_ , leaf_value_);
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <sstream>
namespace LightGBM { namespace LightGBM {
...@@ -18,9 +19,6 @@ template<typename PointWiseLossCalculator> ...@@ -18,9 +19,6 @@ template<typename PointWiseLossCalculator>
class BinaryMetric: public Metric { class BinaryMetric: public Metric {
public: public:
explicit BinaryMetric(const MetricConfig& config) { explicit BinaryMetric(const MetricConfig& config) {
early_stopping_round_ = config.early_stopping_round;
output_freq_ = config.output_freq;
the_bigger_the_better = false;
sigmoid_ = static_cast<score_t>(config.sigmoid); sigmoid_ = static_cast<score_t>(config.sigmoid);
if (sigmoid_ <= 0.0f) { if (sigmoid_ <= 0.0f) {
Log::Fatal("Sigmoid param %f should greater than zero", sigmoid_); Log::Fatal("Sigmoid param %f should greater than zero", sigmoid_);
...@@ -32,7 +30,9 @@ public: ...@@ -32,7 +30,9 @@ public:
} }
void Init(const char* test_name, const Metadata& metadata, data_size_t num_data) override { void Init(const char* test_name, const Metadata& metadata, data_size_t num_data) override {
name = test_name; std::stringstream str_buf;
str_buf << test_name << "'s " << PointWiseLossCalculator::Name();
name_ = str_buf.str();
num_data_ = num_data; num_data_ = num_data;
// get label // get label
label_ = metadata.label(); label_ = metadata.label();
...@@ -41,7 +41,7 @@ public: ...@@ -41,7 +41,7 @@ public:
weights_ = metadata.weights(); weights_ = metadata.weights();
if (weights_ == nullptr) { if (weights_ == nullptr) {
sum_weights_ = static_cast<double>(num_data_); sum_weights_ = static_cast<float>(num_data_);
} else { } else {
sum_weights_ = 0.0f; sum_weights_ = 0.0f;
for (data_size_t i = 0; i < num_data; ++i) { for (data_size_t i = 0; i < num_data; ++i) {
...@@ -50,38 +50,38 @@ public: ...@@ -50,38 +50,38 @@ public:
} }
} }
score_t PrintAndGetLoss(int iter, const score_t* score) const override { const char* GetName() const override {
return name_.c_str();
}
bool is_bigger_better() const override {
return false;
}
std::vector<score_t> Eval(const score_t* score) const override {
score_t sum_loss = 0.0f; score_t sum_loss = 0.0f;
if (early_stopping_round_ > 0 || (output_freq_ > 0 && iter % output_freq_ == 0)) { if (weights_ == nullptr) {
if (weights_ == nullptr) { #pragma omp parallel for schedule(static) reduction(+:sum_loss)
#pragma omp parallel for schedule(static) reduction(+:sum_loss) for (data_size_t i = 0; i < num_data_; ++i) {
for (data_size_t i = 0; i < num_data_; ++i) { // sigmoid transform
// sigmoid transform score_t prob = 1.0f / (1.0f + std::exp(-2.0f * sigmoid_ * score[i]));
score_t prob = 1.0f / (1.0f + std::exp(-2.0f * sigmoid_ * score[i])); // add loss
// add loss sum_loss += PointWiseLossCalculator::LossOnPoint(label_[i], prob);
sum_loss += PointWiseLossCalculator::LossOnPoint(label_[i], prob);
}
} else {
#pragma omp parallel for schedule(static) reduction(+:sum_loss)
for (data_size_t i = 0; i < num_data_; ++i) {
// sigmoid transform
score_t prob = 1.0f / (1.0f + std::exp(-2.0f * sigmoid_ * score[i]));
// add loss
sum_loss += PointWiseLossCalculator::LossOnPoint(label_[i], prob) * weights_[i];
}
} }
score_t loss = sum_loss / sum_weights_; } else {
if (output_freq_ > 0 && iter % output_freq_ == 0){ #pragma omp parallel for schedule(static) reduction(+:sum_loss)
Log::Info("Iteration:%d, %s's %s: %f", iter, name, PointWiseLossCalculator::Name(), loss); for (data_size_t i = 0; i < num_data_; ++i) {
// sigmoid transform
score_t prob = 1.0f / (1.0f + std::exp(-2.0f * sigmoid_ * score[i]));
// add loss
sum_loss += PointWiseLossCalculator::LossOnPoint(label_[i], prob) * weights_[i];
} }
return loss;
} }
return 0.0f; score_t loss = sum_loss / sum_weights_;
return std::vector<score_t>(1, loss);
} }
private: private:
/*! \brief Output frequently */
int output_freq_;
/*! \brief Number of data */ /*! \brief Number of data */
data_size_t num_data_; data_size_t num_data_;
/*! \brief Pointer of label */ /*! \brief Pointer of label */
...@@ -89,9 +89,9 @@ private: ...@@ -89,9 +89,9 @@ private:
/*! \brief Pointer of weighs */ /*! \brief Pointer of weighs */
const float* weights_; const float* weights_;
/*! \brief Sum weights */ /*! \brief Sum weights */
double sum_weights_; float sum_weights_;
/*! \brief Name of test set */ /*! \brief Name of test set */
const char* name; std::string name_;
/*! \brief Sigmoid parameter */ /*! \brief Sigmoid parameter */
score_t sigmoid_; score_t sigmoid_;
}; };
...@@ -145,17 +145,26 @@ public: ...@@ -145,17 +145,26 @@ public:
*/ */
class AUCMetric: public Metric { class AUCMetric: public Metric {
public: public:
explicit AUCMetric(const MetricConfig& config) { explicit AUCMetric(const MetricConfig&) {
early_stopping_round_ = config.early_stopping_round;
output_freq_ = config.output_freq;
the_bigger_the_better = true;
} }
virtual ~AUCMetric() { virtual ~AUCMetric() {
} }
const char* GetName() const override {
return name_.c_str();
}
bool is_bigger_better() const override {
return true;
}
void Init(const char* test_name, const Metadata& metadata, data_size_t num_data) override { void Init(const char* test_name, const Metadata& metadata, data_size_t num_data) override {
name = test_name; std::stringstream str_buf;
str_buf << test_name << "'s AUC";
name_ = str_buf.str();
num_data_ = num_data; num_data_ = num_data;
// get label // get label
label_ = metadata.label(); label_ = metadata.label();
...@@ -163,7 +172,7 @@ public: ...@@ -163,7 +172,7 @@ public:
weights_ = metadata.weights(); weights_ = metadata.weights();
if (weights_ == nullptr) { if (weights_ == nullptr) {
sum_weights_ = static_cast<double>(num_data_); sum_weights_ = static_cast<float>(num_data_);
} else { } else {
sum_weights_ = 0.0f; sum_weights_ = 0.0f;
for (data_size_t i = 0; i < num_data; ++i) { for (data_size_t i = 0; i < num_data; ++i) {
...@@ -172,74 +181,66 @@ public: ...@@ -172,74 +181,66 @@ public:
} }
} }
score_t PrintAndGetLoss(int iter, const score_t* score) const override { std::vector<score_t> Eval(const score_t* score) const override {
if (early_stopping_round_ > 0 || (output_freq_ > 0 && iter % output_freq_ == 0)) { // get indices sorted by score, descent order
// get indices sorted by score, descent order std::vector<data_size_t> sorted_idx;
std::vector<data_size_t> sorted_idx; for (data_size_t i = 0; i < num_data_; ++i) {
sorted_idx.emplace_back(i);
}
std::sort(sorted_idx.begin(), sorted_idx.end(), [score](data_size_t a, data_size_t b) {return score[a] > score[b]; });
// temp sum of postive label
float cur_pos = 0.0f;
// total sum of postive label
float sum_pos = 0.0f;
// accumlate of auc
float accum = 0.0f;
// temp sum of negative label
float cur_neg = 0.0f;
score_t threshold = score[sorted_idx[0]];
if (weights_ == nullptr) { // no weights
for (data_size_t i = 0; i < num_data_; ++i) { for (data_size_t i = 0; i < num_data_; ++i) {
sorted_idx.emplace_back(i); const float cur_label = label_[sorted_idx[i]];
} const score_t cur_score = score[sorted_idx[i]];
std::sort(sorted_idx.begin(), sorted_idx.end(), [score](data_size_t a, data_size_t b) {return score[a] > score[b]; }); // new threshold
// temp sum of postive label if (cur_score != threshold) {
double cur_pos = 0.0; threshold = cur_score;
// total sum of postive label // accmulate
double sum_pos = 0.0; accum += cur_neg*(cur_pos * 0.5f + sum_pos);
// accumlate of auc sum_pos += cur_pos;
double accum = 0.0; // reset
// temp sum of negative label cur_neg = cur_pos = 0.0f;
double cur_neg = 0.0;
score_t threshold = score[sorted_idx[0]];
if (weights_ == nullptr) { // not weights
for (data_size_t i = 0; i < num_data_; ++i) {
const float cur_label = label_[sorted_idx[i]];
const score_t cur_score = score[sorted_idx[i]];
// new threshold
if (cur_score != threshold) {
threshold = cur_score;
// accmulate
accum += cur_neg*(cur_pos * 0.5 + sum_pos);
sum_pos += cur_pos;
// reset
cur_neg = cur_pos = 0.0;
}
cur_neg += 1.0 - cur_label;
cur_pos += cur_label;
} }
} else { // has weights cur_neg += 1.0f - cur_label;
for (data_size_t i = 0; i < num_data_; ++i) { cur_pos += cur_label;
const float cur_label = label_[sorted_idx[i]];
const score_t cur_score = score[sorted_idx[i]];
const float cur_weight = weights_[sorted_idx[i]];
// new threshold
if (cur_score != threshold) {
threshold = cur_score;
// accmulate
accum += cur_neg*(cur_pos * 0.5 + sum_pos);
sum_pos += cur_pos;
// reset
cur_neg = cur_pos = 0.0;
}
cur_neg += (1.0 - cur_label)*cur_weight;
cur_pos += cur_label*cur_weight;
}
}
accum += cur_neg*(cur_pos * 0.5 + sum_pos);
sum_pos += cur_pos;
double auc = 1.0;
if (sum_pos > 0.0f && sum_pos != sum_weights_) {
auc = accum / (sum_pos *(sum_weights_ - sum_pos));
} }
if (output_freq_ > 0 && iter % output_freq_ == 0){ } else { // has weights
Log::Info("Iteration:%d, %s's %s: %f", iter, name, "auc", auc); for (data_size_t i = 0; i < num_data_; ++i) {
const float cur_label = label_[sorted_idx[i]];
const score_t cur_score = score[sorted_idx[i]];
const float cur_weight = weights_[sorted_idx[i]];
// new threshold
if (cur_score != threshold) {
threshold = cur_score;
// accmulate
accum += cur_neg*(cur_pos * 0.5f + sum_pos);
sum_pos += cur_pos;
// reset
cur_neg = cur_pos = 0.0f;
}
cur_neg += (1.0f - cur_label)*cur_weight;
cur_pos += cur_label*cur_weight;
} }
return auc;
} }
return 0.0f; accum += cur_neg*(cur_pos * 0.5f + sum_pos);
sum_pos += cur_pos;
float auc = 1.0f;
if (sum_pos > 0.0f && sum_pos != sum_weights_) {
auc = accum / (sum_pos *(sum_weights_ - sum_pos));
}
return std::vector<score_t>(1, auc);
} }
private: private:
/*! \brief Output frequency */
int output_freq_;
/*! \brief Number of data */ /*! \brief Number of data */
data_size_t num_data_; data_size_t num_data_;
/*! \brief Pointer of label */ /*! \brief Pointer of label */
...@@ -247,9 +248,9 @@ private: ...@@ -247,9 +248,9 @@ private:
/*! \brief Pointer of weighs */ /*! \brief Pointer of weighs */
const float* weights_; const float* weights_;
/*! \brief Sum weights */ /*! \brief Sum weights */
double sum_weights_; float sum_weights_;
/*! \brief Name of test set */ /*! \brief Name of test set */
const char* name; std::string name_;
}; };
} // namespace LightGBM } // namespace LightGBM
......
...@@ -11,23 +11,23 @@ namespace LightGBM { ...@@ -11,23 +11,23 @@ namespace LightGBM {
/*! \brief Declaration for some static members */ /*! \brief Declaration for some static members */
bool DCGCalculator::is_inited_ = false; bool DCGCalculator::is_inited_ = false;
std::vector<double> DCGCalculator::label_gain_; std::vector<float> DCGCalculator::label_gain_;
std::vector<double> DCGCalculator::discount_; std::vector<float> DCGCalculator::discount_;
const data_size_t DCGCalculator::kMaxPosition = 10000; const data_size_t DCGCalculator::kMaxPosition = 10000;
void DCGCalculator::Init(std::vector<double> input_label_gain) { void DCGCalculator::Init(std::vector<float> input_label_gain) {
// only inited one time // only inited one time
if (is_inited_) { return; } if (is_inited_) { return; }
label_gain_ = input_label_gain; label_gain_ = input_label_gain;
discount_.clear(); discount_.clear();
for (data_size_t i = 0; i < kMaxPosition; ++i) { for (data_size_t i = 0; i < kMaxPosition; ++i) {
discount_.emplace_back(1.0 / std::log2(2.0 + i)); discount_.emplace_back(1.0f / std::log2(2.0f + i));
} }
is_inited_ = true; is_inited_ = true;
} }
double DCGCalculator::CalMaxDCGAtK(data_size_t k, const float* label, data_size_t num_data) { float DCGCalculator::CalMaxDCGAtK(data_size_t k, const float* label, data_size_t num_data) {
double ret = 0.0; float ret = 0.0f;
// counts for all labels // counts for all labels
std::vector<data_size_t> label_cnt(label_gain_.size(), 0); std::vector<data_size_t> label_cnt(label_gain_.size(), 0);
for (data_size_t i = 0; i < num_data; ++i) { for (data_size_t i = 0; i < num_data; ++i) {
...@@ -53,14 +53,14 @@ double DCGCalculator::CalMaxDCGAtK(data_size_t k, const float* label, data_size_ ...@@ -53,14 +53,14 @@ double DCGCalculator::CalMaxDCGAtK(data_size_t k, const float* label, data_size_
void DCGCalculator::CalMaxDCG(const std::vector<data_size_t>& ks, void DCGCalculator::CalMaxDCG(const std::vector<data_size_t>& ks,
const float* label, const float* label,
data_size_t num_data, data_size_t num_data,
std::vector<double>* out) { std::vector<float>* out) {
std::vector<data_size_t> label_cnt(label_gain_.size(), 0); std::vector<data_size_t> label_cnt(label_gain_.size(), 0);
// counts for all labels // counts for all labels
for (data_size_t i = 0; i < num_data; ++i) { for (data_size_t i = 0; i < num_data; ++i) {
if (static_cast<size_t>(label[i]) >= label_cnt.size()) { Log::Fatal("label excel %d", label[i]); } if (static_cast<size_t>(label[i]) >= label_cnt.size()) { Log::Fatal("label excel %d", label[i]); }
++label_cnt[static_cast<int>(label[i])]; ++label_cnt[static_cast<int>(label[i])];
} }
double cur_result = 0.0; float cur_result = 0.0f;
data_size_t cur_left = 0; data_size_t cur_left = 0;
size_t top_label = label_gain_.size() - 1; size_t top_label = label_gain_.size() - 1;
// calculate k Max DCG by one pass // calculate k Max DCG by one pass
...@@ -83,7 +83,7 @@ void DCGCalculator::CalMaxDCG(const std::vector<data_size_t>& ks, ...@@ -83,7 +83,7 @@ void DCGCalculator::CalMaxDCG(const std::vector<data_size_t>& ks,
} }
double DCGCalculator::CalDCGAtK(data_size_t k, const float* label, float DCGCalculator::CalDCGAtK(data_size_t k, const float* label,
const score_t* score, data_size_t num_data) { const score_t* score, data_size_t num_data) {
// get sorted indices by score // get sorted indices by score
std::vector<data_size_t> sorted_idx; std::vector<data_size_t> sorted_idx;
...@@ -94,7 +94,7 @@ double DCGCalculator::CalDCGAtK(data_size_t k, const float* label, ...@@ -94,7 +94,7 @@ double DCGCalculator::CalDCGAtK(data_size_t k, const float* label,
[score](data_size_t a, data_size_t b) {return score[a] > score[b]; }); [score](data_size_t a, data_size_t b) {return score[a] > score[b]; });
if (k > num_data) { k = num_data; } if (k > num_data) { k = num_data; }
double dcg = 0.0; float dcg = 0.0f;
// calculate dcg // calculate dcg
for (data_size_t i = 0; i < k; ++i) { for (data_size_t i = 0; i < k; ++i) {
data_size_t idx = sorted_idx[i]; data_size_t idx = sorted_idx[i];
...@@ -104,7 +104,7 @@ double DCGCalculator::CalDCGAtK(data_size_t k, const float* label, ...@@ -104,7 +104,7 @@ double DCGCalculator::CalDCGAtK(data_size_t k, const float* label,
} }
void DCGCalculator::CalDCG(const std::vector<data_size_t>& ks, const float* label, void DCGCalculator::CalDCG(const std::vector<data_size_t>& ks, const float* label,
const score_t * score, data_size_t num_data, std::vector<double>* out) { const score_t * score, data_size_t num_data, std::vector<float>* out) {
// get sorted indices by score // get sorted indices by score
std::vector<data_size_t> sorted_idx; std::vector<data_size_t> sorted_idx;
for (data_size_t i = 0; i < num_data; ++i) { for (data_size_t i = 0; i < num_data; ++i) {
...@@ -113,7 +113,7 @@ void DCGCalculator::CalDCG(const std::vector<data_size_t>& ks, const float* labe ...@@ -113,7 +113,7 @@ void DCGCalculator::CalDCG(const std::vector<data_size_t>& ks, const float* labe
std::sort(sorted_idx.begin(), sorted_idx.end(), std::sort(sorted_idx.begin(), sorted_idx.end(),
[score](data_size_t a, data_size_t b) {return score[a] > score[b]; }); [score](data_size_t a, data_size_t b) {return score[a] > score[b]; });
double cur_result = 0.0; float cur_result = 0.0f;
data_size_t cur_left = 0; data_size_t cur_left = 0;
// calculate multi dcg by one pass // calculate multi dcg by one pass
for (size_t i = 0; i < ks.size(); ++i) { for (size_t i = 0; i < ks.size(); ++i) {
......
...@@ -16,9 +16,6 @@ namespace LightGBM { ...@@ -16,9 +16,6 @@ namespace LightGBM {
class NDCGMetric:public Metric { class NDCGMetric:public Metric {
public: public:
explicit NDCGMetric(const MetricConfig& config) { explicit NDCGMetric(const MetricConfig& config) {
early_stopping_round_ = config.early_stopping_round;
output_freq_ = config.output_freq;
the_bigger_the_better = true;
// get eval position // get eval position
for (auto k : config.eval_at) { for (auto k : config.eval_at) {
eval_at_.push_back(static_cast<data_size_t>(k)); eval_at_.push_back(static_cast<data_size_t>(k));
...@@ -26,8 +23,8 @@ public: ...@@ -26,8 +23,8 @@ public:
// initialize DCG calculator // initialize DCG calculator
DCGCalculator::Init(config.label_gain); DCGCalculator::Init(config.label_gain);
// get number of threads // get number of threads
#pragma omp parallel #pragma omp parallel
#pragma omp master #pragma omp master
{ {
num_threads_ = omp_get_num_threads(); num_threads_ = omp_get_num_threads();
} }
...@@ -36,7 +33,12 @@ public: ...@@ -36,7 +33,12 @@ public:
~NDCGMetric() { ~NDCGMetric() {
} }
void Init(const char* test_name, const Metadata& metadata, data_size_t num_data) override { void Init(const char* test_name, const Metadata& metadata, data_size_t num_data) override {
name = test_name; std::stringstream str_buf;
str_buf << test_name << "'s ";
for (auto k : eval_at_) {
str_buf << "NDCG@" + std::to_string(k) + " ";
}
name_ = str_buf.str();
num_data_ = num_data; num_data_ = num_data;
// get label // get label
label_ = metadata.label(); label_ = metadata.label();
...@@ -49,7 +51,7 @@ public: ...@@ -49,7 +51,7 @@ public:
// get query weights // get query weights
query_weights_ = metadata.query_weights(); query_weights_ = metadata.query_weights();
if (query_weights_ == nullptr) { if (query_weights_ == nullptr) {
sum_query_weights_ = static_cast<double>(num_queries_); sum_query_weights_ = static_cast<float>(num_queries_);
} else { } else {
sum_query_weights_ = 0.0f; sum_query_weights_ = 0.0f;
for (data_size_t i = 0; i < num_queries_; ++i) { for (data_size_t i = 0; i < num_queries_; ++i) {
...@@ -58,99 +60,96 @@ public: ...@@ -58,99 +60,96 @@ public:
} }
// cache the inverse max DCG for all querys, used to calculate NDCG // cache the inverse max DCG for all querys, used to calculate NDCG
for (data_size_t i = 0; i < num_queries_; ++i) { for (data_size_t i = 0; i < num_queries_; ++i) {
inverse_max_dcgs_.emplace_back(eval_at_.size(), 0.0); inverse_max_dcgs_.emplace_back(eval_at_.size(), 0.0f);
DCGCalculator::CalMaxDCG(eval_at_, label_ + query_boundaries_[i], DCGCalculator::CalMaxDCG(eval_at_, label_ + query_boundaries_[i],
query_boundaries_[i + 1] - query_boundaries_[i], query_boundaries_[i + 1] - query_boundaries_[i],
&inverse_max_dcgs_[i]); &inverse_max_dcgs_[i]);
for (size_t j = 0; j < inverse_max_dcgs_[i].size(); ++j) { for (size_t j = 0; j < inverse_max_dcgs_[i].size(); ++j) {
if (inverse_max_dcgs_[i][j] > 0.0) { if (inverse_max_dcgs_[i][j] > 0.0f) {
inverse_max_dcgs_[i][j] = 1.0 / inverse_max_dcgs_[i][j]; inverse_max_dcgs_[i][j] = 1.0f / inverse_max_dcgs_[i][j];
} } else {
else {
// marking negative for all negative querys. // marking negative for all negative querys.
// if one meet this query, it's ndcg will be set as -1. // if one meet this query, it's ndcg will be set as -1.
inverse_max_dcgs_[i][j] = -1.0; inverse_max_dcgs_[i][j] = -1.0f;
} }
} }
} }
} }
score_t PrintAndGetLoss(int iter, const score_t* score) const override { const char* GetName() const override {
if (early_stopping_round_ > 0 || (output_freq_ > 0 && iter % output_freq_ == 0)) { return name_.c_str();
// some buffers for multi-threading sum up }
std::vector<std::vector<double>> result_buffer_;
for (int i = 0; i < num_threads_; ++i) { bool is_bigger_better() const override {
result_buffer_.emplace_back(eval_at_.size(), 0.0); return true;
} }
std::vector<double> tmp_dcg(eval_at_.size(), 0.0);
if (query_weights_ == nullptr) { std::vector<score_t> Eval(const score_t* score) const override {
#pragma omp parallel for schedule(guided) firstprivate(tmp_dcg) // some buffers for multi-threading sum up
for (data_size_t i = 0; i < num_queries_; ++i) { std::vector<std::vector<float>> result_buffer_;
const int tid = omp_get_thread_num(); for (int i = 0; i < num_threads_; ++i) {
// if all doc in this query are all negative, let its NDCG=1 result_buffer_.emplace_back(eval_at_.size(), 0.0f);
if (inverse_max_dcgs_[i][0] <= 0.0) { }
for (size_t j = 0; j < eval_at_.size(); ++j) { std::vector<float> tmp_dcg(eval_at_.size(), 0.0f);
result_buffer_[tid][j] += 1.0; if (query_weights_ == nullptr) {
} #pragma omp parallel for schedule(guided) firstprivate(tmp_dcg)
} else { for (data_size_t i = 0; i < num_queries_; ++i) {
// calculate DCG const int tid = omp_get_thread_num();
DCGCalculator::CalDCG(eval_at_, label_ + query_boundaries_[i], // if all doc in this query are all negative, let its NDCG=1
score + query_boundaries_[i], if (inverse_max_dcgs_[i][0] <= 0.0f) {
query_boundaries_[i + 1] - query_boundaries_[i], &tmp_dcg); for (size_t j = 0; j < eval_at_.size(); ++j) {
// calculate NDCG result_buffer_[tid][j] += 1.0f;
for (size_t j = 0; j < eval_at_.size(); ++j) {
result_buffer_[tid][j] += tmp_dcg[j] * inverse_max_dcgs_[i][j];
}
} }
} } else {
} else { // calculate DCG
#pragma omp parallel for schedule(guided) firstprivate(tmp_dcg) DCGCalculator::CalDCG(eval_at_, label_ + query_boundaries_[i],
for (data_size_t i = 0; i < num_queries_; ++i) { score + query_boundaries_[i],
const int tid = omp_get_thread_num(); query_boundaries_[i + 1] - query_boundaries_[i], &tmp_dcg);
// if all doc in this query are all negative, let its NDCG=1 // calculate NDCG
if (inverse_max_dcgs_[i][0] <= 0.0) { for (size_t j = 0; j < eval_at_.size(); ++j) {
for (size_t j = 0; j < eval_at_.size(); ++j) { result_buffer_[tid][j] += tmp_dcg[j] * inverse_max_dcgs_[i][j];
result_buffer_[tid][j] += 1.0;
}
} else {
// calculate DCG
DCGCalculator::CalDCG(eval_at_, label_ + query_boundaries_[i],
score + query_boundaries_[i],
query_boundaries_[i + 1] - query_boundaries_[i], &tmp_dcg);
// calculate NDCG
for (size_t j = 0; j < eval_at_.size(); ++j) {
result_buffer_[tid][j] += tmp_dcg[j] * inverse_max_dcgs_[i][j] * query_weights_[i];
}
} }
} }
} }
// Get final average NDCG } else {
std::vector<double> result(eval_at_.size(), 0.0); #pragma omp parallel for schedule(guided) firstprivate(tmp_dcg)
std::stringstream result_ss; for (data_size_t i = 0; i < num_queries_; ++i) {
for (size_t j = 0; j < result.size(); ++j) { const int tid = omp_get_thread_num();
for (int i = 0; i < num_threads_; ++i) { // if all doc in this query are all negative, let its NDCG=1
result[j] += result_buffer_[i][j]; if (inverse_max_dcgs_[i][0] <= 0.0f) {
for (size_t j = 0; j < eval_at_.size(); ++j) {
result_buffer_[tid][j] += 1.0f;
}
} else {
// calculate DCG
DCGCalculator::CalDCG(eval_at_, label_ + query_boundaries_[i],
score + query_boundaries_[i],
query_boundaries_[i + 1] - query_boundaries_[i], &tmp_dcg);
// calculate NDCG
for (size_t j = 0; j < eval_at_.size(); ++j) {
result_buffer_[tid][j] += tmp_dcg[j] * inverse_max_dcgs_[i][j] * query_weights_[i];
}
} }
result[j] /= sum_query_weights_;
result_ss << "NDCG@" << eval_at_[j] << ":" << result[j] << "\t";
} }
if (output_freq_ > 0 && iter % output_freq_ == 0){ }
Log::Info("Iteration:%d, Test:%s, %s ", iter, name, result_ss.str().c_str()); // Get final average NDCG
std::vector<float> result(eval_at_.size(), 0.0f);
for (size_t j = 0; j < result.size(); ++j) {
for (int i = 0; i < num_threads_; ++i) {
result[j] += result_buffer_[i][j];
} }
return result[0]; result[j] /= sum_query_weights_;
} }
return 0.0f; return result;
} }
private: private:
/*! \brief Output frequently */
int output_freq_;
/*! \brief Number of data */ /*! \brief Number of data */
data_size_t num_data_; data_size_t num_data_;
/*! \brief Pointer of label */ /*! \brief Pointer of label */
const float* label_; const float* label_;
/*! \brief Name of test set */ /*! \brief Name of test set */
const char* name; std::string name_;
/*! \brief Query boundaries information */ /*! \brief Query boundaries information */
const data_size_t* query_boundaries_; const data_size_t* query_boundaries_;
/*! \brief Number of queries */ /*! \brief Number of queries */
...@@ -158,11 +157,11 @@ private: ...@@ -158,11 +157,11 @@ private:
/*! \brief Weights of queries */ /*! \brief Weights of queries */
const float* query_weights_; const float* query_weights_;
/*! \brief Sum weights of queries */ /*! \brief Sum weights of queries */
double sum_query_weights_; float sum_query_weights_;
/*! \brief Evaluate position of NDCG */ /*! \brief Evaluate position of NDCG */
std::vector<data_size_t> eval_at_; std::vector<data_size_t> eval_at_;
/*! \brief Cache the inverse max dcg for all queries */ /*! \brief Cache the inverse max dcg for all queries */
std::vector<std::vector<double>> inverse_max_dcgs_; std::vector<std::vector<float>> inverse_max_dcgs_;
/*! \brief Number of threads */ /*! \brief Number of threads */
int num_threads_; int num_threads_;
}; };
......
...@@ -15,25 +15,34 @@ namespace LightGBM { ...@@ -15,25 +15,34 @@ namespace LightGBM {
template<typename PointWiseLossCalculator> template<typename PointWiseLossCalculator>
class RegressionMetric: public Metric { class RegressionMetric: public Metric {
public: public:
explicit RegressionMetric(const MetricConfig& config) { explicit RegressionMetric(const MetricConfig&) {
early_stopping_round_ = config.early_stopping_round;
output_freq_ = config.output_freq;
the_bigger_the_better = false;
} }
virtual ~RegressionMetric() { virtual ~RegressionMetric() {
} }
const char* GetName() const override {
return name_.c_str();
}
bool is_bigger_better() const override {
return false;
}
void Init(const char* test_name, const Metadata& metadata, data_size_t num_data) override { void Init(const char* test_name, const Metadata& metadata, data_size_t num_data) override {
name = test_name; std::stringstream str_buf;
str_buf << test_name << "'s " << PointWiseLossCalculator::Name();
name_ = str_buf.str();
num_data_ = num_data; num_data_ = num_data;
// get label // get label
label_ = metadata.label(); label_ = metadata.label();
// get weights // get weights
weights_ = metadata.weights(); weights_ = metadata.weights();
if (weights_ == nullptr) { if (weights_ == nullptr) {
sum_weights_ = static_cast<double>(num_data_); sum_weights_ = static_cast<float>(num_data_);
} else { } else {
sum_weights_ = 0.0f; sum_weights_ = 0.0f;
for (data_size_t i = 0; i < num_data_; ++i) { for (data_size_t i = 0; i < num_data_; ++i) {
...@@ -41,30 +50,25 @@ public: ...@@ -41,30 +50,25 @@ public:
} }
} }
} }
score_t PrintAndGetLoss(int iter, const score_t* score) const override { std::vector<float> Eval(const score_t* score) const override {
if (early_stopping_round_ > 0 || (output_freq_ > 0 && iter % output_freq_ == 0)) { score_t sum_loss = 0.0f;
score_t sum_loss = 0.0; if (weights_ == nullptr) {
if (weights_ == nullptr) { #pragma omp parallel for schedule(static) reduction(+:sum_loss)
#pragma omp parallel for schedule(static) reduction(+:sum_loss) for (data_size_t i = 0; i < num_data_; ++i) {
for (data_size_t i = 0; i < num_data_; ++i) { // add loss
// add loss sum_loss += PointWiseLossCalculator::LossOnPoint(label_[i], score[i]);
sum_loss += PointWiseLossCalculator::LossOnPoint(label_[i], score[i]);
}
} else {
#pragma omp parallel for schedule(static) reduction(+:sum_loss)
for (data_size_t i = 0; i < num_data_; ++i) {
// add loss
sum_loss += PointWiseLossCalculator::LossOnPoint(label_[i], score[i]) * weights_[i];
}
} }
score_t loss = PointWiseLossCalculator::AverageLoss(sum_loss, sum_weights_); } else {
if (output_freq_ > 0 && iter % output_freq_ == 0){ #pragma omp parallel for schedule(static) reduction(+:sum_loss)
Log::Info("Iteration:%d, %s's %s : %f", iter, name, PointWiseLossCalculator::Name(), loss); for (data_size_t i = 0; i < num_data_; ++i) {
// add loss
sum_loss += PointWiseLossCalculator::LossOnPoint(label_[i], score[i]) * weights_[i];
} }
return loss;
} }
return 0.0f; score_t loss = PointWiseLossCalculator::AverageLoss(sum_loss, sum_weights_);
return std::vector<float>(1, loss);
} }
inline static score_t AverageLoss(score_t sum_loss, score_t sum_weights) { inline static score_t AverageLoss(score_t sum_loss, score_t sum_weights) {
...@@ -72,8 +76,6 @@ public: ...@@ -72,8 +76,6 @@ public:
} }
private: private:
/*! \brief Output frequency */
int output_freq_;
/*! \brief Number of data */ /*! \brief Number of data */
data_size_t num_data_; data_size_t num_data_;
/*! \brief Pointer of label */ /*! \brief Pointer of label */
...@@ -81,9 +83,9 @@ private: ...@@ -81,9 +83,9 @@ private:
/*! \brief Pointer of weighs */ /*! \brief Pointer of weighs */
const float* weights_; const float* weights_;
/*! \brief Sum weights */ /*! \brief Sum weights */
double sum_weights_; float sum_weights_;
/*! \brief Name of this test set */ /*! \brief Name of this test set */
const char* name; std::string name_;
}; };
/*! \brief L2 loss for regression task */ /*! \brief L2 loss for regression task */
......
...@@ -80,7 +80,7 @@ public: ...@@ -80,7 +80,7 @@ public:
} }
} }
double GetSigmoid() const override { float GetSigmoid() const override {
return sigmoid_; return sigmoid_;
} }
......
...@@ -23,7 +23,7 @@ public: ...@@ -23,7 +23,7 @@ public:
// initialize DCG calculator // initialize DCG calculator
DCGCalculator::Init(config.label_gain); DCGCalculator::Init(config.label_gain);
// copy lable gain to local // copy lable gain to local
std::vector<double> label_gain = config.label_gain; std::vector<float> label_gain = config.label_gain;
for (auto gain : label_gain) { for (auto gain : label_gain) {
label_gain_.push_back(static_cast<score_t>(gain)); label_gain_.push_back(static_cast<score_t>(gain));
} }
...@@ -194,7 +194,7 @@ public: ...@@ -194,7 +194,7 @@ public:
} }
} }
double GetSigmoid() const override { float GetSigmoid() const override {
// though we use sigmoid transform on objective // though we use sigmoid transform on objective
// for the prediction, we actually don't need to transform by sigmoid. // for the prediction, we actually don't need to transform by sigmoid.
// since we only need the ranking score. // since we only need the ranking score.
......
...@@ -38,9 +38,9 @@ public: ...@@ -38,9 +38,9 @@ public:
} }
} }
double GetSigmoid() const override { float GetSigmoid() const override {
// not sigmoid transform, return -1 // not sigmoid transform, return -1
return -1.0; return -1.0f;
} }
private: private:
......
...@@ -200,12 +200,12 @@ void DataParallelTreeLearner::FindBestThresholds() { ...@@ -200,12 +200,12 @@ void DataParallelTreeLearner::FindBestThresholds() {
void DataParallelTreeLearner::FindBestSplitsForLeaves() { void DataParallelTreeLearner::FindBestSplitsForLeaves() {
int smaller_best_feature = -1, larger_best_feature = -1; int smaller_best_feature = -1, larger_best_feature = -1;
SplitInfo smaller_best, larger_best; SplitInfo smaller_best, larger_best;
std::vector<double> gains; std::vector<float> gains;
// find local best split for smaller leaf // find local best split for smaller leaf
for (size_t i = 0; i < smaller_leaf_splits_->BestSplitPerFeature().size(); ++i) { for (size_t i = 0; i < smaller_leaf_splits_->BestSplitPerFeature().size(); ++i) {
gains.push_back(smaller_leaf_splits_->BestSplitPerFeature()[i].gain); gains.push_back(smaller_leaf_splits_->BestSplitPerFeature()[i].gain);
} }
smaller_best_feature = static_cast<int>(ArrayArgs<double>::ArgMax(gains)); smaller_best_feature = static_cast<int>(ArrayArgs<float>::ArgMax(gains));
smaller_best = smaller_leaf_splits_->BestSplitPerFeature()[smaller_best_feature]; smaller_best = smaller_leaf_splits_->BestSplitPerFeature()[smaller_best_feature];
// find local best split for larger leaf // find local best split for larger leaf
if (larger_leaf_splits_->LeafIndex() >= 0) { if (larger_leaf_splits_->LeafIndex() >= 0) {
...@@ -213,7 +213,7 @@ void DataParallelTreeLearner::FindBestSplitsForLeaves() { ...@@ -213,7 +213,7 @@ void DataParallelTreeLearner::FindBestSplitsForLeaves() {
for (size_t i = 0; i < larger_leaf_splits_->BestSplitPerFeature().size(); ++i) { for (size_t i = 0; i < larger_leaf_splits_->BestSplitPerFeature().size(); ++i) {
gains.push_back(larger_leaf_splits_->BestSplitPerFeature()[i].gain); gains.push_back(larger_leaf_splits_->BestSplitPerFeature()[i].gain);
} }
larger_best_feature = static_cast<int>(ArrayArgs<double>::ArgMax(gains)); larger_best_feature = static_cast<int>(ArrayArgs<float>::ArgMax(gains));
larger_best = larger_leaf_splits_->BestSplitPerFeature()[larger_best_feature]; larger_best = larger_leaf_splits_->BestSplitPerFeature()[larger_best_feature];
} }
......
...@@ -47,11 +47,11 @@ void FeatureParallelTreeLearner::FindBestSplitsForLeaves() { ...@@ -47,11 +47,11 @@ void FeatureParallelTreeLearner::FindBestSplitsForLeaves() {
int smaller_best_feature = -1, larger_best_feature = -1; int smaller_best_feature = -1, larger_best_feature = -1;
SplitInfo smaller_best, larger_best; SplitInfo smaller_best, larger_best;
// get best split at smaller leaf // get best split at smaller leaf
std::vector<double> gains; std::vector<float> gains;
for (size_t i = 0; i < smaller_leaf_splits_->BestSplitPerFeature().size(); ++i) { for (size_t i = 0; i < smaller_leaf_splits_->BestSplitPerFeature().size(); ++i) {
gains.push_back(smaller_leaf_splits_->BestSplitPerFeature()[i].gain); gains.push_back(smaller_leaf_splits_->BestSplitPerFeature()[i].gain);
} }
smaller_best_feature = static_cast<int>(ArrayArgs<double>::ArgMax(gains)); smaller_best_feature = static_cast<int>(ArrayArgs<float>::ArgMax(gains));
smaller_best = smaller_leaf_splits_->BestSplitPerFeature()[smaller_best_feature]; smaller_best = smaller_leaf_splits_->BestSplitPerFeature()[smaller_best_feature];
// get best split at larger leaf // get best split at larger leaf
if (larger_leaf_splits_->LeafIndex() >= 0) { if (larger_leaf_splits_->LeafIndex() >= 0) {
...@@ -59,7 +59,7 @@ void FeatureParallelTreeLearner::FindBestSplitsForLeaves() { ...@@ -59,7 +59,7 @@ void FeatureParallelTreeLearner::FindBestSplitsForLeaves() {
for (size_t i = 0; i < larger_leaf_splits_->BestSplitPerFeature().size(); ++i) { for (size_t i = 0; i < larger_leaf_splits_->BestSplitPerFeature().size(); ++i) {
gains.push_back(larger_leaf_splits_->BestSplitPerFeature()[i].gain); gains.push_back(larger_leaf_splits_->BestSplitPerFeature()[i].gain);
} }
larger_best_feature = static_cast<int>(ArrayArgs<double>::ArgMax(gains)); larger_best_feature = static_cast<int>(ArrayArgs<float>::ArgMax(gains));
larger_best = larger_leaf_splits_->BestSplitPerFeature()[larger_best_feature]; larger_best = larger_leaf_splits_->BestSplitPerFeature()[larger_best_feature];
} }
// sync global best info // sync global best info
......
...@@ -15,7 +15,7 @@ SerialTreeLearner::SerialTreeLearner(const TreeConfig& tree_config) ...@@ -15,7 +15,7 @@ SerialTreeLearner::SerialTreeLearner(const TreeConfig& tree_config)
// initialize with nullptr // initialize with nullptr
num_leaves_ = tree_config.num_leaves; num_leaves_ = tree_config.num_leaves;
min_num_data_one_leaf_ = static_cast<data_size_t>(tree_config.min_data_in_leaf); min_num_data_one_leaf_ = static_cast<data_size_t>(tree_config.min_data_in_leaf);
min_sum_hessian_one_leaf_ = static_cast<float>(tree_config.min_sum_hessian_in_leaf); min_sum_hessian_one_leaf_ = static_cast<score_t>(tree_config.min_sum_hessian_in_leaf);
feature_fraction_ = tree_config.feature_fraction; feature_fraction_ = tree_config.feature_fraction;
random_ = Random(tree_config.feature_fraction_seed); random_ = Random(tree_config.feature_fraction_seed);
histogram_pool_size_ = tree_config.histogram_pool_size; histogram_pool_size_ = tree_config.histogram_pool_size;
......
...@@ -41,11 +41,11 @@ public: ...@@ -41,11 +41,11 @@ public:
void AddPredictionToScore(score_t *out_score) const override { void AddPredictionToScore(score_t *out_score) const override {
#pragma omp parallel for schedule(guided) #pragma omp parallel for schedule(guided)
for (int i = 0; i < data_partition_->num_leaves(); ++i) { for (int i = 0; i < data_partition_->num_leaves(); ++i) {
double output = last_trained_tree_->LeafOutput(i); score_t output = last_trained_tree_->LeafOutput(i);
data_size_t* tmp_idx = nullptr; data_size_t* tmp_idx = nullptr;
data_size_t cnt_leaf_data = data_partition_->GetIndexOnLeaf(i, &tmp_idx); data_size_t cnt_leaf_data = data_partition_->GetIndexOnLeaf(i, &tmp_idx);
for (data_size_t j = 0; j < cnt_leaf_data; ++j) { for (data_size_t j = 0; j < cnt_leaf_data; ++j) {
out_score[tmp_idx[j]] += static_cast<score_t>(output); out_score[tmp_idx[j]] += output;
} }
} }
} }
...@@ -116,7 +116,7 @@ protected: ...@@ -116,7 +116,7 @@ protected:
/*! \brief mininal sum hessian on one leaf */ /*! \brief mininal sum hessian on one leaf */
score_t min_sum_hessian_one_leaf_; score_t min_sum_hessian_one_leaf_;
/*! \brief sub-feature fraction rate */ /*! \brief sub-feature fraction rate */
double feature_fraction_; float feature_fraction_;
/*! \brief training data partition on leaves */ /*! \brief training data partition on leaves */
DataPartition* data_partition_; DataPartition* data_partition_;
/*! \brief used for generate used features */ /*! \brief used for generate used features */
...@@ -160,7 +160,7 @@ protected: ...@@ -160,7 +160,7 @@ protected:
/*! \brief is_data_in_leaf_[i] != 0 means i-th data is marked */ /*! \brief is_data_in_leaf_[i] != 0 means i-th data is marked */
char* is_data_in_leaf_; char* is_data_in_leaf_;
/*! \brief max cache size(unit:GB) for historical histogram. < 0 means not limit */ /*! \brief max cache size(unit:GB) for historical histogram. < 0 means not limit */
double histogram_pool_size_; float histogram_pool_size_;
/*! \brief used to cache historical histogram to speed up*/ /*! \brief used to cache historical histogram to speed up*/
LRUPool<FeatureHistogram*> histogram_pool_; LRUPool<FeatureHistogram*> histogram_pool_;
/*! \brief max depth of tree model */ /*! \brief max depth of tree model */
...@@ -186,11 +186,11 @@ inline void SerialTreeLearner::FindBestSplitForLeaf(LeafSplits* leaf_splits) { ...@@ -186,11 +186,11 @@ inline void SerialTreeLearner::FindBestSplitForLeaf(LeafSplits* leaf_splits) {
if (leaf_splits == nullptr || leaf_splits->LeafIndex() < 0) { if (leaf_splits == nullptr || leaf_splits->LeafIndex() < 0) {
return; return;
} }
std::vector<double> gains; std::vector<float> gains;
for (size_t i = 0; i < leaf_splits->BestSplitPerFeature().size(); ++i) { for (size_t i = 0; i < leaf_splits->BestSplitPerFeature().size(); ++i) {
gains.push_back(leaf_splits->BestSplitPerFeature()[i].gain); gains.push_back(leaf_splits->BestSplitPerFeature()[i].gain);
} }
int best_feature = static_cast<int>(ArrayArgs<double>::ArgMax(gains)); int best_feature = static_cast<int>(ArrayArgs<float>::ArgMax(gains));
int leaf = leaf_splits->LeafIndex(); int leaf = leaf_splits->LeafIndex();
best_split_per_leaf_[leaf] = leaf_splits->BestSplitPerFeature()[best_feature]; best_split_per_leaf_[leaf] = leaf_splits->BestSplitPerFeature()[best_feature];
best_split_per_leaf_[leaf].feature = best_feature; best_split_per_leaf_[leaf].feature = best_feature;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment