1#ifndef LIGHTGBM_OBJECTIVE_REGRESSION_OBJECTIVE_HPP_
2#define LIGHTGBM_OBJECTIVE_REGRESSION_OBJECTIVE_HPP_
4#include <LightGBM/objective_function.h>
5#include <LightGBM/meta.h>
7#include <LightGBM/utils/array_args.h>
11#define PercentileFun(T, data_reader, cnt_data, alpha) {\
12 if (cnt_data <= 1) { return data_reader(0); }\
13 std::vector<T> ref_data(cnt_data);\
14 for (data_size_t i = 0; i < cnt_data; ++i) {\
15 ref_data[i] = data_reader(i);\
17 const double float_pos = (1.0f - alpha) * cnt_data;\
18 const data_size_t pos = static_cast<data_size_t>(float_pos);\
20 return ref_data[ArrayArgs<T>::ArgMax(ref_data)];\
21 } else if (pos >= cnt_data) {\
22 return ref_data[ArrayArgs<T>::ArgMin(ref_data)];\
24 const double bias = float_pos - pos;\
25 if (pos > cnt_data / 2) {\
26 ArrayArgs<T>::ArgMaxAtK(&ref_data, 0, cnt_data, pos - 1);\
27 T v1 = ref_data[pos - 1];\
28 T v2 = ref_data[pos + ArrayArgs<T>::ArgMax(ref_data.data() + pos, cnt_data - pos)];\
29 return static_cast<T>(v1 - (v1 - v2) * bias);\
31 ArrayArgs<T>::ArgMaxAtK(&ref_data, 0, cnt_data, pos);\
32 T v2 = ref_data[pos];\
33 T v1 = ref_data[ArrayArgs<T>::ArgMin(ref_data.data(), pos)];\
34 return static_cast<T>(v1 - (v1 - v2) * bias);\
39#define WeightedPercentileFun(T, data_reader, weight_reader, cnt_data, alpha) {\
40 if (cnt_data <= 1) { return data_reader(0); }\
41 std::vector<data_size_t> sorted_idx(cnt_data);\
42 for (data_size_t i = 0; i < cnt_data; ++i) {\
45 std::stable_sort(sorted_idx.begin(), sorted_idx.end(), [=](data_size_t a, data_size_t b) {return data_reader(a) < data_reader(b); });\
46 std::vector<double> weighted_cdf(cnt_data);\
47 weighted_cdf[0] = weight_reader(sorted_idx[0]);\
48 for (data_size_t i = 1; i < cnt_data; ++i) {\
49 weighted_cdf[i] = weighted_cdf[i - 1] + weight_reader(sorted_idx[i]);\
51 double threshold = weighted_cdf[cnt_data - 1] * alpha;\
52 size_t pos = std::upper_bound(weighted_cdf.begin(), weighted_cdf.end(), threshold) - weighted_cdf.begin();\
53 pos = std::min(pos, static_cast<size_t>(cnt_data -1));\
54 if (pos == 0 || pos == static_cast<size_t>(cnt_data - 1)) {\
55 return data_reader(sorted_idx[pos]);\
57 CHECK(threshold >= weighted_cdf[pos - 1]);\
58 CHECK(threshold < weighted_cdf[pos]);\
59 T v1 = data_reader(sorted_idx[pos - 1]);\
60 T v2 = data_reader(sorted_idx[pos]);\
61 if(weighted_cdf[pos + 1] - weighted_cdf[pos] > kEpsilon){\
62 return static_cast<T>((threshold - weighted_cdf[pos]) / (weighted_cdf[pos + 1] - weighted_cdf[pos]) * (v2 - v1) + v1); \
64 return static_cast<T>(v2);\
74 sqrt_ = config.reg_sqrt;
79 for (
auto str : strs) {
80 if (str == std::string(
"sqrt")) {
94 #pragma omp parallel for schedule(static)
96 trans_label_[i] = Common::Sign(
label_[i]) * std::sqrt(std::fabs(
label_[i]));
98 label_ = trans_label_.data();
104 score_t* hessians)
const override {
106 #pragma omp parallel for schedule(static)
112 #pragma omp parallel for schedule(static)
120 const char* GetName()
const override {
124 void ConvertOutput(
const double* input,
double* output)
const override {
126 output[0] = Common::Sign(input[0]) * input[0] * input[0];
128 output[0] = input[0];
132 std::string ToString()
const override {
133 std::stringstream str_buf;
134 str_buf << GetName();
138 return str_buf.str();
141 bool IsConstantHessian()
const override {
149 double BoostFromScore(
int)
const override {
153 #pragma omp parallel for schedule(static) reduction(+:suml, sumw)
160 #pragma omp parallel for schedule(static) reduction(+:suml)
176 std::vector<label_t> trans_label_;
193 score_t* hessians)
const override {
195 #pragma omp parallel for schedule(static)
197 const double diff = score[i] -
label_[i];
198 gradients[i] =
static_cast<score_t>(Common::Sign(diff));
202 #pragma omp parallel for schedule(static)
204 const double diff = score[i] -
label_[i];
211 double BoostFromScore(
int)
const override {
212 const double alpha = 0.5;
214 #define data_reader(i) (label_[i])
215 #define weight_reader(i) (weights_[i])
216 WeightedPercentileFun(
label_t, data_reader, weight_reader,
num_data_, alpha);
220 #define data_reader(i) (label_[i])
226 bool IsRenewTreeOutput()
const override {
return true; }
228 double RenewTreeOutput(
double,
const double* pred,
232 const double alpha = 0.5;
234 if (bagging_mapper ==
nullptr) {
235 #define data_reader(i) (label_[index_mapper[i]] - pred[index_mapper[i]])
236 PercentileFun(
double, data_reader, num_data_in_leaf, alpha);
239 #define data_reader(i) (label_[bagging_mapper[index_mapper[i]]] - pred[bagging_mapper[index_mapper[i]]])
240 PercentileFun(
double, data_reader, num_data_in_leaf, alpha);
244 if (bagging_mapper ==
nullptr) {
245 #define data_reader(i) (label_[index_mapper[i]] - pred[index_mapper[i]])
246 #define weight_reader(i) (weights_[index_mapper[i]])
247 WeightedPercentileFun(
double, data_reader, weight_reader, num_data_in_leaf, alpha);
251 #define data_reader(i) (label_[bagging_mapper[index_mapper[i]]] - pred[bagging_mapper[index_mapper[i]]])
252 #define weight_reader(i) (weights_[bagging_mapper[index_mapper[i]]])
253 WeightedPercentileFun(
double, data_reader, weight_reader, num_data_in_leaf, alpha);
260 double RenewTreeOutput(
double,
double pred,
264 const double alpha = 0.5;
266 if (bagging_mapper ==
nullptr) {
267 #define data_reader(i) (label_[index_mapper[i]] - pred)
268 PercentileFun(
double, data_reader, num_data_in_leaf, alpha);
271 #define data_reader(i) (label_[bagging_mapper[index_mapper[i]]] - pred)
272 PercentileFun(
double, data_reader, num_data_in_leaf, alpha);
276 if (bagging_mapper ==
nullptr) {
277 #define data_reader(i) (label_[index_mapper[i]] - pred)
278 #define weight_reader(i) (weights_[index_mapper[i]])
279 WeightedPercentileFun(
double, data_reader, weight_reader, num_data_in_leaf, alpha);
283 #define data_reader(i) (label_[bagging_mapper[index_mapper[i]]] - pred)
284 #define weight_reader(i) (weights_[bagging_mapper[index_mapper[i]]])
285 WeightedPercentileFun(
double, data_reader, weight_reader, num_data_in_leaf, alpha);
292 const char* GetName()
const override {
293 return "regression_l1";
303 alpha_ =
static_cast<double>(config.alpha);
305 Log::Warning(
"Cannot use sqrt transform in %s Regression, will auto disable it", GetName());
312 Log::Warning(
"Cannot use sqrt transform in %s Regression, will auto disable it", GetName());
321 score_t* hessians)
const override {
323 #pragma omp parallel for schedule(static)
325 const double diff = score[i] -
label_[i];
326 if (std::abs(diff) <= alpha_) {
327 gradients[i] =
static_cast<score_t>(diff);
329 gradients[i] =
static_cast<score_t>(Common::Sign(diff) * alpha_);
334 #pragma omp parallel for schedule(static)
336 const double diff = score[i] -
label_[i];
337 if (std::abs(diff) <= alpha_) {
340 gradients[i] =
static_cast<score_t>(Common::Sign(diff) *
weights_[i] * alpha_);
347 const char* GetName()
const override {
351 bool IsConstantHessian()
const override {
365 c_ =
static_cast<double>(config.fair_c);
374 score_t* hessians)
const override {
376 #pragma omp parallel for schedule(static)
378 const double x = score[i] -
label_[i];
379 gradients[i] =
static_cast<score_t>(c_ * x / (std::fabs(x) + c_));
380 hessians[i] =
static_cast<score_t>(c_ * c_ / ((std::fabs(x) + c_) * (std::fabs(x) + c_)));
383 #pragma omp parallel for schedule(static)
385 const double x = score[i] -
label_[i];
386 gradients[i] =
static_cast<score_t>(c_ * x / (std::fabs(x) + c_) *
weights_[i]);
387 hessians[i] =
static_cast<score_t>(c_ * c_ / ((std::fabs(x) + c_) * (std::fabs(x) + c_)) *
weights_[i]);
392 const char* GetName()
const override {
396 bool IsConstantHessian()
const override {
412 max_delta_step_ =
static_cast<double>(config.poisson_max_delta_step);
414 Log::Warning(
"Cannot use sqrt transform in %s Regression, will auto disable it", GetName());
426 Log::Warning(
"Cannot use sqrt transform in %s Regression, will auto disable it", GetName());
435 Log::Fatal(
"[%s]: at least one target label is negative", GetName());
438 Log::Fatal(
"[%s]: sum of labels is zero", GetName());
452 score_t* hessians)
const override {
454 #pragma omp parallel for schedule(static)
456 gradients[i] =
static_cast<score_t>(std::exp(score[i]) -
label_[i]);
457 hessians[i] =
static_cast<score_t>(std::exp(score[i] + max_delta_step_));
460 #pragma omp parallel for schedule(static)
463 hessians[i] =
static_cast<score_t>(std::exp(score[i] + max_delta_step_) *
weights_[i]);
468 void ConvertOutput(
const double* input,
double* output)
const override {
469 output[0] = std::exp(input[0]);
472 const char* GetName()
const override {
476 double BoostFromScore(
int)
const override {
477 return Common::SafeLog(RegressionL2loss::BoostFromScore(0));
480 bool IsConstantHessian()
const override {
486 double max_delta_step_;
492 alpha_ =
static_cast<score_t>(config.alpha);
493 CHECK(alpha_ > 0 && alpha_ < 1);
502 score_t* hessians)
const override {
504 #pragma omp parallel for schedule(static)
508 gradients[i] = (1.0f - alpha_);
510 gradients[i] = -alpha_;
515 #pragma omp parallel for schedule(static)
528 const char* GetName()
const override {
532 double BoostFromScore(
int)
const override {
534 #define data_reader(i) (label_[i])
535 #define weight_reader(i) (weights_[i])
536 WeightedPercentileFun(
label_t, data_reader, weight_reader,
num_data_, alpha_);
540 #define data_reader(i) (label_[i])
546 bool IsRenewTreeOutput()
const override {
return true; }
548 double RenewTreeOutput(
double,
const double* pred,
553 if (bagging_mapper ==
nullptr) {
554 #define data_reader(i) (label_[index_mapper[i]] - pred[index_mapper[i]])
555 PercentileFun(
double, data_reader, num_data_in_leaf, alpha_);
558 #define data_reader(i) (label_[bagging_mapper[index_mapper[i]]] - pred[bagging_mapper[index_mapper[i]]])
559 PercentileFun(
double, data_reader, num_data_in_leaf, alpha_);
563 if (bagging_mapper ==
nullptr) {
564 #define data_reader(i) (label_[index_mapper[i]] - pred[index_mapper[i]])
565 #define weight_reader(i) (weights_[index_mapper[i]])
566 WeightedPercentileFun(
double, data_reader, weight_reader, num_data_in_leaf, alpha_);
570 #define data_reader(i) (label_[bagging_mapper[index_mapper[i]]] - pred[bagging_mapper[index_mapper[i]]])
571 #define weight_reader(i) (weights_[bagging_mapper[index_mapper[i]]])
572 WeightedPercentileFun(
double, data_reader, weight_reader, num_data_in_leaf, alpha_);
579 double RenewTreeOutput(
double,
double pred,
584 if (bagging_mapper ==
nullptr) {
585 #define data_reader(i) (label_[index_mapper[i]] - pred)
586 PercentileFun(
double, data_reader, num_data_in_leaf, alpha_);
589 #define data_reader(i) (label_[bagging_mapper[index_mapper[i]]] - pred)
590 PercentileFun(
double, data_reader, num_data_in_leaf, alpha_);
594 if (bagging_mapper ==
nullptr) {
595 #define data_reader(i) (label_[index_mapper[i]] - pred)
596 #define weight_reader(i) (weights_[index_mapper[i]])
597 WeightedPercentileFun(
double, data_reader, weight_reader, num_data_in_leaf, alpha_);
601 #define data_reader(i) (label_[bagging_mapper[index_mapper[i]]] - pred)
602 #define weight_reader(i) (weights_[bagging_mapper[index_mapper[i]]])
603 WeightedPercentileFun(
double, data_reader, weight_reader, num_data_in_leaf, alpha_);
631 if (std::fabs(
label_[i]) < 1) {
632 Log::Warning(
"Met 'abs(label) < 1', will convert them to '1' in MAPE objective and metric");
636 label_weight_.resize(num_data);
638 #pragma omp parallel for schedule(static)
640 label_weight_[i] = 1.0f / std::max(1.0f, std::fabs(
label_[i]));
643 #pragma omp parallel for schedule(static)
645 label_weight_[i] = 1.0f / std::max(1.0f, std::fabs(
label_[i])) *
weights_[i];
651 score_t* hessians)
const override {
653 #pragma omp parallel for schedule(static)
655 const double diff = score[i] -
label_[i];
656 gradients[i] =
static_cast<score_t>(Common::Sign(diff) * label_weight_[i]);
660 #pragma omp parallel for schedule(static)
662 const double diff = score[i] -
label_[i];
663 gradients[i] =
static_cast<score_t>(Common::Sign(diff) * label_weight_[i]);
669 double BoostFromScore(
int)
const override {
670 const double alpha = 0.5;
671 #define data_reader(i) (label_[i])
672 #define weight_reader(i) (label_weight_[i])
673 WeightedPercentileFun(
label_t, data_reader, weight_reader,
num_data_, alpha);
678 bool IsRenewTreeOutput()
const override {
return true; }
680 double RenewTreeOutput(
double,
const double* pred,
684 const double alpha = 0.5;
685 if (bagging_mapper ==
nullptr) {
686 #define data_reader(i) (label_[index_mapper[i]] - pred[index_mapper[i]])
687 #define weight_reader(i) (label_weight_[index_mapper[i]])
688 WeightedPercentileFun(
double, data_reader, weight_reader, num_data_in_leaf, alpha);
692 #define data_reader(i) (label_[bagging_mapper[index_mapper[i]]] - pred[bagging_mapper[index_mapper[i]]])
693 #define weight_reader(i) (label_weight_[bagging_mapper[index_mapper[i]]])
694 WeightedPercentileFun(
double, data_reader, weight_reader, num_data_in_leaf, alpha);
700 double RenewTreeOutput(
double,
double pred,
704 const double alpha = 0.5;
705 if (bagging_mapper ==
nullptr) {
706 #define data_reader(i) (label_[index_mapper[i]] - pred)
707 #define weight_reader(i) (label_weight_[index_mapper[i]])
708 WeightedPercentileFun(
double, data_reader, weight_reader, num_data_in_leaf, alpha);
712 #define data_reader(i) (label_[bagging_mapper[index_mapper[i]]] - pred)
713 #define weight_reader(i) (label_weight_[bagging_mapper[index_mapper[i]]])
714 WeightedPercentileFun(
double, data_reader, weight_reader, num_data_in_leaf, alpha);
720 const char* GetName()
const override {
724 bool IsConstantHessian()
const override {
729 std::vector<label_t> label_weight_;
748 score_t* hessians)
const override {
750 #pragma omp parallel for schedule(static)
752 gradients[i] =
static_cast<score_t>(1.0 -
label_[i] / std::exp(score[i]));
753 hessians[i] =
static_cast<score_t>(
label_[i] / std::exp(score[i]));
756 #pragma omp parallel for schedule(static)
764 const char* GetName()
const override {
775 rho_ = config.tweedie_variance_power;
784 score_t* hessians)
const override {
786 #pragma omp parallel for schedule(static)
788 gradients[i] =
static_cast<score_t>(-
label_[i] * std::exp((1 - rho_) * score[i]) + std::exp((2 - rho_) * score[i]));
789 hessians[i] =
static_cast<score_t>(-
label_[i] * (1 - rho_) * std::exp((1 - rho_) * score[i]) +
790 (2 - rho_) * std::exp((2 - rho_) * score[i]));
793 #pragma omp parallel for schedule(static)
795 gradients[i] =
static_cast<score_t>((-
label_[i] * std::exp((1 - rho_) * score[i]) + std::exp((2 - rho_) * score[i])) *
weights_[i]);
796 hessians[i] =
static_cast<score_t>((-
label_[i] * (1 - rho_) * std::exp((1 - rho_) * score[i]) +
797 (2 - rho_) * std::exp((2 - rho_) * score[i])) *
weights_[i]);
802 const char* GetName()
const override {
811#undef WeightedPercentileFun
The interface of Objective Function.
Definition objective_function.h:13
Definition regression_objective.hpp:362
void GetGradients(const double *score, score_t *gradients, score_t *hessians) const override
calculating first order derivative of loss function
Definition regression_objective.hpp:373
Objective function for Gamma regression.
Definition regression_objective.hpp:737
void GetGradients(const double *score, score_t *gradients, score_t *hessians) const override
calculating first order derivative of loss function
Definition regression_objective.hpp:747
Huber regression loss.
Definition regression_objective.hpp:300
void GetGradients(const double *score, score_t *gradients, score_t *hessians) const override
calculating first order derivative of loss function
Definition regression_objective.hpp:320
L1 regression loss.
Definition regression_objective.hpp:182
void GetGradients(const double *score, score_t *gradients, score_t *hessians) const override
calculating first order derivative of loss function
Definition regression_objective.hpp:192
Objective function for regression.
Definition regression_objective.hpp:71
const label_t * weights_
Pointer of weights.
Definition regression_objective.hpp:175
const label_t * label_
Pointer of label.
Definition regression_objective.hpp:173
void Init(const Metadata &metadata, data_size_t num_data) override
Initialize.
Definition regression_objective.hpp:89
void GetGradients(const double *score, score_t *gradients, score_t *hessians) const override
calculating first order derivative of loss function
Definition regression_objective.hpp:103
data_size_t num_data_
Number of data.
Definition regression_objective.hpp:171
Mape Regression Loss.
Definition regression_objective.hpp:618
void Init(const Metadata &metadata, data_size_t num_data) override
Initialize.
Definition regression_objective.hpp:628
void GetGradients(const double *score, score_t *gradients, score_t *hessians) const override
calculating first order derivative of loss function
Definition regression_objective.hpp:650
Objective function for Poisson regression.
Definition regression_objective.hpp:409
void Init(const Metadata &metadata, data_size_t num_data) override
Initialize.
Definition regression_objective.hpp:424
void GetGradients(const double *score, score_t *gradients, score_t *hessians) const override
calculating first order derivative of loss function
Definition regression_objective.hpp:451
Definition regression_objective.hpp:489
void GetGradients(const double *score, score_t *gradients, score_t *hessians) const override
calculating first order derivative of loss function
Definition regression_objective.hpp:501
Objective function for Tweedie regression.
Definition regression_objective.hpp:772
void GetGradients(const double *score, score_t *gradients, score_t *hessians) const override
calculating first order derivative of loss function
Definition regression_objective.hpp:783
desc and descl2 fields must be written in reStructuredText format
Definition application.h:10
float score_t
Type of score, and gradients.
Definition meta.h:26
float label_t
Type of metadata, include weight and label.
Definition meta.h:33
int32_t data_size_t
Type of data size, it is better to use signed type.
Definition meta.h:14