Medial Code Documentation
Loading...
Searching...
No Matches
regression_objective.hpp
1#ifndef LIGHTGBM_OBJECTIVE_REGRESSION_OBJECTIVE_HPP_
2#define LIGHTGBM_OBJECTIVE_REGRESSION_OBJECTIVE_HPP_
3
4#include <LightGBM/objective_function.h>
5#include <LightGBM/meta.h>
6
7#include <LightGBM/utils/array_args.h>
8
9namespace LightGBM {
10
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);\
16 }\
17 const double float_pos = (1.0f - alpha) * cnt_data;\
18 const data_size_t pos = static_cast<data_size_t>(float_pos);\
19 if (pos < 1) {\
20 return ref_data[ArrayArgs<T>::ArgMax(ref_data)];\
21 } else if (pos >= cnt_data) {\
22 return ref_data[ArrayArgs<T>::ArgMin(ref_data)];\
23 } else {\
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);\
30 } else {\
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);\
35 }\
36 }\
37}\
38
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) {\
43 sorted_idx[i] = i;\
44 }\
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]);\
50 }\
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]);\
56 }\
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); \
63 } else {\
64 return static_cast<T>(v2);\
65 }\
66}\
67
72public:
73 explicit RegressionL2loss(const Config& config) {
74 sqrt_ = config.reg_sqrt;
75 }
76
77 explicit RegressionL2loss(const std::vector<std::string>& strs) {
78 sqrt_ = false;
79 for (auto str : strs) {
80 if (str == std::string("sqrt")) {
81 sqrt_ = true;
82 }
83 }
84 }
85
87 }
88
89 void Init(const Metadata& metadata, data_size_t num_data) override {
90 num_data_ = num_data;
91 label_ = metadata.label();
92 if (sqrt_) {
93 trans_label_.resize(num_data_);
94 #pragma omp parallel for schedule(static)
95 for (data_size_t i = 0; i < num_data; ++i) {
96 trans_label_[i] = Common::Sign(label_[i]) * std::sqrt(std::fabs(label_[i]));
97 }
98 label_ = trans_label_.data();
99 }
100 weights_ = metadata.weights();
101 }
102
103 void GetGradients(const double* score, score_t* gradients,
104 score_t* hessians) const override {
105 if (weights_ == nullptr) {
106 #pragma omp parallel for schedule(static)
107 for (data_size_t i = 0; i < num_data_; ++i) {
108 gradients[i] = static_cast<score_t>(score[i] - label_[i]);
109 hessians[i] = 1.0f;
110 }
111 } else {
112 #pragma omp parallel for schedule(static)
113 for (data_size_t i = 0; i < num_data_; ++i) {
114 gradients[i] = static_cast<score_t>((score[i] - label_[i]) * weights_[i]);
115 hessians[i] = static_cast<score_t>(weights_[i]);
116 }
117 }
118 }
119
120 const char* GetName() const override {
121 return "regression";
122 }
123
124 void ConvertOutput(const double* input, double* output) const override {
125 if (sqrt_) {
126 output[0] = Common::Sign(input[0]) * input[0] * input[0];
127 } else {
128 output[0] = input[0];
129 }
130 }
131
132 std::string ToString() const override {
133 std::stringstream str_buf;
134 str_buf << GetName();
135 if (sqrt_) {
136 str_buf << " sqrt";
137 }
138 return str_buf.str();
139 }
140
141 bool IsConstantHessian() const override {
142 if (weights_ == nullptr) {
143 return true;
144 } else {
145 return false;
146 }
147 }
148
149 double BoostFromScore(int) const override {
150 double suml = 0.0f;
151 double sumw = 0.0f;
152 if (weights_ != nullptr) {
153 #pragma omp parallel for schedule(static) reduction(+:suml, sumw)
154 for (data_size_t i = 0; i < num_data_; ++i) {
155 suml += label_[i] * weights_[i];
156 sumw += weights_[i];
157 }
158 } else {
159 sumw = static_cast<double>(num_data_);
160 #pragma omp parallel for schedule(static) reduction(+:suml)
161 for (data_size_t i = 0; i < num_data_; ++i) {
162 suml += label_[i];
163 }
164 }
165 return suml / sumw;
166 }
167
168protected:
169 bool sqrt_;
176 std::vector<label_t> trans_label_;
177};
178
183public:
184 explicit RegressionL1loss(const Config& config): RegressionL2loss(config) {
185 }
186
187 explicit RegressionL1loss(const std::vector<std::string>& strs): RegressionL2loss(strs) {
188 }
189
191
192 void GetGradients(const double* score, score_t* gradients,
193 score_t* hessians) const override {
194 if (weights_ == nullptr) {
195 #pragma omp parallel for schedule(static)
196 for (data_size_t i = 0; i < num_data_; ++i) {
197 const double diff = score[i] - label_[i];
198 gradients[i] = static_cast<score_t>(Common::Sign(diff));
199 hessians[i] = 1.0f;
200 }
201 } else {
202 #pragma omp parallel for schedule(static)
203 for (data_size_t i = 0; i < num_data_; ++i) {
204 const double diff = score[i] - label_[i];
205 gradients[i] = static_cast<score_t>(Common::Sign(diff) * weights_[i]);
206 hessians[i] = weights_[i];
207 }
208 }
209 }
210
211 double BoostFromScore(int) const override {
212 const double alpha = 0.5;
213 if (weights_ != nullptr) {
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);
217 #undef data_reader
218 #undef weight_reader
219 } else {
220 #define data_reader(i) (label_[i])
221 PercentileFun(label_t, data_reader, num_data_, alpha);
222 #undef data_reader
223 }
224 }
225
226 bool IsRenewTreeOutput() const override { return true; }
227
228 double RenewTreeOutput(double, const double* pred,
229 const data_size_t* index_mapper,
230 const data_size_t* bagging_mapper,
231 data_size_t num_data_in_leaf) const override {
232 const double alpha = 0.5;
233 if (weights_ == nullptr) {
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);
237 #undef data_reader
238 } else {
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);
241 #undef data_reader
242 }
243 } else {
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);
248 #undef data_reader
249 #undef weight_reader
250 } else {
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);
254 #undef data_reader
255 #undef weight_reader
256 }
257 }
258 }
259
260 double RenewTreeOutput(double, double pred,
261 const data_size_t* index_mapper,
262 const data_size_t* bagging_mapper,
263 data_size_t num_data_in_leaf) const override {
264 const double alpha = 0.5;
265 if (weights_ == nullptr) {
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);
269 #undef data_reader
270 } else {
271 #define data_reader(i) (label_[bagging_mapper[index_mapper[i]]] - pred)
272 PercentileFun(double, data_reader, num_data_in_leaf, alpha);
273 #undef data_reader
274 }
275 } else {
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);
280 #undef data_reader
281 #undef weight_reader
282 } else {
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);
286 #undef data_reader
287 #undef weight_reader
288 }
289 }
290 }
291
292 const char* GetName() const override {
293 return "regression_l1";
294 }
295};
296
301public:
302 explicit RegressionHuberLoss(const Config& config): RegressionL2loss(config) {
303 alpha_ = static_cast<double>(config.alpha);
304 if (sqrt_) {
305 Log::Warning("Cannot use sqrt transform in %s Regression, will auto disable it", GetName());
306 sqrt_ = false;
307 }
308 }
309
310 explicit RegressionHuberLoss(const std::vector<std::string>& strs): RegressionL2loss(strs) {
311 if (sqrt_) {
312 Log::Warning("Cannot use sqrt transform in %s Regression, will auto disable it", GetName());
313 sqrt_ = false;
314 }
315 }
316
318 }
319
320 void GetGradients(const double* score, score_t* gradients,
321 score_t* hessians) const override {
322 if (weights_ == nullptr) {
323 #pragma omp parallel for schedule(static)
324 for (data_size_t i = 0; i < num_data_; ++i) {
325 const double diff = score[i] - label_[i];
326 if (std::abs(diff) <= alpha_) {
327 gradients[i] = static_cast<score_t>(diff);
328 } else {
329 gradients[i] = static_cast<score_t>(Common::Sign(diff) * alpha_);
330 }
331 hessians[i] = 1.0f;
332 }
333 } else {
334 #pragma omp parallel for schedule(static)
335 for (data_size_t i = 0; i < num_data_; ++i) {
336 const double diff = score[i] - label_[i];
337 if (std::abs(diff) <= alpha_) {
338 gradients[i] = static_cast<score_t>(diff * weights_[i]);
339 } else {
340 gradients[i] = static_cast<score_t>(Common::Sign(diff) * weights_[i] * alpha_);
341 }
342 hessians[i] = static_cast<score_t>(weights_[i]);
343 }
344 }
345 }
346
347 const char* GetName() const override {
348 return "huber";
349 }
350
351 bool IsConstantHessian() const override {
352 return false;
353 }
354
355private:
357 double alpha_;
358};
359
360
361// http://research.microsoft.com/en-us/um/people/zhang/INRIA/Publis/Tutorial-Estim/node24.html
363public:
364 explicit RegressionFairLoss(const Config& config): RegressionL2loss(config) {
365 c_ = static_cast<double>(config.fair_c);
366 }
367
368 explicit RegressionFairLoss(const std::vector<std::string>& strs): RegressionL2loss(strs) {
369 }
370
372
373 void GetGradients(const double* score, score_t* gradients,
374 score_t* hessians) const override {
375 if (weights_ == nullptr) {
376 #pragma omp parallel for schedule(static)
377 for (data_size_t i = 0; i < num_data_; ++i) {
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_)));
381 }
382 } else {
383 #pragma omp parallel for schedule(static)
384 for (data_size_t i = 0; i < num_data_; ++i) {
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]);
388 }
389 }
390 }
391
392 const char* GetName() const override {
393 return "fair";
394 }
395
396 bool IsConstantHessian() const override {
397 return false;
398 }
399
400private:
402 double c_;
403};
404
405
410public:
411 explicit RegressionPoissonLoss(const Config& config): RegressionL2loss(config) {
412 max_delta_step_ = static_cast<double>(config.poisson_max_delta_step);
413 if (sqrt_) {
414 Log::Warning("Cannot use sqrt transform in %s Regression, will auto disable it", GetName());
415 sqrt_ = false;
416 }
417 }
418
419 explicit RegressionPoissonLoss(const std::vector<std::string>& strs): RegressionL2loss(strs) {
420 }
421
423
424 void Init(const Metadata& metadata, data_size_t num_data) override {
425 if (sqrt_) {
426 Log::Warning("Cannot use sqrt transform in %s Regression, will auto disable it", GetName());
427 sqrt_ = false;
428 }
429 RegressionL2loss::Init(metadata, num_data);
430 // Safety check of labels
431 label_t miny;
432 double sumy;
433 Common::ObtainMinMaxSum(label_, num_data_, &miny, (label_t*)nullptr, &sumy);
434 if (miny < 0.0f) {
435 Log::Fatal("[%s]: at least one target label is negative", GetName());
436 }
437 if (sumy == 0.0f) {
438 Log::Fatal("[%s]: sum of labels is zero", GetName());
439 }
440 }
441
442 /* Parametrize with unbounded internal score "f"; then
443 * loss = exp(f) - label * f
444 * grad = exp(f) - label
445 * hess = exp(f)
446 *
447 * And the output is exp(f); so the associated metric get s=exp(f)
448 * so that its loss = s - label * log(s); a little awkward maybe.
449 *
450 */
451 void GetGradients(const double* score, score_t* gradients,
452 score_t* hessians) const override {
453 if (weights_ == nullptr) {
454 #pragma omp parallel for schedule(static)
455 for (data_size_t i = 0; i < num_data_; ++i) {
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_));
458 }
459 } else {
460 #pragma omp parallel for schedule(static)
461 for (data_size_t i = 0; i < num_data_; ++i) {
462 gradients[i] = static_cast<score_t>((std::exp(score[i]) - label_[i]) * weights_[i]);
463 hessians[i] = static_cast<score_t>(std::exp(score[i] + max_delta_step_) * weights_[i]);
464 }
465 }
466 }
467
468 void ConvertOutput(const double* input, double* output) const override {
469 output[0] = std::exp(input[0]);
470 }
471
472 const char* GetName() const override {
473 return "poisson";
474 }
475
476 double BoostFromScore(int) const override {
477 return Common::SafeLog(RegressionL2loss::BoostFromScore(0));
478 }
479
480 bool IsConstantHessian() const override {
481 return false;
482 }
483
484private:
486 double max_delta_step_;
487};
488
490public:
491 explicit RegressionQuantileloss(const Config& config): RegressionL2loss(config) {
492 alpha_ = static_cast<score_t>(config.alpha);
493 CHECK(alpha_ > 0 && alpha_ < 1);
494 }
495
496 explicit RegressionQuantileloss(const std::vector<std::string>& strs): RegressionL2loss(strs) {
497 }
498
500
501 void GetGradients(const double* score, score_t* gradients,
502 score_t* hessians) const override {
503 if (weights_ == nullptr) {
504 #pragma omp parallel for schedule(static)
505 for (data_size_t i = 0; i < num_data_; ++i) {
506 score_t delta = static_cast<score_t>(score[i] - label_[i]);
507 if (delta >= 0) {
508 gradients[i] = (1.0f - alpha_);
509 } else {
510 gradients[i] = -alpha_;
511 }
512 hessians[i] = 1.0f;
513 }
514 } else {
515 #pragma omp parallel for schedule(static)
516 for (data_size_t i = 0; i < num_data_; ++i) {
517 score_t delta = static_cast<score_t>(score[i] - label_[i]);
518 if (delta >= 0) {
519 gradients[i] = static_cast<score_t>((1.0f - alpha_) * weights_[i]);
520 } else {
521 gradients[i] = static_cast<score_t>(-alpha_ * weights_[i]);
522 }
523 hessians[i] = static_cast<score_t>(weights_[i]);
524 }
525 }
526 }
527
528 const char* GetName() const override {
529 return "quantile";
530 }
531
532 double BoostFromScore(int) const override {
533 if (weights_ != nullptr) {
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_);
537 #undef data_reader
538 #undef weight_reader
539 } else {
540 #define data_reader(i) (label_[i])
541 PercentileFun(label_t, data_reader, num_data_, alpha_);
542 #undef data_reader
543 }
544 }
545
546 bool IsRenewTreeOutput() const override { return true; }
547
548 double RenewTreeOutput(double, const double* pred,
549 const data_size_t* index_mapper,
550 const data_size_t* bagging_mapper,
551 data_size_t num_data_in_leaf) const override {
552 if (weights_ == nullptr) {
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_);
556 #undef data_reader
557 } else {
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_);
560 #undef data_reader
561 }
562 } else {
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_);
567 #undef data_reader
568 #undef weight_reader
569 } else {
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_);
573 #undef data_reader
574 #undef weight_reader
575 }
576 }
577 }
578
579 double RenewTreeOutput(double, double pred,
580 const data_size_t* index_mapper,
581 const data_size_t* bagging_mapper,
582 data_size_t num_data_in_leaf) const override {
583 if (weights_ == nullptr) {
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_);
587 #undef data_reader
588 } else {
589 #define data_reader(i) (label_[bagging_mapper[index_mapper[i]]] - pred)
590 PercentileFun(double, data_reader, num_data_in_leaf, alpha_);
591 #undef data_reader
592 }
593 } else {
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_);
598 #undef data_reader
599 #undef weight_reader
600 } else {
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_);
604 #undef data_reader
605 #undef weight_reader
606 }
607 }
608 }
609
610private:
611 score_t alpha_;
612};
613
614
619public:
620 explicit RegressionMAPELOSS(const Config& config) : RegressionL1loss(config) {
621 }
622
623 explicit RegressionMAPELOSS(const std::vector<std::string>& strs) : RegressionL1loss(strs) {
624 }
625
627
628 void Init(const Metadata& metadata, data_size_t num_data) override {
629 RegressionL2loss::Init(metadata, num_data);
630 for (data_size_t i = 0; i < num_data_; ++i) {
631 if (std::fabs(label_[i]) < 1) {
632 Log::Warning("Met 'abs(label) < 1', will convert them to '1' in MAPE objective and metric");
633 break;
634 }
635 }
636 label_weight_.resize(num_data);
637 if (weights_ == nullptr) {
638 #pragma omp parallel for schedule(static)
639 for (data_size_t i = 0; i < num_data_; ++i) {
640 label_weight_[i] = 1.0f / std::max(1.0f, std::fabs(label_[i]));
641 }
642 } else {
643 #pragma omp parallel for schedule(static)
644 for (data_size_t i = 0; i < num_data_; ++i) {
645 label_weight_[i] = 1.0f / std::max(1.0f, std::fabs(label_[i])) * weights_[i];
646 }
647 }
648 }
649
650 void GetGradients(const double* score, score_t* gradients,
651 score_t* hessians) const override {
652 if (weights_ == nullptr) {
653 #pragma omp parallel for schedule(static)
654 for (data_size_t i = 0; i < num_data_; ++i) {
655 const double diff = score[i] - label_[i];
656 gradients[i] = static_cast<score_t>(Common::Sign(diff) * label_weight_[i]);
657 hessians[i] = 1.0f;
658 }
659 } else {
660 #pragma omp parallel for schedule(static)
661 for (data_size_t i = 0; i < num_data_; ++i) {
662 const double diff = score[i] - label_[i];
663 gradients[i] = static_cast<score_t>(Common::Sign(diff) * label_weight_[i]);
664 hessians[i] = weights_[i];
665 }
666 }
667 }
668
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);
674 #undef data_reader
675 #undef weight_reader
676 }
677
678 bool IsRenewTreeOutput() const override { return true; }
679
680 double RenewTreeOutput(double, const double* pred,
681 const data_size_t* index_mapper,
682 const data_size_t* bagging_mapper,
683 data_size_t num_data_in_leaf) const override {
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);
689 #undef data_reader
690 #undef weight_reader
691 } else {
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);
695 #undef data_reader
696 #undef weight_reader
697 }
698 }
699
700 double RenewTreeOutput(double, double pred,
701 const data_size_t* index_mapper,
702 const data_size_t* bagging_mapper,
703 data_size_t num_data_in_leaf) const override {
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);
709 #undef data_reader
710 #undef weight_reader
711 } else {
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);
715 #undef data_reader
716 #undef weight_reader
717 }
718 }
719
720 const char* GetName() const override {
721 return "mape";
722 }
723
724 bool IsConstantHessian() const override {
725 return true;
726 }
727
728private:
729 std::vector<label_t> label_weight_;
730};
731
732
733
738public:
739 explicit RegressionGammaLoss(const Config& config) : RegressionPoissonLoss(config) {
740 }
741
742 explicit RegressionGammaLoss(const std::vector<std::string>& strs) : RegressionPoissonLoss(strs) {
743 }
744
746
747 void GetGradients(const double* score, score_t* gradients,
748 score_t* hessians) const override {
749 if (weights_ == nullptr) {
750 #pragma omp parallel for schedule(static)
751 for (data_size_t i = 0; i < num_data_; ++i) {
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]));
754 }
755 } else {
756 #pragma omp parallel for schedule(static)
757 for (data_size_t i = 0; i < num_data_; ++i) {
758 gradients[i] = static_cast<score_t>(1.0 - label_[i] / std::exp(score[i]) * weights_[i]);
759 hessians[i] = static_cast<score_t>(label_[i] / std::exp(score[i]) * weights_[i]);
760 }
761 }
762 }
763
764 const char* GetName() const override {
765 return "gamma";
766 }
767};
768
773public:
774 explicit RegressionTweedieLoss(const Config& config) : RegressionPoissonLoss(config) {
775 rho_ = config.tweedie_variance_power;
776 }
777
778 explicit RegressionTweedieLoss(const std::vector<std::string>& strs) : RegressionPoissonLoss(strs) {
779 }
780
782
783 void GetGradients(const double* score, score_t* gradients,
784 score_t* hessians) const override {
785 if (weights_ == nullptr) {
786 #pragma omp parallel for schedule(static)
787 for (data_size_t i = 0; i < num_data_; ++i) {
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]));
791 }
792 } else {
793 #pragma omp parallel for schedule(static)
794 for (data_size_t i = 0; i < num_data_; ++i) {
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]);
798 }
799 }
800 }
801
802 const char* GetName() const override {
803 return "tweedie";
804 }
805
806private:
807 double rho_;
808};
809
810#undef PercentileFun
811#undef WeightedPercentileFun
812
813} // namespace LightGBM
814#endif // LightGBM_OBJECTIVE_REGRESSION_OBJECTIVE_HPP_
This class is used to store some meta(non-feature) data for training data, e.g. labels,...
Definition dataset.h:36
const label_t * label() const
Get pointer of label.
Definition dataset.h:113
const label_t * weights() const
Get weights, if not exists, will return nullptr.
Definition dataset.h:146
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
Definition config.h:27