CMS 3D CMS Logo

LossFunctions.h
Go to the documentation of this file.
1 // LossFunctions.h
2 // Here we define the different loss functions that can be used
3 // with the BDT system.
4 
5 #ifndef L1Trigger_L1TMuonEndCap_emtf_LossFunctions
6 #define L1Trigger_L1TMuonEndCap_emtf_LossFunctions
7 
8 #include "Event.h"
9 #include <string>
10 #include <algorithm>
11 
12 // ========================================================
13 // ================ Define the Interface ==================
14 //=========================================================
15 
16 namespace emtf {
17 
18 // Define the Interface
20 {
21  public:
22 
23  // The gradient of the loss function.
24  // Each tree is a step in the direction of the gradient
25  // towards the minimum of the Loss Function.
26  virtual double target(Event* e) = 0;
27 
28  // The fit should minimize the loss function in each
29  // terminal node at each iteration.
30  virtual double fit(std::vector<Event*>& v) = 0;
31  virtual std::string name() = 0;
32  virtual int id() = 0;
33  virtual ~LossFunction() = default;
34 };
35 
36 // ========================================================
37 // ================ Least Squares =========================
38 // ========================================================
39 
40 class LeastSquares : public LossFunction
41 {
42  public:
44  virtual ~LeastSquares(){}
45 
46  double target(Event* e) override
47  {
48  // Each tree fits the residuals when using LeastSquares.
49  return e->trueValue - e->predictedValue;
50  }
51 
52  double fit(std::vector<Event*>& v) override
53  {
54  // The average of the residuals minmizes the Loss Function for LS.
55 
56  double SUM = 0;
57  for(unsigned int i=0; i<v.size(); i++)
58  {
59  Event* e = v[i];
60  SUM += e->trueValue - e->predictedValue;
61  }
62 
63  return SUM/v.size();
64  }
65  std::string name() override { return "Least_Squares"; }
66  int id() override{ return 1; }
67 
68 };
69 
70 // ========================================================
71 // ============== Absolute Deviation ===================
72 // ========================================================
73 
75 {
76  public:
78  virtual ~AbsoluteDeviation(){}
79 
80  double target(Event* e) override
81  {
82  // The gradient.
83  if ((e->trueValue - e->predictedValue) >= 0)
84  return 1;
85  else
86  return -1;
87  }
88 
89  double fit(std::vector<Event*>& v) override
90  {
91  // The median of the residuals minimizes absolute deviation.
92  if(v.empty()) return 0;
93  std::vector<double> residuals(v.size());
94 
95  // Load the residuals into a vector.
96  for(unsigned int i=0; i<v.size(); i++)
97  {
98  Event* e = v[i];
99  residuals[i] = (e->trueValue - e->predictedValue);
100  }
101 
102  // Get the median and return it.
103  int median_loc = (residuals.size()-1)/2;
104 
105  // Odd.
106  if(residuals.size()%2 != 0)
107  {
108  std::nth_element(residuals.begin(), residuals.begin()+median_loc, residuals.end());
109  return residuals[median_loc];
110  }
111 
112  // Even.
113  else
114  {
115  std::nth_element(residuals.begin(), residuals.begin()+median_loc, residuals.end());
116  double low = residuals[median_loc];
117  std::nth_element(residuals.begin()+median_loc+1, residuals.begin()+median_loc+1, residuals.end());
118  double high = residuals[median_loc+1];
119  return (high + low)/2;
120  }
121  }
122  std::string name() override { return "Absolute_Deviation"; }
123  int id() override{ return 2; }
124 };
125 
126 // ========================================================
127 // ============== Huber ================================
128 // ========================================================
129 
130 class Huber : public LossFunction
131 {
132  public:
133  Huber(){}
134  virtual ~Huber(){}
135 
136  double quantile;
138 
139  double target(Event* e) override
140  {
141  // The gradient of the loss function.
142 
143  if (std::abs(e->trueValue - e->predictedValue) <= quantile)
144  return (e->trueValue - e->predictedValue);
145  else
146  return quantile*(((e->trueValue - e->predictedValue) > 0)?1.0:-1.0);
147  }
148 
149  double fit(std::vector<Event*>& v) override
150  {
151  // The constant fit that minimizes Huber in a region.
152 
153  quantile = calculateQuantile(v, 0.7);
154  residual_median = calculateQuantile(v, 0.5);
155 
156  double x = 0;
157  for(unsigned int i=0; i<v.size(); i++)
158  {
159  Event* e = v[i];
160  double residual = e->trueValue - e->predictedValue;
161  double diff = residual - residual_median;
162  x += ((diff > 0)?1.0:-1.0)*std::min(quantile, std::abs(diff));
163  }
164 
165  return (residual_median + x/v.size());
166 
167  }
168 
169  std::string name() override { return "Huber"; }
170  int id() override{ return 3; }
171 
172  double calculateQuantile(std::vector<Event*>& v, double whichQuantile)
173  {
174  // Container for the residuals.
175  std::vector<double> residuals(v.size());
176 
177  // Load the residuals into a vector.
178  for(unsigned int i=0; i<v.size(); i++)
179  {
180  Event* e = v[i];
181  residuals[i] = std::abs(e->trueValue - e->predictedValue);
182  }
183 
184  std::sort(residuals.begin(), residuals.end());
185  unsigned int quantile_location = whichQuantile*(residuals.size()-1);
186  return residuals[quantile_location];
187  }
188 };
189 
190 // ========================================================
191 // ============== Percent Error ===========================
192 // ========================================================
193 
195 {
196  public:
199 
200  double target(Event* e) override
201  {
202  // The gradient of the squared percent error.
203  return (e->trueValue - e->predictedValue)/(e->trueValue * e->trueValue);
204  }
205 
206  double fit(std::vector<Event*>& v) override
207  {
208  // The average of the weighted residuals minimizes the squared percent error.
209  // Weight(i) = 1/true(i)^2.
210 
211  double SUMtop = 0;
212  double SUMbottom = 0;
213 
214  for(unsigned int i=0; i<v.size(); i++)
215  {
216  Event* e = v[i];
217  SUMtop += (e->trueValue - e->predictedValue)/(e->trueValue*e->trueValue);
218  SUMbottom += 1/(e->trueValue*e->trueValue);
219  }
220 
221  return SUMtop/SUMbottom;
222  }
223  std::string name() override { return "Percent_Error"; }
224  int id() override{ return 4; }
225 };
226 
227 } // end of emtf namespace
228 
229 #endif
virtual ~Huber()
double fit(std::vector< Event * > &v) override
Definition: LossFunctions.h:52
std::string name() override
std::string name() override
Definition: Event.h:15
double target(Event *e) override
Definition: LossFunctions.h:80
virtual double fit(std::vector< Event * > &v)=0
double target(Event *e) override
std::string name() override
virtual std::string name()=0
double fit(std::vector< Event * > &v) override
double predictedValue
Definition: Event.h:21
virtual ~LeastSquares()
Definition: LossFunctions.h:44
int id() override
Definition: LossFunctions.h:66
double quantile
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double target(Event *e) override
Definition: LossFunctions.h:46
T min(T a, T b)
Definition: MathUtil.h:58
double trueValue
Definition: Event.h:20
double fit(std::vector< Event * > &v) override
virtual double target(Event *e)=0
#define SUM(A, B)
std::string name() override
Definition: LossFunctions.h:65
double fit(std::vector< Event * > &v) override
Definition: LossFunctions.h:89
double target(Event *e) override
int id() override
double calculateQuantile(std::vector< Event * > &v, double whichQuantile)
double residual_median
virtual int id()=0
virtual ~LossFunction()=default