Use bst_float consistently throughout (#1824)
* Fix various typos * Add override to functions that are overridden gcc gives warnings about functions that are being overridden by not being marked as oveirridden. This fixes it. * Use bst_float consistently Use bst_float for all the variables that involve weight, leaf value, gradient, hessian, gain, loss_chg, predictions, base_margin, feature values. In some cases, when due to additions and so on the value can take a larger value, double is used. This ensures that type conversions are minimal and reduces loss of precision.
This commit is contained in:
@@ -21,9 +21,9 @@ DMLC_REGISTRY_FILE_TAG(elementwise_metric);
|
||||
*/
|
||||
template<typename Derived>
|
||||
struct EvalEWiseBase : public Metric {
|
||||
float Eval(const std::vector<float>& preds,
|
||||
const MetaInfo& info,
|
||||
bool distributed) const override {
|
||||
bst_float Eval(const std::vector<bst_float>& preds,
|
||||
const MetaInfo& info,
|
||||
bool distributed) const override {
|
||||
CHECK_NE(info.labels.size(), 0) << "label set cannot be empty";
|
||||
CHECK_EQ(preds.size(), info.labels.size())
|
||||
<< "label and prediction size not match, "
|
||||
@@ -32,7 +32,7 @@ struct EvalEWiseBase : public Metric {
|
||||
double sum = 0.0, wsum = 0.0;
|
||||
#pragma omp parallel for reduction(+: sum, wsum) schedule(static)
|
||||
for (omp_ulong i = 0; i < ndata; ++i) {
|
||||
const float wt = info.GetWeight(i);
|
||||
const bst_float wt = info.GetWeight(i);
|
||||
sum += static_cast<const Derived*>(this)->EvalRow(info.labels[i], preds[i]) * wt;
|
||||
wsum += wt;
|
||||
}
|
||||
@@ -48,13 +48,13 @@ struct EvalEWiseBase : public Metric {
|
||||
* \param label label of current instance
|
||||
* \param pred prediction value of current instance
|
||||
*/
|
||||
inline float EvalRow(float label, float pred) const;
|
||||
inline bst_float EvalRow(bst_float label, bst_float pred) const;
|
||||
/*!
|
||||
* \brief to be overridden by subclass, final transformation
|
||||
* \param esum the sum statistics returned by EvalRow
|
||||
* \param wsum sum of weight
|
||||
*/
|
||||
inline static float GetFinal(float esum, float wsum) {
|
||||
inline static bst_float GetFinal(bst_float esum, bst_float wsum) {
|
||||
return esum / wsum;
|
||||
}
|
||||
};
|
||||
@@ -63,11 +63,11 @@ struct EvalRMSE : public EvalEWiseBase<EvalRMSE> {
|
||||
const char *Name() const override {
|
||||
return "rmse";
|
||||
}
|
||||
inline float EvalRow(float label, float pred) const {
|
||||
float diff = label - pred;
|
||||
inline bst_float EvalRow(bst_float label, bst_float pred) const {
|
||||
bst_float diff = label - pred;
|
||||
return diff * diff;
|
||||
}
|
||||
inline static float GetFinal(float esum, float wsum) {
|
||||
inline static bst_float GetFinal(bst_float esum, bst_float wsum) {
|
||||
return std::sqrt(esum / wsum);
|
||||
}
|
||||
};
|
||||
@@ -76,7 +76,7 @@ struct EvalMAE : public EvalEWiseBase<EvalMAE> {
|
||||
const char *Name() const override {
|
||||
return "mae";
|
||||
}
|
||||
inline float EvalRow(float label, float pred) const {
|
||||
inline bst_float EvalRow(bst_float label, bst_float pred) const {
|
||||
return std::abs(label - pred);
|
||||
}
|
||||
};
|
||||
@@ -85,9 +85,9 @@ struct EvalLogLoss : public EvalEWiseBase<EvalLogLoss> {
|
||||
const char *Name() const override {
|
||||
return "logloss";
|
||||
}
|
||||
inline float EvalRow(float y, float py) const {
|
||||
const float eps = 1e-16f;
|
||||
const float pneg = 1.0f - py;
|
||||
inline bst_float EvalRow(bst_float y, bst_float py) const {
|
||||
const bst_float eps = 1e-16f;
|
||||
const bst_float pneg = 1.0f - py;
|
||||
if (py < eps) {
|
||||
return -y * std::log(eps) - (1.0f - y) * std::log(1.0f - eps);
|
||||
} else if (pneg < eps) {
|
||||
@@ -115,12 +115,12 @@ struct EvalError : public EvalEWiseBase<EvalError> {
|
||||
const char *Name() const override {
|
||||
return name_.c_str();
|
||||
}
|
||||
inline float EvalRow(float label, float pred) const {
|
||||
inline bst_float EvalRow(bst_float label, bst_float pred) const {
|
||||
// assume label is in [0,1]
|
||||
return pred > threshold_ ? 1.0f - label : label;
|
||||
}
|
||||
protected:
|
||||
float threshold_;
|
||||
bst_float threshold_;
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
@@ -128,8 +128,8 @@ struct EvalPoissionNegLogLik : public EvalEWiseBase<EvalPoissionNegLogLik> {
|
||||
const char *Name() const override {
|
||||
return "poisson-nloglik";
|
||||
}
|
||||
inline float EvalRow(float y, float py) const {
|
||||
const float eps = 1e-16f;
|
||||
inline bst_float EvalRow(bst_float y, bst_float py) const {
|
||||
const bst_float eps = 1e-16f;
|
||||
if (py < eps) py = eps;
|
||||
return common::LogGamma(y + 1.0f) + py - std::log(py) * y;
|
||||
}
|
||||
@@ -139,12 +139,12 @@ struct EvalGammaDeviance : public EvalEWiseBase<EvalGammaDeviance> {
|
||||
const char *Name() const override {
|
||||
return "gamma-deviance";
|
||||
}
|
||||
inline float EvalRow(float label, float pred) const {
|
||||
float epsilon = 1.0e-9;
|
||||
float tmp = label / (pred + epsilon);
|
||||
inline bst_float EvalRow(bst_float label, bst_float pred) const {
|
||||
bst_float epsilon = 1.0e-9;
|
||||
bst_float tmp = label / (pred + epsilon);
|
||||
return tmp - std::log(tmp) - 1;
|
||||
}
|
||||
inline static float GetFinal(float esum, float wsum) {
|
||||
inline static bst_float GetFinal(bst_float esum, bst_float wsum) {
|
||||
return 2 * esum;
|
||||
}
|
||||
};
|
||||
@@ -153,12 +153,12 @@ struct EvalGammaNLogLik: public EvalEWiseBase<EvalGammaNLogLik> {
|
||||
const char *Name() const override {
|
||||
return "gamma-nloglik";
|
||||
}
|
||||
inline float EvalRow(float y, float py) const {
|
||||
float psi = 1.0;
|
||||
float theta = -1. / py;
|
||||
float a = psi;
|
||||
float b = -std::log(-theta);
|
||||
float c = 1. / psi * std::log(y/psi) - std::log(y) - common::LogGamma(1. / psi);
|
||||
inline bst_float EvalRow(bst_float y, bst_float py) const {
|
||||
bst_float psi = 1.0;
|
||||
bst_float theta = -1. / py;
|
||||
bst_float a = psi;
|
||||
bst_float b = -std::log(-theta);
|
||||
bst_float c = 1. / psi * std::log(y/psi) - std::log(y) - common::LogGamma(1. / psi);
|
||||
return -((y * theta - b) / a + c);
|
||||
}
|
||||
};
|
||||
@@ -177,14 +177,14 @@ struct EvalTweedieNLogLik: public EvalEWiseBase<EvalTweedieNLogLik> {
|
||||
const char *Name() const override {
|
||||
return name_.c_str();
|
||||
}
|
||||
inline float EvalRow(float y, float p) const {
|
||||
float a = y * std::exp((1 - rho_) * std::log(p)) / (1 - rho_);
|
||||
float b = std::exp((2 - rho_) * std::log(p)) / (2 - rho_);
|
||||
inline bst_float EvalRow(bst_float y, bst_float p) const {
|
||||
bst_float a = y * std::exp((1 - rho_) * std::log(p)) / (1 - rho_);
|
||||
bst_float b = std::exp((2 - rho_) * std::log(p)) / (2 - rho_);
|
||||
return -a + b;
|
||||
}
|
||||
protected:
|
||||
std::string name_;
|
||||
float rho_;
|
||||
bst_float rho_;
|
||||
};
|
||||
|
||||
XGBOOST_REGISTER_METRIC(RMSE, "rmse")
|
||||
|
||||
@@ -20,9 +20,9 @@ DMLC_REGISTRY_FILE_TAG(multiclass_metric);
|
||||
*/
|
||||
template<typename Derived>
|
||||
struct EvalMClassBase : public Metric {
|
||||
float Eval(const std::vector<float> &preds,
|
||||
const MetaInfo &info,
|
||||
bool distributed) const override {
|
||||
bst_float Eval(const std::vector<bst_float> &preds,
|
||||
const MetaInfo &info,
|
||||
bool distributed) const override {
|
||||
CHECK_NE(info.labels.size(), 0) << "label set cannot be empty";
|
||||
CHECK(preds.size() % info.labels.size() == 0)
|
||||
<< "label and prediction size not match";
|
||||
@@ -35,7 +35,7 @@ struct EvalMClassBase : public Metric {
|
||||
int label_error = 0;
|
||||
#pragma omp parallel for reduction(+: sum, wsum) schedule(static)
|
||||
for (bst_omp_uint i = 0; i < ndata; ++i) {
|
||||
const float wt = info.GetWeight(i);
|
||||
const bst_float wt = info.GetWeight(i);
|
||||
int label = static_cast<int>(info.labels[i]);
|
||||
if (label >= 0 && label < static_cast<int>(nclass)) {
|
||||
sum += Derived::EvalRow(label,
|
||||
@@ -63,15 +63,15 @@ struct EvalMClassBase : public Metric {
|
||||
* \param pred prediction value of current instance
|
||||
* \param nclass number of class in the prediction
|
||||
*/
|
||||
inline static float EvalRow(int label,
|
||||
const float *pred,
|
||||
size_t nclass);
|
||||
inline static bst_float EvalRow(int label,
|
||||
const bst_float *pred,
|
||||
size_t nclass);
|
||||
/*!
|
||||
* \brief to be overridden by subclass, final transformation
|
||||
* \param esum the sum statistics returned by EvalRow
|
||||
* \param wsum sum of weight
|
||||
*/
|
||||
inline static float GetFinal(float esum, float wsum) {
|
||||
inline static bst_float GetFinal(bst_float esum, bst_float wsum) {
|
||||
return esum / wsum;
|
||||
}
|
||||
// used to store error message
|
||||
@@ -83,9 +83,9 @@ struct EvalMatchError : public EvalMClassBase<EvalMatchError> {
|
||||
const char* Name() const override {
|
||||
return "merror";
|
||||
}
|
||||
inline static float EvalRow(int label,
|
||||
const float *pred,
|
||||
size_t nclass) {
|
||||
inline static bst_float EvalRow(int label,
|
||||
const bst_float *pred,
|
||||
size_t nclass) {
|
||||
return common::FindMaxIndex(pred, pred + nclass) != pred + static_cast<int>(label);
|
||||
}
|
||||
};
|
||||
@@ -95,10 +95,10 @@ struct EvalMultiLogLoss : public EvalMClassBase<EvalMultiLogLoss> {
|
||||
const char* Name() const override {
|
||||
return "mlogloss";
|
||||
}
|
||||
inline static float EvalRow(int label,
|
||||
const float *pred,
|
||||
size_t nclass) {
|
||||
const float eps = 1e-16f;
|
||||
inline static bst_float EvalRow(int label,
|
||||
const bst_float *pred,
|
||||
size_t nclass) {
|
||||
const bst_float eps = 1e-16f;
|
||||
size_t k = static_cast<size_t>(label);
|
||||
if (pred[k] > eps) {
|
||||
return -std::log(pred[k]);
|
||||
|
||||
@@ -26,15 +26,15 @@ struct EvalAMS : public Metric {
|
||||
os << "ams@" << ratio_;
|
||||
name_ = os.str();
|
||||
}
|
||||
float Eval(const std::vector<float> &preds,
|
||||
const MetaInfo &info,
|
||||
bool distributed) const override {
|
||||
bst_float Eval(const std::vector<bst_float> &preds,
|
||||
const MetaInfo &info,
|
||||
bool distributed) const override {
|
||||
CHECK(!distributed) << "metric AMS do not support distributed evaluation";
|
||||
using namespace std; // NOLINT(*)
|
||||
|
||||
const bst_omp_uint ndata = static_cast<bst_omp_uint>(info.labels.size());
|
||||
CHECK_EQ(info.weights.size(), ndata) << "we need weight to evaluate ams";
|
||||
std::vector<std::pair<float, unsigned> > rec(ndata);
|
||||
std::vector<std::pair<bst_float, unsigned> > rec(ndata);
|
||||
|
||||
#pragma omp parallel for schedule(static)
|
||||
for (bst_omp_uint i = 0; i < ndata; ++i) {
|
||||
@@ -48,7 +48,7 @@ struct EvalAMS : public Metric {
|
||||
double s_tp = 0.0, b_fp = 0.0, tams = 0.0;
|
||||
for (unsigned i = 0; i < static_cast<unsigned>(ndata-1) && i < ntop; ++i) {
|
||||
const unsigned ridx = rec[i].second;
|
||||
const float wt = info.weights[ridx];
|
||||
const bst_float wt = info.weights[ridx];
|
||||
if (info.labels[ridx] > 0.5f) {
|
||||
s_tp += wt;
|
||||
} else {
|
||||
@@ -63,10 +63,10 @@ struct EvalAMS : public Metric {
|
||||
}
|
||||
}
|
||||
if (ntop == ndata) {
|
||||
LOG(INFO) << "best-ams-ratio=" << static_cast<float>(thresindex) / ndata;
|
||||
return static_cast<float>(tams);
|
||||
LOG(INFO) << "best-ams-ratio=" << static_cast<bst_float>(thresindex) / ndata;
|
||||
return static_cast<bst_float>(tams);
|
||||
} else {
|
||||
return static_cast<float>(
|
||||
return static_cast<bst_float>(
|
||||
sqrt(2 * ((s_tp + b_fp + br) * log(1.0 + s_tp/(b_fp + br)) - s_tp)));
|
||||
}
|
||||
}
|
||||
@@ -82,9 +82,9 @@ struct EvalAMS : public Metric {
|
||||
|
||||
/*! \brief Area Under Curve, for both classification and rank */
|
||||
struct EvalAuc : public Metric {
|
||||
float Eval(const std::vector<float> &preds,
|
||||
const MetaInfo &info,
|
||||
bool distributed) const override {
|
||||
bst_float Eval(const std::vector<bst_float> &preds,
|
||||
const MetaInfo &info,
|
||||
bool distributed) const override {
|
||||
CHECK_NE(info.labels.size(), 0) << "label set cannot be empty";
|
||||
CHECK_EQ(preds.size(), info.labels.size())
|
||||
<< "label size predict size not match";
|
||||
@@ -96,12 +96,12 @@ struct EvalAuc : public Metric {
|
||||
<< "EvalAuc: group structure must match number of prediction";
|
||||
const bst_omp_uint ngroup = static_cast<bst_omp_uint>(gptr.size() - 1);
|
||||
// sum statistics
|
||||
double sum_auc = 0.0f;
|
||||
bst_float sum_auc = 0.0f;
|
||||
int auc_error = 0;
|
||||
#pragma omp parallel reduction(+:sum_auc)
|
||||
{
|
||||
// each thread takes a local rec
|
||||
std::vector< std::pair<float, unsigned> > rec;
|
||||
std::vector< std::pair<bst_float, unsigned> > rec;
|
||||
#pragma omp for schedule(static)
|
||||
for (bst_omp_uint k = 0; k < ngroup; ++k) {
|
||||
rec.clear();
|
||||
@@ -113,8 +113,8 @@ struct EvalAuc : public Metric {
|
||||
double sum_pospair = 0.0;
|
||||
double sum_npos = 0.0, sum_nneg = 0.0, buf_pos = 0.0, buf_neg = 0.0;
|
||||
for (size_t j = 0; j < rec.size(); ++j) {
|
||||
const float wt = info.GetWeight(rec[j].second);
|
||||
const float ctr = info.labels[rec[j].second];
|
||||
const bst_float wt = info.GetWeight(rec[j].second);
|
||||
const bst_float ctr = info.labels[rec[j].second];
|
||||
// keep bucketing predictions in same bucket
|
||||
if (j != 0 && rec[j].first != rec[j - 1].first) {
|
||||
sum_pospair += buf_neg * (sum_npos + buf_pos *0.5);
|
||||
@@ -140,14 +140,14 @@ struct EvalAuc : public Metric {
|
||||
CHECK(!auc_error)
|
||||
<< "AUC: the dataset only contains pos or neg samples";
|
||||
if (distributed) {
|
||||
float dat[2];
|
||||
dat[0] = static_cast<float>(sum_auc);
|
||||
dat[1] = static_cast<float>(ngroup);
|
||||
bst_float dat[2];
|
||||
dat[0] = static_cast<bst_float>(sum_auc);
|
||||
dat[1] = static_cast<bst_float>(ngroup);
|
||||
// approximately estimate auc using mean
|
||||
rabit::Allreduce<rabit::op::Sum>(dat, 2);
|
||||
return dat[0] / dat[1];
|
||||
} else {
|
||||
return static_cast<float>(sum_auc) / ngroup;
|
||||
return static_cast<bst_float>(sum_auc) / ngroup;
|
||||
}
|
||||
}
|
||||
const char* Name() const override {
|
||||
@@ -158,9 +158,9 @@ struct EvalAuc : public Metric {
|
||||
/*! \brief Evaluate rank list */
|
||||
struct EvalRankList : public Metric {
|
||||
public:
|
||||
float Eval(const std::vector<float> &preds,
|
||||
const MetaInfo &info,
|
||||
bool distributed) const override {
|
||||
bst_float Eval(const std::vector<bst_float> &preds,
|
||||
const MetaInfo &info,
|
||||
bool distributed) const override {
|
||||
CHECK_EQ(preds.size(), info.labels.size())
|
||||
<< "label size predict size not match";
|
||||
// quick consistency when group is not available
|
||||
@@ -176,7 +176,7 @@ struct EvalRankList : public Metric {
|
||||
#pragma omp parallel reduction(+:sum_metric)
|
||||
{
|
||||
// each thread takes a local rec
|
||||
std::vector< std::pair<float, unsigned> > rec;
|
||||
std::vector< std::pair<bst_float, unsigned> > rec;
|
||||
#pragma omp for schedule(static)
|
||||
for (bst_omp_uint k = 0; k < ngroup; ++k) {
|
||||
rec.clear();
|
||||
@@ -187,14 +187,14 @@ struct EvalRankList : public Metric {
|
||||
}
|
||||
}
|
||||
if (distributed) {
|
||||
float dat[2];
|
||||
dat[0] = static_cast<float>(sum_metric);
|
||||
dat[1] = static_cast<float>(ngroup);
|
||||
bst_float dat[2];
|
||||
dat[0] = static_cast<bst_float>(sum_metric);
|
||||
dat[1] = static_cast<bst_float>(ngroup);
|
||||
// approximately estimate the metric using mean
|
||||
rabit::Allreduce<rabit::op::Sum>(dat, 2);
|
||||
return dat[0] / dat[1];
|
||||
} else {
|
||||
return static_cast<float>(sum_metric) / ngroup;
|
||||
return static_cast<bst_float>(sum_metric) / ngroup;
|
||||
}
|
||||
}
|
||||
const char* Name() const override {
|
||||
@@ -221,7 +221,7 @@ struct EvalRankList : public Metric {
|
||||
}
|
||||
}
|
||||
/*! \return evaluation metric, given the pair_sort record, (pred,label) */
|
||||
virtual float EvalMetric(std::vector<std::pair<float, unsigned> > &pair_sort) const = 0; // NOLINT(*)
|
||||
virtual bst_float EvalMetric(std::vector<std::pair<bst_float, unsigned> > &pair_sort) const = 0; // NOLINT(*)
|
||||
|
||||
protected:
|
||||
unsigned topn_;
|
||||
@@ -235,14 +235,14 @@ struct EvalPrecision : public EvalRankList{
|
||||
explicit EvalPrecision(const char *name) : EvalRankList("pre", name) {}
|
||||
|
||||
protected:
|
||||
virtual float EvalMetric(std::vector< std::pair<float, unsigned> > &rec) const {
|
||||
virtual bst_float EvalMetric(std::vector< std::pair<bst_float, unsigned> > &rec) const {
|
||||
// calculate Precision
|
||||
std::sort(rec.begin(), rec.end(), common::CmpFirst);
|
||||
unsigned nhit = 0;
|
||||
for (size_t j = 0; j < rec.size() && j < this->topn_; ++j) {
|
||||
nhit += (rec[j].second != 0);
|
||||
}
|
||||
return static_cast<float>(nhit) / topn_;
|
||||
return static_cast<bst_float>(nhit) / topn_;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -252,7 +252,7 @@ struct EvalNDCG : public EvalRankList{
|
||||
explicit EvalNDCG(const char *name) : EvalRankList("ndcg", name) {}
|
||||
|
||||
protected:
|
||||
inline float CalcDCG(const std::vector<std::pair<float, unsigned> > &rec) const {
|
||||
inline bst_float CalcDCG(const std::vector<std::pair<bst_float, unsigned> > &rec) const {
|
||||
double sumdcg = 0.0;
|
||||
for (size_t i = 0; i < rec.size() && i < this->topn_; ++i) {
|
||||
const unsigned rel = rec[i].second;
|
||||
@@ -260,13 +260,13 @@ struct EvalNDCG : public EvalRankList{
|
||||
sumdcg += ((1 << rel) - 1) / std::log2(i + 2.0);
|
||||
}
|
||||
}
|
||||
return static_cast<float>(sumdcg);
|
||||
return sumdcg;
|
||||
}
|
||||
virtual float EvalMetric(std::vector<std::pair<float, unsigned> > &rec) const { // NOLINT(*)
|
||||
virtual bst_float EvalMetric(std::vector<std::pair<bst_float, unsigned> > &rec) const { // NOLINT(*)
|
||||
std::stable_sort(rec.begin(), rec.end(), common::CmpFirst);
|
||||
float dcg = this->CalcDCG(rec);
|
||||
bst_float dcg = this->CalcDCG(rec);
|
||||
std::stable_sort(rec.begin(), rec.end(), common::CmpSecond);
|
||||
float idcg = this->CalcDCG(rec);
|
||||
bst_float idcg = this->CalcDCG(rec);
|
||||
if (idcg == 0.0f) {
|
||||
if (minus_) {
|
||||
return 0.0f;
|
||||
@@ -284,7 +284,7 @@ struct EvalMAP : public EvalRankList {
|
||||
explicit EvalMAP(const char *name) : EvalRankList("map", name) {}
|
||||
|
||||
protected:
|
||||
virtual float EvalMetric(std::vector< std::pair<float, unsigned> > &rec) const {
|
||||
virtual bst_float EvalMetric(std::vector< std::pair<bst_float, unsigned> > &rec) const {
|
||||
std::sort(rec.begin(), rec.end(), common::CmpFirst);
|
||||
unsigned nhits = 0;
|
||||
double sumap = 0.0;
|
||||
@@ -292,13 +292,13 @@ struct EvalMAP : public EvalRankList {
|
||||
if (rec[i].second != 0) {
|
||||
nhits += 1;
|
||||
if (i < this->topn_) {
|
||||
sumap += static_cast<float>(nhits) / (i + 1);
|
||||
sumap += static_cast<bst_float>(nhits) / (i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nhits != 0) {
|
||||
sumap /= nhits;
|
||||
return static_cast<float>(sumap);
|
||||
return static_cast<bst_float>(sumap);
|
||||
} else {
|
||||
if (minus_) {
|
||||
return 0.0f;
|
||||
|
||||
Reference in New Issue
Block a user