56 TMVA::HuberLossFunction::HuberLossFunction(){
57 fTransitionPoint = -9999;
58 fSumOfWeights = -9999;
63 TMVA::HuberLossFunction::HuberLossFunction(Double_t quantile){
64 fSumOfWeights = -9999;
65 fTransitionPoint = -9999;
72 TMVA::HuberLossFunction::~HuberLossFunction(){
80 void TMVA::HuberLossFunction::Init(std::vector<LossFunctionEventInfo>& evs){
84 SetTransitionPoint(evs);
92 Double_t TMVA::HuberLossFunction::CalculateSumOfWeights(
const std::vector<LossFunctionEventInfo>& evs){
94 auto mapFunc = [&evs](UInt_t i) {
return evs[i].weight; };
95 auto redFunc = [](
const std::vector<Double_t> &a) {
return std::accumulate(a.begin(), a.end(), 0.0); };
97 return TMVA::Config::Instance().GetThreadExecutor().MapReduce(
98 mapFunc, ROOT::TSeqU(evs.size()), redFunc, TMVA::Config::Instance().GetThreadExecutor().GetPoolSize());
103 Double_t TMVA::HuberLossFunction::CalculateSumOfWeights(
const std::vector<LossFunctionEventInfo>& evs){
106 Double_t sumOfWeights = 0;
107 for(UInt_t i = 0; i<evs.size(); i++)
108 sumOfWeights+=evs[i].weight;
117 Double_t TMVA::HuberLossFunction::CalculateQuantile(std::vector<LossFunctionEventInfo>& evs, Double_t whichQuantile, Double_t sumOfWeights,
bool abs){
123 std::sort(evs.begin(), evs.end(), [](LossFunctionEventInfo a, LossFunctionEventInfo b){
124 return TMath::Abs(a.trueValue-a.predictedValue) < TMath::Abs(b.trueValue-b.predictedValue); });
126 std::sort(evs.begin(), evs.end(), [](LossFunctionEventInfo a, LossFunctionEventInfo b){
127 return (a.trueValue-a.predictedValue) < (b.trueValue-b.predictedValue); });
130 while(i<evs.size()-1 && temp <= sumOfWeights*whichQuantile){
131 temp += evs[i].weight;
136 if(whichQuantile == 0) i=0;
139 if(abs)
return TMath::Abs(evs[i].trueValue-evs[i].predictedValue);
140 else return evs[i].trueValue-evs[i].predictedValue;
147 void TMVA::HuberLossFunction::SetTransitionPoint(std::vector<LossFunctionEventInfo>& evs){
148 fTransitionPoint = CalculateQuantile(evs, fQuantile, fSumOfWeights,
true);
152 if(fTransitionPoint == 0){
154 for(UInt_t i=0; i<evs.size(); i++){
155 Double_t residual = TMath::Abs(evs[i].trueValue - evs[i].predictedValue);
157 fTransitionPoint = residual;
164 if(fTransitionPoint == 0){
174 void TMVA::HuberLossFunction::SetSumOfWeights(std::vector<LossFunctionEventInfo>& evs){
175 fSumOfWeights = CalculateSumOfWeights(evs);
181 Double_t TMVA::HuberLossFunction::CalculateLoss(LossFunctionEventInfo& e){
184 if(fSumOfWeights == -9999){
185 std::vector<LossFunctionEventInfo> evs{e};
186 SetSumOfWeights(evs);
187 SetTransitionPoint(evs);
190 Double_t residual = TMath::Abs(e.trueValue - e.predictedValue);
193 if(residual <= fTransitionPoint) loss = 0.5*residual*residual;
195 else loss = fQuantile*residual - 0.5*fQuantile*fQuantile;
196 return e.weight*loss;
202 Double_t TMVA::HuberLossFunction::CalculateNetLoss(std::vector<LossFunctionEventInfo>& evs){
206 SetSumOfWeights(evs);
207 SetTransitionPoint(evs);
209 Double_t netloss = 0;
210 for(UInt_t i=0; i<evs.size(); i++)
211 netloss+=CalculateLoss(evs[i]);
220 Double_t TMVA::HuberLossFunction::CalculateMeanLoss(std::vector<LossFunctionEventInfo>& evs){
224 SetSumOfWeights(evs);
225 SetTransitionPoint(evs);
227 Double_t netloss = 0;
228 for(UInt_t i=0; i<evs.size(); i++)
229 netloss+=CalculateLoss(evs[i]);
230 return netloss/fSumOfWeights;
240 TMVA::HuberLossFunctionBDT::HuberLossFunctionBDT(){
246 void TMVA::HuberLossFunctionBDT::Init(std::map<const TMVA::Event*, LossFunctionEventInfo>& evinfomap, std::vector<double>& boostWeights){
249 std::vector<LossFunctionEventInfo> evinfovec(evinfomap.size());
250 for (
auto &e: evinfomap){
251 evinfovec.push_back(LossFunctionEventInfo(e.second.trueValue, e.second.predictedValue, e.first->GetWeight()));
255 SetSumOfWeights(evinfovec);
256 Double_t weightedMedian = CalculateQuantile(evinfovec, 0.5, fSumOfWeights,
false);
259 boostWeights.push_back(weightedMedian);
260 for (
auto &e: evinfomap ) {
262 e.second.predictedValue += weightedMedian;
271 void TMVA::HuberLossFunctionBDT::SetTargets(std::vector<const TMVA::Event*>& evs, std::map< const TMVA::Event*, LossFunctionEventInfo >& evinfomap){
273 std::vector<LossFunctionEventInfo> eventvec(evs.size());
278 auto fcopy = [&eventvec, &evs, &evinfomap](UInt_t i) {
279 eventvec[i] = LossFunctionEventInfo(evinfomap[evs[i]].trueValue, evinfomap[evs[i]].predictedValue, evs[i]->GetWeight());
282 TMVA::Config::Instance().GetThreadExecutor().Foreach(fcopy, ROOT::TSeqU(evs.size()), TMVA::Config::Instance().GetThreadExecutor().GetPoolSize());
287 SetSumOfWeights(eventvec);
288 SetTransitionPoint(eventvec);
292 auto f = [
this, &evinfomap](
const TMVA::Event* ev) {
293 const_cast<TMVA::Event*
>(ev)->SetTarget(0, Target(evinfomap[ev]));
296 TMVA::Config::Instance().GetThreadExecutor().Foreach(f, evs, TMVA::Config::Instance().GetThreadExecutor().GetPoolSize());
301 void TMVA::HuberLossFunctionBDT::SetTargets(std::vector<const TMVA::Event*>& evs, std::map< const TMVA::Event*, LossFunctionEventInfo >& evinfomap){
303 std::vector<LossFunctionEventInfo> eventvec(evs.size());
304 for (std::vector<const TMVA::Event*>::const_iterator e=evs.begin(); e!=evs.end();e++){
305 eventvec.push_back(LossFunctionEventInfo(evinfomap[*e].trueValue, evinfomap[*e].predictedValue, (*e)->GetWeight()));
311 SetSumOfWeights(eventvec);
312 SetTransitionPoint(eventvec);
314 for (std::vector<const TMVA::Event*>::const_iterator e=evs.begin(); e!=evs.end();e++) {
315 const_cast<TMVA::Event*
>(*e)->SetTarget(0,Target(evinfomap[*e]));
323 Double_t TMVA::HuberLossFunctionBDT::Target(LossFunctionEventInfo& e){
324 Double_t residual = e.trueValue - e.predictedValue;
326 if(TMath::Abs(residual) <= fTransitionPoint)
return residual;
327 else return fTransitionPoint*(residual<0?-1.0:1.0);
334 Double_t TMVA::HuberLossFunctionBDT::Fit(std::vector<LossFunctionEventInfo>& evs){
340 Double_t sumOfWeights = CalculateSumOfWeights(evs);
341 Double_t shift=0,diff= 0;
342 Double_t residualMedian = CalculateQuantile(evs,0.5,sumOfWeights,
false);
343 for(UInt_t j=0;j<evs.size();j++){
344 Double_t residual = evs[j].trueValue - evs[j].predictedValue;
345 diff = residual-residualMedian;
347 shift+=1.0/evs.size()*((diff<0)?-1.0:1.0)*TMath::Min(fTransitionPoint,fabs(diff));
352 return (residualMedian + shift);
368 Double_t TMVA::LeastSquaresLossFunction::CalculateLoss(LossFunctionEventInfo& e){
369 Double_t residual = (e.trueValue - e.predictedValue);
371 loss = residual*residual;
372 return e.weight*loss;
378 Double_t TMVA::LeastSquaresLossFunction::CalculateNetLoss(std::vector<LossFunctionEventInfo>& evs){
379 Double_t netloss = 0;
380 for(UInt_t i=0; i<evs.size(); i++)
381 netloss+=CalculateLoss(evs[i]);
390 Double_t TMVA::LeastSquaresLossFunction::CalculateMeanLoss(std::vector<LossFunctionEventInfo>& evs){
391 Double_t netloss = 0;
392 Double_t sumOfWeights = 0;
393 for(UInt_t i=0; i<evs.size(); i++){
394 sumOfWeights+=evs[i].weight;
395 netloss+=CalculateLoss(evs[i]);
398 return netloss/sumOfWeights;
413 void TMVA::LeastSquaresLossFunctionBDT::Init(std::map<const TMVA::Event*, LossFunctionEventInfo>& evinfomap, std::vector<double>& boostWeights){
416 std::vector<LossFunctionEventInfo> evinfovec(evinfomap.size());
417 for (
auto &e: evinfomap){
418 evinfovec.push_back(LossFunctionEventInfo(e.second.trueValue, e.second.predictedValue, e.first->GetWeight()));
422 Double_t weightedMean = Fit(evinfovec);
425 boostWeights.push_back(weightedMean);
426 for (
auto &e: evinfomap ) {
428 e.second.predictedValue += weightedMean;
437 void TMVA::LeastSquaresLossFunctionBDT::SetTargets(std::vector<const TMVA::Event*>& evs, std::map< const TMVA::Event*, LossFunctionEventInfo >& evinfomap) {
440 auto f = [
this, &evinfomap](
const TMVA::Event* ev) {
441 const_cast<TMVA::Event*
>(ev)->SetTarget(0, Target(evinfomap[ev]));
444 TMVA::Config::Instance().GetThreadExecutor().Foreach(f, evs, TMVA::Config::Instance().GetThreadExecutor().GetPoolSize());
448 void TMVA::LeastSquaresLossFunctionBDT::SetTargets(std::vector<const TMVA::Event*>& evs, std::map< const TMVA::Event*, LossFunctionEventInfo >& evinfomap){
450 for (std::vector<const TMVA::Event*>::const_iterator e=evs.begin(); e!=evs.end();e++) {
451 const_cast<TMVA::Event*
>(*e)->SetTarget(0,Target(evinfomap[*e]));
459 Double_t TMVA::LeastSquaresLossFunctionBDT::Target(LossFunctionEventInfo& e){
460 Double_t residual = e.trueValue - e.predictedValue;
470 Double_t TMVA::LeastSquaresLossFunctionBDT::Fit(std::vector<LossFunctionEventInfo>& evs){
472 Double_t sumOfWeights = 0;
473 Double_t weightedResidualSum = 0;
474 for(UInt_t j=0;j<evs.size();j++){
475 sumOfWeights += evs[j].weight;
476 Double_t residual = evs[j].trueValue - evs[j].predictedValue;
477 weightedResidualSum += evs[j].weight*residual;
479 Double_t weightedMean = weightedResidualSum/sumOfWeights;
497 Double_t TMVA::AbsoluteDeviationLossFunction::CalculateLoss(LossFunctionEventInfo& e){
498 Double_t residual = e.trueValue - e.predictedValue;
499 return e.weight*TMath::Abs(residual);
505 Double_t TMVA::AbsoluteDeviationLossFunction::CalculateNetLoss(std::vector<LossFunctionEventInfo>& evs){
507 Double_t netloss = 0;
508 for(UInt_t i=0; i<evs.size(); i++)
509 netloss+=CalculateLoss(evs[i]);
516 Double_t TMVA::AbsoluteDeviationLossFunction::CalculateMeanLoss(std::vector<LossFunctionEventInfo>& evs){
517 Double_t sumOfWeights = 0;
518 Double_t netloss = 0;
519 for(UInt_t i=0; i<evs.size(); i++){
520 sumOfWeights+=evs[i].weight;
521 netloss+=CalculateLoss(evs[i]);
523 return netloss/sumOfWeights;
536 void TMVA::AbsoluteDeviationLossFunctionBDT::Init(std::map<const TMVA::Event*, LossFunctionEventInfo>& evinfomap, std::vector<double>& boostWeights){
539 std::vector<LossFunctionEventInfo> evinfovec(evinfomap.size());
540 for (
auto &e: evinfomap){
541 evinfovec.push_back(LossFunctionEventInfo(e.second.trueValue, e.second.predictedValue, e.first->GetWeight()));
544 Double_t weightedMedian = Fit(evinfovec);
547 boostWeights.push_back(weightedMedian);
548 for (
auto &e: evinfomap ) {
550 e.second.predictedValue += weightedMedian;
559 void TMVA::AbsoluteDeviationLossFunctionBDT::SetTargets(std::vector<const TMVA::Event*>& evs, std::map< const TMVA::Event*, LossFunctionEventInfo >& evinfomap){
561 auto f = [
this, &evinfomap](
const TMVA::Event* ev) {
562 const_cast<TMVA::Event*
>(ev)->SetTarget(0, Target(evinfomap[ev]));
565 TMVA::Config::Instance().GetThreadExecutor().Foreach(f, evs, TMVA::Config::Instance().GetThreadExecutor().GetPoolSize());
569 void TMVA::AbsoluteDeviationLossFunctionBDT::SetTargets(std::vector<const TMVA::Event*>& evs, std::map< const TMVA::Event*, LossFunctionEventInfo >& evinfomap){
571 for (std::vector<const TMVA::Event*>::const_iterator e=evs.begin(); e!=evs.end();e++) {
572 const_cast<TMVA::Event*
>(*e)->SetTarget(0,Target(evinfomap[*e]));
580 Double_t TMVA::AbsoluteDeviationLossFunctionBDT::Target(LossFunctionEventInfo& e){
582 Double_t residual = e.trueValue - e.predictedValue;
584 return (residual<0?-1.0:1.0);
591 Double_t TMVA::AbsoluteDeviationLossFunctionBDT::Fit(std::vector<LossFunctionEventInfo>& evs){
596 std::sort(evs.begin(), evs.end(), [](LossFunctionEventInfo a, LossFunctionEventInfo b){
597 return (a.trueValue-a.predictedValue) < (b.trueValue-b.predictedValue); });
600 Double_t sumOfWeights = 0;
601 for(UInt_t j=0; j<evs.size(); j++)
602 sumOfWeights+=evs[j].weight;
607 while(i<evs.size() && temp <= sumOfWeights*0.5){
608 temp += evs[i].weight;
611 if (i >= evs.size())
return 0.;
614 return evs[i].trueValue-evs[i].predictedValue;