Medial Code Documentation
Loading...
Searching...
No Matches
regression_metric.hpp
1#ifndef LIGHTGBM_METRIC_REGRESSION_METRIC_HPP_
2#define LIGHTGBM_METRIC_REGRESSION_METRIC_HPP_
3
4#include <LightGBM/metric.h>
5
6#include <LightGBM/utils/log.h>
7
8#include <cmath>
9
10namespace LightGBM {
15template<typename PointWiseLossCalculator>
16class RegressionMetric: public Metric {
17public:
18 explicit RegressionMetric(const Config& config) :config_(config) {
19 }
20
21 virtual ~RegressionMetric() {
22 }
23
24 const std::vector<std::string>& GetName() const override {
25 return name_;
26 }
27
28 double factor_to_bigger_better() const override {
29 return -1.0f;
30 }
31
32 void Init(const Metadata& metadata, data_size_t num_data) override {
33 name_.emplace_back(PointWiseLossCalculator::Name());
34 num_data_ = num_data;
35 // get label
36 label_ = metadata.label();
37 // get weights
38 weights_ = metadata.weights();
39 if (weights_ == nullptr) {
40 sum_weights_ = static_cast<double>(num_data_);
41 } else {
42 sum_weights_ = 0.0f;
43 for (data_size_t i = 0; i < num_data_; ++i) {
44 sum_weights_ += weights_[i];
45 }
46 }
47 for (data_size_t i = 0; i < num_data_; ++i) {
48 PointWiseLossCalculator::CheckLabel(label_[i]);
49 }
50 }
51
52 std::vector<double> Eval(const double* score, const ObjectiveFunction* objective) const override {
53 double sum_loss = 0.0f;
54 if (objective == nullptr) {
55 if (weights_ == nullptr) {
56 #pragma omp parallel for schedule(static) reduction(+:sum_loss)
57 for (data_size_t i = 0; i < num_data_; ++i) {
58 // add loss
59 sum_loss += PointWiseLossCalculator::LossOnPoint(label_[i], score[i], config_);
60 }
61 } else {
62 #pragma omp parallel for schedule(static) reduction(+:sum_loss)
63 for (data_size_t i = 0; i < num_data_; ++i) {
64 // add loss
65 sum_loss += PointWiseLossCalculator::LossOnPoint(label_[i], score[i], config_) * weights_[i];
66 }
67 }
68 } else {
69 if (weights_ == nullptr) {
70 #pragma omp parallel for schedule(static) reduction(+:sum_loss)
71 for (data_size_t i = 0; i < num_data_; ++i) {
72 // add loss
73 double t = 0;
74 objective->ConvertOutput(&score[i], &t);
75 sum_loss += PointWiseLossCalculator::LossOnPoint(label_[i], t, config_);
76 }
77 } else {
78 #pragma omp parallel for schedule(static) reduction(+:sum_loss)
79 for (data_size_t i = 0; i < num_data_; ++i) {
80 // add loss
81 double t = 0;
82 objective->ConvertOutput(&score[i], &t);
83 sum_loss += PointWiseLossCalculator::LossOnPoint(label_[i], t, config_) * weights_[i];
84 }
85 }
86 }
87 double loss = PointWiseLossCalculator::AverageLoss(sum_loss, sum_weights_);
88 return std::vector<double>(1, loss);
89 }
90
91 inline static double AverageLoss(double sum_loss, double sum_weights) {
92 return sum_loss / sum_weights;
93 }
94
95 inline static void CheckLabel(label_t) {
96 }
97
98private:
100 data_size_t num_data_;
102 const label_t* label_;
104 const label_t* weights_;
106 double sum_weights_;
108 Config config_;
109 std::vector<std::string> name_;
110};
111
113class RMSEMetric: public RegressionMetric<RMSEMetric> {
114public:
115 explicit RMSEMetric(const Config& config) :RegressionMetric<RMSEMetric>(config) {}
116
117 inline static double LossOnPoint(label_t label, double score, const Config&) {
118 return (score - label)*(score - label);
119 }
120
121 inline static double AverageLoss(double sum_loss, double sum_weights) {
122 // need sqrt the result for RMSE loss
123 return std::sqrt(sum_loss / sum_weights);
124 }
125
126 inline static const char* Name() {
127 return "rmse";
128 }
129};
130
132class L2Metric: public RegressionMetric<L2Metric> {
133public:
134 explicit L2Metric(const Config& config) :RegressionMetric<L2Metric>(config) {}
135
136 inline static double LossOnPoint(label_t label, double score, const Config&) {
137 return (score - label)*(score - label);
138 }
139
140 inline static const char* Name() {
141 return "l2";
142 }
143};
144
146class QuantileMetric : public RegressionMetric<QuantileMetric> {
147public:
148 explicit QuantileMetric(const Config& config) :RegressionMetric<QuantileMetric>(config) {
149 }
150
151 inline static double LossOnPoint(label_t label, double score, const Config& config) {
152 double delta = label - score;
153 if (delta < 0) {
154 return (config.alpha - 1.0f) * delta;
155 } else {
156 return config.alpha * delta;
157 }
158 }
159
160 inline static const char* Name() {
161 return "quantile";
162 }
163};
164
165
167class L1Metric: public RegressionMetric<L1Metric> {
168public:
169 explicit L1Metric(const Config& config) :RegressionMetric<L1Metric>(config) {}
170
171 inline static double LossOnPoint(label_t label, double score, const Config&) {
172 return std::fabs(score - label);
173 }
174 inline static const char* Name() {
175 return "l1";
176 }
177};
178
180class HuberLossMetric: public RegressionMetric<HuberLossMetric> {
181public:
182 explicit HuberLossMetric(const Config& config) :RegressionMetric<HuberLossMetric>(config) {
183 }
184
185 inline static double LossOnPoint(label_t label, double score, const Config& config) {
186 const double diff = score - label;
187 if (std::abs(diff) <= config.alpha) {
188 return 0.5f * diff * diff;
189 } else {
190 return config.alpha * (std::abs(diff) - 0.5f * config.alpha);
191 }
192 }
193
194 inline static const char* Name() {
195 return "huber";
196 }
197};
198
200// http://research.microsoft.com/en-us/um/people/zhang/INRIA/Publis/Tutorial-Estim/node24.html
201class FairLossMetric: public RegressionMetric<FairLossMetric> {
202public:
203 explicit FairLossMetric(const Config& config) :RegressionMetric<FairLossMetric>(config) {
204 }
205
206 inline static double LossOnPoint(label_t label, double score, const Config& config) {
207 const double x = std::fabs(score - label);
208 const double c = config.fair_c;
209 return c * x - c * c * std::log(1.0f + x / c);
210 }
211
212 inline static const char* Name() {
213 return "fair";
214 }
215};
216
218class PoissonMetric: public RegressionMetric<PoissonMetric> {
219public:
220 explicit PoissonMetric(const Config& config) :RegressionMetric<PoissonMetric>(config) {
221 }
222
223 inline static double LossOnPoint(label_t label, double score, const Config&) {
224 const double eps = 1e-10f;
225 if (score < eps) {
226 score = eps;
227 }
228 return score - label * std::log(score);
229 }
230 inline static const char* Name() {
231 return "poisson";
232 }
233};
234
235
237class MAPEMetric : public RegressionMetric<MAPEMetric> {
238public:
239 explicit MAPEMetric(const Config& config) :RegressionMetric<MAPEMetric>(config) {
240 }
241
242 inline static double LossOnPoint(label_t label, double score, const Config&) {
243 return std::fabs((label - score)) / std::max(1.0f, std::fabs(label));
244 }
245 inline static const char* Name() {
246 return "mape";
247 }
248};
249
250class GammaMetric : public RegressionMetric<GammaMetric> {
251public:
252 explicit GammaMetric(const Config& config) :RegressionMetric<GammaMetric>(config) {
253 }
254
255 inline static double LossOnPoint(label_t label, double score, const Config&) {
256 const double psi = 1.0;
257 const double theta = -1.0 / score;
258 const double a = psi;
259 const double b = -Common::SafeLog(-theta);
260 const double c = 1. / psi * Common::SafeLog(label / psi) - Common::SafeLog(label) - 0; // 0 = std::lgamma(1.0 / psi) = std::lgamma(1.0);
261 return -((label * theta - b) / a + c);
262 }
263 inline static const char* Name() {
264 return "gamma";
265 }
266
267 inline static void CheckLabel(label_t label) {
268 CHECK(label > 0);
269 }
270};
271
272
273class GammaDevianceMetric : public RegressionMetric<GammaDevianceMetric> {
274public:
275 explicit GammaDevianceMetric(const Config& config) :RegressionMetric<GammaDevianceMetric>(config) {
276 }
277
278 inline static double LossOnPoint(label_t label, double score, const Config&) {
279 const double epsilon = 1.0e-9;
280 const double tmp = label / (score + epsilon);
281 return tmp - Common::SafeLog(tmp) - 1;
282 }
283 inline static const char* Name() {
284 return "gamma-deviance";
285 }
286 inline static double AverageLoss(double sum_loss, double) {
287 return sum_loss * 2;
288 }
289 inline static void CheckLabel(label_t label) {
290 CHECK(label > 0);
291 }
292};
293
294class TweedieMetric : public RegressionMetric<TweedieMetric> {
295public:
296 explicit TweedieMetric(const Config& config) :RegressionMetric<TweedieMetric>(config) {
297 }
298
299 inline static double LossOnPoint(label_t label, double score, const Config& config) {
300 const double rho = config.tweedie_variance_power;
301 const double eps = 1e-10f;
302 if (score < eps) {
303 score = eps;
304 }
305 const double a = label * std::exp((1 - rho) * std::log(score)) / (1 - rho);
306 const double b = std::exp((2 - rho) * std::log(score)) / (2 - rho);
307 return -a + b;
308 }
309 inline static const char* Name() {
310 return "tweedie";
311 }
312};
313
314
315} // namespace LightGBM
316#endif // LightGBM_METRIC_REGRESSION_METRIC_HPP_
Fair loss for regression task.
Definition regression_metric.hpp:201
Definition regression_metric.hpp:273
Definition regression_metric.hpp:250
Huber loss for regression task.
Definition regression_metric.hpp:180
L1 loss for regression task.
Definition regression_metric.hpp:167
L2 loss for regression task.
Definition regression_metric.hpp:132
Mape regression loss for regression task.
Definition regression_metric.hpp:237
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 metric. Metric is used to calculate metric result.
Definition metric.h:20
The interface of Objective Function.
Definition objective_function.h:13
Poisson regression loss for regression task.
Definition regression_metric.hpp:218
L2 loss for regression task.
Definition regression_metric.hpp:146
RMSE loss for regression task.
Definition regression_metric.hpp:113
Metric for regression task. Use static class "PointWiseLossCalculator" to calculate loss point-wise.
Definition regression_metric.hpp:16
void Init(const Metadata &metadata, data_size_t num_data) override
Initialize.
Definition regression_metric.hpp:32
std::vector< double > Eval(const double *score, const ObjectiveFunction *objective) const override
Calcaluting and printing metric result.
Definition regression_metric.hpp:52
Definition regression_metric.hpp:294
desc and descl2 fields must be written in reStructuredText format
Definition application.h:10
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