149#include <unordered_map>
342 DeclareOptionRef(
fMinNodeSizeS=tmp,
"MinNodeSize",
"Minimum percentage of training events required in a leaf node (default: Classification: 5%, Regression: 0.2%)");
344 DeclareOptionRef(
fNCuts,
"nCuts",
"Number of grid points in variable range used in finding optimal cut in node splitting");
368 DeclareOptionRef(
fRandomisedTrees,
"UseRandomisedTrees",
"Determine at each node splitting the cut variable only as the best out of a random subset of variables (like in RandomForests)");
370 DeclareOptionRef(
fUsePoissonNvars,
"UsePoissonNvars",
"Interpret \"UseNvars\" not as fixed number but as mean of a Poisson distribution in each split with RandomisedTree option");
371 DeclareOptionRef(
fBaggedSampleFraction=.6,
"BaggedSampleFraction",
"Relative size of bagged event sample to original size of the data sample (used whenever bagging is used (i.e. UseBaggedBoost, Bagging,)" );
374 "Use Sig or Bkg categories, or the purity=S/(S+B) as classification of the leaf node -> Real-AdaBoost");
379 DeclareOptionRef(
fNegWeightTreatment=
"InverseBoostNegWeights",
"NegWeightTreatment",
"How to treat events with negative weights in the BDT training (particular the boosting) : IgnoreInTraining; Boost With inverse boostweight; Pair events with negative and positive weights in training sample and *annihilate* them (experimental!)");
414 DeclareOptionRef(
fHuberQuantile = 0.7,
"HuberQuantile",
"In the Huber loss function this is the quantile that separates the core from the tails in the residuals distribution.");
428 DeclareOptionRef(
fPruneMethodS,
"PruneMethod",
"Note: for BDTs use small trees (e.g.MaxDepth=3) and NoPruning: Pruning: Method used for pruning (removal) of statistically insignificant branches ");
442 DeclareOptionRef(
fBaggedGradBoost=
kFALSE,
"UseBaggedGrad",
"deprecated: Use *UseBaggedBoost* instead: Use only a random subsample of all events for growing the trees in each iteration.");
443 DeclareOptionRef(
fBaggedSampleFraction,
"GradBaggingFraction",
"deprecated: Use *BaggedSampleFraction* instead: Defines the fraction of events to be used in each iteration, e.g. when UseBaggedGrad=kTRUE. ");
444 DeclareOptionRef(
fUseNTrainEvents,
"UseNTrainEvents",
"deprecated: Use *BaggedSampleFraction* instead: Number of randomly picked training events used in randomised (and bagged) trees");
458 "Use weighted trees or simple average in classification from the forest");
480 Log() << kFATAL <<
"<ProcessOptions> unknown Separation Index option " <<
fSepTypeS <<
" called" <<
Endl;
485 Log() << kFATAL <<
"<ProcessOptions> Huber Quantile must be in range [0,1]. Value given, " <<
fHuberQuantile <<
", does not match this criteria" <<
Endl;
504 Log() << kFATAL <<
"<ProcessOptions> unknown PruneMethod " <<
fPruneMethodS <<
" option called" <<
Endl;
510 <<
"Sorry automatic pruning strength determination is not implemented yet for ExpectedErrorPruning" <<
Endl;
516 Log() << kWARNING <<
"You have explicitly set ** nEventsMin = " <<
fMinNodeEvents<<
" ** the min absolute number \n"
517 <<
"of events in a leaf node. This is DEPRECATED, please use the option \n"
518 <<
"*MinNodeSize* giving the relative number as percentage of training \n"
519 <<
"events instead. \n"
522 Log() << kWARNING <<
"Note also that explicitly setting *nEventsMin* so far OVERWRITES the option recommended \n"
536 Log() << kINFO <<
"the option NegWeightTreatment=InverseBoostNegWeights does"
537 <<
" not exist for BoostType=Grad" <<
Endl;
538 Log() << kINFO <<
"--> change to new default NegWeightTreatment=Pray" <<
Endl;
539 Log() << kDEBUG <<
"i.e. simply keep them as if which should work fine for Grad Boost" <<
Endl;
552 Log() << kWARNING <<
"You have chosen to use more than half of your training sample "
553 <<
"to optimize the automatic pruning algorithm. This is probably wasteful "
554 <<
"and your overall results will be degraded. Are you sure you want this?"
559 if (this->
Data()->HasNegativeEventWeights()){
560 Log() << kINFO <<
" You are using a Monte Carlo that has also negative weights. "
561 <<
"That should in principle be fine as long as on average you end up with "
562 <<
"something positive. For this you have to make sure that the minimal number "
563 <<
"of (un-weighted) events demanded for a tree node (currently you use: MinNodeSize="
565 <<
", (or the deprecated equivalent nEventsMin) you can set this via the "
566 <<
"BDT option string when booking the "
567 <<
"classifier) is large enough to allow for reasonable averaging!!! "
568 <<
" If this does not help.. maybe you want to try the option: IgnoreNegWeightsInTraining "
569 <<
"which ignores events with negative weight in the training. " <<
Endl
570 <<
Endl <<
"Note: You'll get a WARNING message during the training if that should ever happen" <<
Endl;
575 Log() << kWARNING <<
"Regression Trees do not work with fUseYesNoLeaf=TRUE --> I will set it to FALSE" <<
Endl;
580 Log() << kWARNING <<
"Regression Trees do not work with Separation type other than <RegressionVariance> --> I will use it instead" <<
Endl;
584 Log() << kWARNING <<
"Sorry, UseFisherCuts is not available for regression analysis, I will ignore it!" <<
Endl;
588 Log() << kWARNING <<
"Sorry, the option of nCuts<0 using a more elaborate node splitting algorithm " <<
Endl;
589 Log() << kWARNING <<
"is not implemented for regression analysis ! " <<
Endl;
590 Log() << kWARNING <<
"--> I switch do default nCuts = 20 and use standard node splitting"<<
Endl;
595 Log() << kINFO <<
" Randomised trees use no pruning" <<
Endl;
601 Log() << kWARNING <<
"When using the option UseFisherCuts, the other option nCuts<0 (i.e. using" <<
Endl;
602 Log() <<
" a more elaborate node splitting algorithm) is not implemented. " <<
Endl;
609 Log() << kERROR <<
" Zero Decision Trees demanded... that does not work !! "
610 <<
" I set it to 1 .. just so that the program does not crash"
623 Log() << kFATAL <<
"<ProcessOptions> unknown option for treating negative event weights during training " <<
fNegWeightTreatment <<
" requested" <<
Endl;
627 Log() << kWARNING <<
" you specified the option NegWeightTreatment=PairNegWeightsGlobal : This option is still considered EXPERIMENTAL !! " <<
Endl;
638 Log() << kWARNING <<
"You have specified a deprecated option *NNodesMax="<<
fNNodesMax
639 <<
"* \n this has been translated to MaxDepth="<<
fMaxDepth<<
Endl;
645 Log() << kWARNING <<
"You have specified a deprecated option *UseNTrainEvents="<<
fUseNTrainEvents
652 Log() << kWARNING <<
"You have specified a deprecated option *UseBaggedGrad* --> please use *UseBaggedBoost* instead" <<
Endl;
660 if (sizeInPercent > 0 && sizeInPercent < 50){
664 Log() << kFATAL <<
"you have demanded a minimal node size of "
665 << sizeInPercent <<
"% of the training events.. \n"
666 <<
" that somehow does not make sense "<<
Endl;
678 Log() << kFATAL <<
"I had problems reading the option MinNodeEvents, which "
679 <<
"after removing a possible % sign now reads " << sizeInPercent <<
Endl;
742 Log() << kDEBUG <<
" successfully(?) reset the method " <<
Endl;
769 UInt_t nevents =
Data()->GetNTrainingEvents();
771 std::vector<const TMVA::Event*> tmpEventSample;
772 for (
Long64_t ievt=0; ievt<nevents; ievt++) {
775 tmpEventSample.push_back(event);
781 for (
UInt_t i=0; i<tmpEventSample.size(); i++)
delete tmpEventSample[i];
786 for (
Long64_t ievt=0; ievt<nevents; ievt++) {
798 if (firstNegWeight) {
799 Log() << kWARNING <<
" Note, you have events with negative event weight in the sample, but you've chosen to ignore them" <<
Endl;
803 }
else if (event->GetWeight()==0){
804 if (firstZeroWeight) {
806 Log() <<
"Events with weight == 0 are going to be simply ignored " <<
Endl;
810 if (event->GetWeight() < 0) {
815 Log() << kWARNING <<
"Events with negative event weights are found and "
816 <<
" will be removed prior to the actual BDT training by global "
817 <<
" paring (and subsequent annihilation) with positiv weight events"
820 Log() << kWARNING <<
"Events with negative event weights are USED during "
821 <<
"the BDT training. This might cause problems with small node sizes "
822 <<
"or with the boosting. Please remove negative events from training "
823 <<
"using the option *IgnoreEventsWithNegWeightsInTraining* in case you "
824 <<
"observe problems with the boosting"
832 Int_t imodulo =
static_cast<Int_t>( fmod(modulo,1.0) > 0.5 ? ceil(modulo) : floor(modulo) );
843 Log() << kINFO <<
"<InitEventSample> Internally I use " <<
fEventSample.size()
846 <<
"% of training used for validation)" <<
Endl;
859 Log() << kDEBUG <<
"\t<InitEventSample> For classification trees, "<<
Endl;
860 Log() << kDEBUG <<
" \tthe effective number of backgrounds is scaled to match "<<
Endl;
861 Log() << kDEBUG <<
" \tthe signal. Otherwise the first boosting step would do 'just that'!"<<
Endl;
877 Int_t sumSig=0, sumBkg=0;
887 if (sumSigW && sumBkgW){
890 Log() << kDEBUG <<
"\tre-normalise events such that Sig and Bkg have respective sum of weights = "
892 Log() << kDEBUG <<
" \tsig->sig*"<<normSig <<
"ev. bkg->bkg*"<<normBkg <<
"ev." <<
Endl;
893 Log() << kHEADER <<
"#events: (reweighted) sig: "<< sumSigW*normSig <<
" bkg: " << sumBkgW*normBkg <<
Endl;
894 Log() << kINFO <<
"#events: (unweighted) sig: "<< sumSig <<
" bkg: " << sumBkg <<
Endl;
895 for (
Long64_t ievt=0; ievt<nevents; ievt++) {
900 Log() << kINFO <<
"--> could not determine scaling factors as either there are " <<
Endl;
901 Log() << kINFO <<
" no signal events (sumSigW="<<sumSigW<<
") or no bkg ev. (sumBkgW="<<sumBkgW<<
")"<<
Endl;
935 std::vector<const Event*> negEvents;
945 if (totalNegWeights == 0 ) {
946 Log() << kINFO <<
"no negative event weights found .. no preprocessing necessary" <<
Endl;
949 Log() << kINFO <<
"found a total of " << totalNegWeights <<
" of negative event weights which I am going to try to pair with positive events to annihilate them" <<
Endl;
950 Log() << kINFO <<
"found a total of " << totalPosWeights <<
" of events with positive weights" <<
Endl;
951 Log() << kINFO <<
"--> total sum of weights = " << totalWeights <<
" = " << totalNegWeights+totalPosWeights <<
Endl;
958 for (
Int_t i=0; i<2; i++){
959 invCov = ((*cov)[i]);
961 std::cout <<
"<MethodBDT::PreProcessNeg...> matrix is almost singular with determinant="
963 <<
" did you use the variables that are linear combinations or highly correlated?"
967 std::cout <<
"<MethodBDT::PreProcessNeg...> matrix is singular with determinant="
969 <<
" did you use the variables that are linear combinations?"
978 Log() << kINFO <<
"Found a total of " << totalNegWeights <<
" in negative weights out of " <<
fEventSample.size() <<
" training events " <<
Endl;
979 Timer timer(negEvents.size(),
"Negative Event paired");
980 for (
UInt_t nev = 0; nev < negEvents.size(); nev++){
982 Double_t weight = negEvents[nev]->GetWeight();
983 UInt_t iClassID = negEvents[nev]->GetClass();
984 invCov = ((*cov)[iClassID]);
995 dist += (negEvents[nev]->GetValue(ivar)-
fEventSample[iev]->GetValue(ivar))*
996 (*invCov)[ivar][jvar]*
997 (negEvents[nev]->GetValue(jvar)-
fEventSample[iev]->GetValue(jvar));
1000 if (dist < minDist) { iMin=iev; minDist=dist;}
1008 negEvents[nev]->SetBoostWeight( 0 );
1011 negEvents[nev]->SetBoostWeight( newWeight/negEvents[nev]->GetOriginalWeight() );
1015 }
else Log() << kFATAL <<
"preprocessing didn't find event to pair with the negative weight ... probably a bug" <<
Endl;
1016 weight = negEvents[nev]->GetWeight();
1023 totalNegWeights = 0;
1024 totalPosWeights = 0;
1031 std::vector<const Event*> newEventSample;
1052 if (totalNegWeights < 0)
Log() << kFATAL <<
" compensation of negative event weights with positive ones did not work " << totalNegWeights <<
Endl;
1057 Log() << kINFO <<
" after PreProcessing, the Event sample is left with " <<
fEventSample.size() <<
" events (unweighted), all with positive weights, adding up to " << totalWeights <<
Endl;
1058 Log() << kINFO <<
" nSig="<<nSig <<
" sigWeight="<<sigWeight <<
" nBkg="<<nBkg <<
" bkgWeight="<<bkgWeight <<
Endl;
1070 std::map<TString,TMVA::Interval*> tuneParameters;
1071 std::map<TString,Double_t> tunedParameters;
1080 tuneParameters.insert(std::pair<TString,Interval*>(
"NTrees",
new Interval(10,1000,5)));
1081 tuneParameters.insert(std::pair<TString,Interval*>(
"MaxDepth",
new Interval(2,4,3)));
1082 tuneParameters.insert(std::pair<TString,Interval*>(
"MinNodeSize",
new LogInterval(1,30,30)));
1088 tuneParameters.insert(std::pair<TString,Interval*>(
"AdaBoostBeta",
new Interval(.2,1.,5)));
1091 tuneParameters.insert(std::pair<TString,Interval*>(
"Shrinkage",
new Interval(0.05,0.50,5)));
1096 tuneParameters.insert(std::pair<TString,Interval*>(
"UseNvars",
new Interval(min_var,max_var,4)));
1100 Log()<<kINFO <<
" the following BDT parameters will be tuned on the respective *grid*\n"<<
Endl;
1101 std::map<TString,TMVA::Interval*>::iterator it;
1102 for(it=tuneParameters.begin(); it!= tuneParameters.end(); ++it){
1103 Log() << kWARNING << it->first <<
Endl;
1104 std::ostringstream oss;
1105 (it->second)->
Print(oss);
1111 tunedParameters=optimize.
optimize();
1113 return tunedParameters;
1122 std::map<TString,Double_t>::iterator it;
1123 for(it=tuneParameters.begin(); it!= tuneParameters.end(); ++it){
1124 Log() << kWARNING << it->first <<
" = " << it->second <<
Endl;
1126 else if (it->first ==
"MinNodeSize" )
SetMinNodeSize (it->second);
1130 else if (it->first ==
"Shrinkage" )
SetShrinkage (it->second);
1133 else Log() << kFATAL <<
" SetParameter for " << it->first <<
" not yet implemented " <<
Endl;
1151 Log() << kERROR <<
" Zero Decision Trees demanded... that does not work !! "
1152 <<
" I set it to 1 .. just so that the program does not crash"
1158 std::vector<TString> titles = {
"Boost weight",
"Error Fraction"};
1166 if (
IsNormalised())
Log() << kFATAL <<
"\"Normalise\" option cannot be used with BDT; "
1167 <<
"please remove the option from the configuration string, or "
1168 <<
"use \"!Normalise\""
1174 Log() << kINFO <<
"Training "<<
fNTrees <<
" Decision Trees ... patience please" <<
Endl;
1176 Log() << kDEBUG <<
"Training with maximal depth = " <<
fMaxDepth
1186 TString hname =
"AdaBooost weight distribution";
1196 hname=
"Boost event weights distribution";
1209 h->SetXTitle(
"boost weight");
1210 results->
Store(
h,
"BoostWeights");
1215 TH2* boostMonitor =
new TH2F(
"BoostMonitor",
"ROC Integral Vs iTree",2,0,
fNTrees,2,0,1.05);
1217 boostMonitor->
SetYTitle(
"ROC Integral");
1218 results->
Store(boostMonitor,
"BoostMonitor");
1220 boostMonitorGraph->
SetName(
"BoostMonitorGraph");
1221 boostMonitorGraph->
SetTitle(
"ROCIntegralVsNTrees");
1222 results->
Store(boostMonitorGraph,
"BoostMonitorGraph");
1227 h->SetXTitle(
"#tree");
1228 h->SetYTitle(
"boost weight");
1229 results->
Store(
h,
"BoostWeightsVsTree");
1233 h->SetXTitle(
"#tree");
1234 h->SetYTitle(
"error fraction");
1235 results->
Store(
h,
"ErrorFrac");
1238 nodesBeforePruningVsTree->
SetXTitle(
"#tree");
1239 nodesBeforePruningVsTree->
SetYTitle(
"#tree nodes");
1240 results->
Store(nodesBeforePruningVsTree);
1243 nodesAfterPruningVsTree->
SetXTitle(
"#tree");
1244 nodesAfterPruningVsTree->
SetYTitle(
"#tree nodes");
1245 results->
Store(nodesAfterPruningVsTree);
1255 Int_t nNodesBeforePruningCount = 0;
1256 Int_t nNodesAfterPruningCount = 0;
1258 Int_t nNodesBeforePruning = 0;
1259 Int_t nNodesAfterPruning = 0;
1269 while (itree <
fNTrees && continueBoost){
1285 Log() << kFATAL <<
"Multiclass is currently only supported by gradient boost. "
1286 <<
"Please change boost option accordingly (BoostType=Grad)." <<
Endl;
1290 for (
UInt_t i=0;i<nClasses;i++){
1299 fForest.back()->SetUseFisherCuts();
1311 Log() << kWARNING <<
"stopped boosting at itree="<<itree <<
Endl;
1326 fForest.back()->SetUseFisherCuts();
1334 nNodesBeforePruning =
fForest.back()->CleanTree();
1337 nNodesBeforePruningCount += nNodesBeforePruning;
1338 nodesBeforePruningVsTree->
SetBinContent(itree+1,nNodesBeforePruning);
1343 std::vector<const Event*> * validationSample = NULL;
1350 Log() << kWARNING <<
"stopped boosting at itree="<<itree <<
Endl;
1362 nNodesAfterPruning =
fForest.back()->GetNNodes();
1363 nNodesAfterPruningCount += nNodesAfterPruning;
1364 nodesAfterPruningVsTree->
SetBinContent(itree+1,nNodesAfterPruning);
1373 if ( itree==
fNTrees-1 || (!(itree%500)) ||
1374 (!(itree%250) && itree <1000)||
1375 (!(itree%100) && itree < 500)||
1376 (!(itree%50) && itree < 250)||
1377 (!(itree%25) && itree < 150)||
1378 (!(itree%10) && itree < 50)||
1379 (!(itree%5) && itree < 20)
1391 Log() << kDEBUG <<
"\t<Train> average number of nodes (w/o pruning) : "
1395 Log() << kDEBUG <<
"\t<Train> average number of nodes before/after pruning : "
1396 << nNodesBeforePruningCount/
GetNTrees() <<
" / "
1405 Log() << kDEBUG <<
"Now I delete the privat data sample"<<
Endl;
1422 for (
UInt_t itree=0; itree<nTrees; itree++) {
1427 return 2.0/(1.0+exp(-2.0*
sum))-1;
1437 Bool_t isLastClass = (cls == nClasses - 1);
1449 std::map<const TMVA::Event *, std::vector<double>> & residuals = this->
fResiduals;
1452 auto update_residuals = [&residuals, &lastTree, cls](
const TMVA::Event *
e) {
1456 auto update_residuals_last = [&residuals, &lastTree, cls, nClasses](
const TMVA::Event *
e) {
1459 auto &residualsThisEvent = residuals[
e];
1461 std::vector<Double_t> expCache(nClasses, 0.0);
1462 std::transform(residualsThisEvent.begin(),
1463 residualsThisEvent.begin() + nClasses,
1464 expCache.begin(), [](
Double_t d) { return exp(d); });
1466 Double_t exp_sum = std::accumulate(expCache.begin(),
1467 expCache.begin() + nClasses,
1470 for (
UInt_t i = 0; i < nClasses; i++) {
1471 Double_t p_cls = expCache[i] / exp_sum;
1473 Double_t res = (
e->GetClass() == i) ? (1.0 - p_cls) : (-p_cls);
1480 .
Foreach(update_residuals_last, eventSample);
1483 .
Foreach(update_residuals, eventSample);
1489 std::vector<Double_t> expCache;
1491 expCache.resize(nClasses);
1494 for (
auto e : eventSample) {
1498 std::transform(residualsThisEvent.begin(),
1499 residualsThisEvent.begin() + nClasses,
1500 expCache.begin(), [](
Double_t d) { return exp(d); });
1502 Double_t exp_sum = std::accumulate(expCache.begin(),
1503 expCache.begin() + nClasses,
1506 for (
UInt_t i = 0; i < nClasses; i++) {
1507 Double_t p_cls = expCache[i] / exp_sum;
1509 Double_t res = (
e->GetClass() == i) ? (1.0 - p_cls) : (-p_cls);
1516 std::map<const TMVA::Event *, std::vector<double>> & residuals = this->
fResiduals;
1522 auto update_residuals = [&residuals, &lastTree, signalClass](
const TMVA::Event *
e) {
1523 double & residualAt0 = residuals[
e].at(0);
1526 Double_t p_sig = 1.0 / (1.0 + exp(-2.0 * residualAt0));
1527 Double_t res = ((
e->GetClass() == signalClass) ? (1.0 - p_sig) : (-p_sig));
1533 .
Foreach(update_residuals, eventSample);
1535 for (
auto e : eventSample) {
1536 double & residualAt0 = residuals[
e].at(0);
1539 Double_t p_sig = 1.0 / (1.0 + exp(-2.0 * residualAt0));
1540 Double_t res = ((
e->GetClass() == signalClass) ? (1.0 - p_sig) : (-p_sig));
1563 auto f = [
this, &nPartitions](
UInt_t partition = 0) ->
Int_t {
1600 std::unordered_map<TMVA::DecisionTreeNode*, LeafInfo> leaves;
1601 for (
auto e : eventSample) {
1604 auto &
v = leaves[node];
1605 auto target =
e->GetTarget(cls);
1606 v.sumWeightTarget += target * weight;
1607 v.sum2 += fabs(target) * (1.0 - fabs(target)) * weight;
1609 for (
auto &iLeave : leaves) {
1610 constexpr auto minValue = 1
e-30;
1611 if (iLeave.second.sum2 < minValue) {
1612 iLeave.second.sum2 = minValue;
1615 iLeave.first->SetResponse(
fShrinkage * (K - 1) / K * iLeave.second.sumWeightTarget / iLeave.second.sum2);
1632 std::map<TMVA::DecisionTreeNode*,vector< TMVA::LossFunctionEventInfo > > leaves;
1633 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
1642 for (std::map<
TMVA::DecisionTreeNode*,vector< TMVA::LossFunctionEventInfo > >::iterator iLeave=leaves.begin();
1643 iLeave!=leaves.end();++iLeave){
1645 (iLeave->first)->SetResponse(
fShrinkage*fit);
1663 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
1674 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
1675 for (
UInt_t i=0;i<nClasses;i++){
1677 Double_t r = (*e)->GetClass()==i?(1-1.0/nClasses):(-1.0/nClasses);
1684 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
1709 return ncorrect / (ncorrect + nfalse);
1729 returnVal = this->
GradBoost (eventSample, dt, cls);
1731 returnVal = this->
GradBoost (eventSample, dt);
1735 Log() << kFATAL <<
"<Boost> unknown boost option " <<
fBoostType<<
" called" <<
Endl;
1754 TH1F *tmpS =
new TH1F(
"tmpS",
"", 100 , -1., 1.00001 );
1755 TH1F *tmpB =
new TH1F(
"tmpB",
"", 100 , -1., 1.00001 );
1759 UInt_t signalClassNr =
DataInfo().GetClassInfo(
"Signal")->GetNumber();
1770 for (
UInt_t iev=0; iev < nevents; iev++){
1773 if (event->GetClass() == signalClassNr) {tmp=tmpS;}
1779 std::vector<TH1F*> hS;
1780 std::vector<TH1F*> hB;
1784 results->
Store(hS.back(),hS.back()->GetTitle());
1785 results->
Store(hB.back(),hB.back()->GetTitle());
1794 results->
Store(tmpBoostWeightsS,tmpBoostWeightsS->
GetTitle());
1795 results->
Store(tmpBoostWeightsB,tmpBoostWeightsB->
GetTitle());
1797 TH1F *tmpBoostWeights;
1798 std::vector<TH1F*> *
h;
1802 tmpBoostWeights=tmpBoostWeightsS;
1805 tmpBoostWeights=tmpBoostWeightsB;
1846 Double_t err=0, sumGlobalw=0, sumGlobalwfalse=0, sumGlobalwfalse2=0;
1848 std::vector<Double_t> sumw(
DataInfo().GetNClasses(),0);
1851 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
1854 UInt_t iclass=(*e)->GetClass();
1859 sumGlobalwfalse += w * tmpDev;
1860 sumGlobalwfalse2 += w * tmpDev*tmpDev;
1861 if (tmpDev > maxDev) maxDev = tmpDev;
1866 if (!(isSignalType ==
DataInfo().IsSignal(*
e))) {
1867 sumGlobalwfalse+= w;
1872 if (
DataInfo().IsSignal(*
e)) trueType = 1;
1874 sumGlobalwfalse+= w*trueType*dtoutput;
1879 err = sumGlobalwfalse/sumGlobalw ;
1883 err = sumGlobalwfalse/maxDev/sumGlobalw ;
1886 err = sumGlobalwfalse2/maxDev/maxDev/sumGlobalw ;
1890 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
1893 err += w * (1 - exp (-tmpDev/maxDev)) / sumGlobalw;
1898 Log() << kFATAL <<
" you've chosen a Loss type for Adaboost other than linear, quadratic or exponential "
1900 <<
"and this is not implemented... a typo in the options ??" <<
Endl;
1904 Log() << kDEBUG <<
"BDT AdaBoos wrong/all: " << sumGlobalwfalse <<
"/" << sumGlobalw <<
Endl;
1908 std::vector<Double_t> newSumw(sumw.size(),0);
1915 Log() << kERROR <<
" YOUR tree has only 1 Node... kind of a funny *tree*. I cannot "
1916 <<
"boost such a thing... if after 1 step the error rate is == 0.5"
1918 <<
"please check why this happens, maybe too many events per node requested ?"
1922 Log() << kERROR <<
" The error rate in the BDT boosting is > 0.5. ("<<
err
1923 <<
") That should not happen, please check your code (i.e... the BDT code), I "
1924 <<
" stop boosting here" <<
Endl;
1928 }
else if (
err < 0) {
1929 Log() << kERROR <<
" The error rate in the BDT boosting is < 0. That can happen"
1930 <<
" due to improper treatment of negative weights in a Monte Carlo.. (if you have"
1931 <<
" an idea on how to do it in a better way, please let me know (Helge.Voss@cern.ch)"
1932 <<
" for the time being I set it to its absolute value.. just to continue.." <<
Endl;
1941 Log() << kDEBUG <<
"BDT AdaBoos wrong/all: " << sumGlobalwfalse <<
"/" << sumGlobalw <<
" 1-err/err="<<boostWeight<<
" log.."<<
TMath::Log(boostWeight)<<
Endl;
1946 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
1953 if ( (*e)->GetWeight() > 0 ){
1954 (*e)->SetBoostWeight( (*e)->GetBoostWeight() * boostfactor);
1959 else (*e)->SetBoostWeight( (*e)->GetBoostWeight() * boostfactor);
1967 if (
DataInfo().IsSignal(*
e)) trueType = 1;
1971 if ( (*e)->GetWeight() > 0 ){
1972 (*e)->SetBoostWeight( (*e)->GetBoostWeight() * boostfactor);
1977 else (*e)->SetBoostWeight( (*e)->GetBoostWeight() * boostfactor);
1980 newSumGlobalw+=(*e)->GetWeight();
1981 newSumw[(*e)->GetClass()] += (*e)->GetWeight();
1987 Log() << kDEBUG <<
"new Nsig="<<newSumw[0]*globalNormWeight <<
" new Nbkg="<<newSumw[1]*globalNormWeight <<
Endl;
1990 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
1995 else (*e)->ScaleBoostWeight( globalNormWeight );
2029 Double_t err=0, sumGlobalWeights=0, sumGlobalCost=0;
2031 std::vector<Double_t> sumw(
DataInfo().GetNClasses(),0);
2033 for (vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
2035 sumGlobalWeights += w;
2036 UInt_t iclass=(*e)->GetClass();
2041 Log() << kFATAL <<
" AdaCost not implemented for regression"<<
Endl;
2047 Bool_t isSelectedSignal = (dtoutput>0);
2048 if (isTrueSignal) trueType = 1;
2052 if (isTrueSignal && isSelectedSignal) cost=Css;
2053 else if (isTrueSignal && !isSelectedSignal) cost=Cts_sb;
2054 else if (!isTrueSignal && isSelectedSignal) cost=Ctb_ss;
2055 else if (!isTrueSignal && !isSelectedSignal) cost=Cbb;
2056 else Log() << kERROR <<
"something went wrong in AdaCost" <<
Endl;
2058 sumGlobalCost+= w*trueType*dtoutput*cost;
2064 Log() << kFATAL <<
" AdaCost not implemented for regression"<<
Endl;
2069 sumGlobalCost /= sumGlobalWeights;
2074 vector<Double_t> newSumClassWeights(sumw.size(),0);
2080 for (vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
2084 Bool_t isSelectedSignal = (dtoutput>0);
2085 if (isTrueSignal) trueType = 1;
2089 if (isTrueSignal && isSelectedSignal) cost=Css;
2090 else if (isTrueSignal && !isSelectedSignal) cost=Cts_sb;
2091 else if (!isTrueSignal && isSelectedSignal) cost=Ctb_ss;
2092 else if (!isTrueSignal && !isSelectedSignal) cost=Cbb;
2093 else Log() << kERROR <<
"something went wrong in AdaCost" <<
Endl;
2097 if ( (*e)->GetWeight() > 0 ){
2098 (*e)->SetBoostWeight( (*e)->GetBoostWeight() * boostfactor);
2105 newSumGlobalWeights+=(*e)->GetWeight();
2106 newSumClassWeights[(*e)->GetClass()] += (*e)->GetWeight();
2111 Double_t globalNormWeight=
Double_t(eventSample.size())/newSumGlobalWeights;
2112 Log() << kDEBUG <<
"new Nsig="<<newSumClassWeights[0]*globalNormWeight <<
" new Nbkg="<<newSumClassWeights[1]*globalNormWeight <<
Endl;
2115 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
2119 else (*e)->ScaleBoostWeight( globalNormWeight );
2157 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
2193 if ( !
DoRegression() )
Log() << kFATAL <<
"Somehow you chose a regression boost method for a classification job" <<
Endl;
2195 Double_t err=0, sumw=0, sumwfalse=0, sumwfalse2=0;
2197 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
2202 sumwfalse += w * tmpDev;
2203 sumwfalse2 += w * tmpDev*tmpDev;
2204 if (tmpDev > maxDev) maxDev = tmpDev;
2209 err = sumwfalse/maxDev/sumw ;
2212 err = sumwfalse2/maxDev/maxDev/sumw ;
2216 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
2219 err += w * (1 - exp (-tmpDev/maxDev)) / sumw;
2224 Log() << kFATAL <<
" you've chosen a Loss type for Adaboost other than linear, quadratic or exponential "
2226 <<
"and this is not implemented... a typo in the options ??" <<
Endl;
2234 Log() << kERROR <<
" YOUR tree has only 1 Node... kind of a funny *tree*. I cannot "
2235 <<
"boost such a thing... if after 1 step the error rate is == 0.5"
2237 <<
"please check why this happens, maybe too many events per node requested ?"
2241 Log() << kERROR <<
" The error rate in the BDT boosting is > 0.5. ("<<
err
2242 <<
") That should not happen, but is possible for regression trees, and"
2243 <<
" should trigger a stop for the boosting. please check your code (i.e... the BDT code), I "
2244 <<
" stop boosting " <<
Endl;
2248 }
else if (
err < 0) {
2249 Log() << kERROR <<
" The error rate in the BDT boosting is < 0. That can happen"
2250 <<
" due to improper treatment of negative weights in a Monte Carlo.. (if you have"
2251 <<
" an idea on how to do it in a better way, please let me know (Helge.Voss@cern.ch)"
2252 <<
" for the time being I set it to its absolute value.. just to continue.." <<
Endl;
2261 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
2263 results->
GetHist(
"BoostWeights")->
Fill(boostfactor);
2265 if ( (*e)->GetWeight() > 0 ){
2266 Float_t newBoostWeight = (*e)->GetBoostWeight() * boostfactor;
2267 Float_t newWeight = (*e)->GetWeight() * (*e)->GetBoostWeight() * boostfactor;
2268 if (newWeight == 0) {
2269 Log() << kINFO <<
"Weight= " << (*e)->GetWeight() <<
Endl;
2270 Log() << kINFO <<
"BoostWeight= " << (*e)->GetBoostWeight() <<
Endl;
2271 Log() << kINFO <<
"boostweight="<<boostWeight <<
" err= " <<
err <<
Endl;
2272 Log() << kINFO <<
"NewBoostWeight= " << newBoostWeight <<
Endl;
2273 Log() << kINFO <<
"boostfactor= " << boostfactor <<
Endl;
2274 Log() << kINFO <<
"maxDev = " << maxDev <<
Endl;
2276 Log() << kINFO <<
"target = " << (*e)->GetTarget(0) <<
Endl;
2279 (*e)->SetBoostWeight( newBoostWeight );
2282 (*e)->SetBoostWeight( (*e)->GetBoostWeight() / boostfactor);
2284 newSumw+=(*e)->GetWeight();
2288 Double_t normWeight = sumw / newSumw;
2289 for (std::vector<const TMVA::Event*>::const_iterator
e=eventSample.begin();
e!=eventSample.end();++
e) {
2292 (*e)->SetBoostWeight( (*e)->GetBoostWeight() * normWeight );
2330 void* trxml =
fForest[i]->AddXMLTo(wght);
2385 if(
gTools().HasAttr(parent,
"TreeType")) {
2396 fForest.back()->SetTreeID(i++);
2410 Int_t analysisType(0);
2414 Log() << kINFO <<
"Read " <<
fNTrees <<
" Decision trees" <<
Endl;
2422 istr >> dummy >> iTree >> dummy >> boostWeight;
2424 fForest.back()->Print( std::cout );
2425 Log() << kFATAL <<
"Error while reading weight file; mismatch iTree="
2426 << iTree <<
" i=" << i
2427 <<
" dummy " << dummy
2428 <<
" boostweight " << boostWeight
2475 if (useNTrees > 0 ) nTrees = useNTrees;
2481 for (
UInt_t itree=0; itree<nTrees; itree++) {
2486 return ( norm > std::numeric_limits<double>::epsilon() ) ? myMVA /= norm : 0 ;
2500 std::vector<Double_t> temp(nClasses);
2501 auto forestSize =
fForest.size();
2504 std::vector<TMVA::DecisionTree *> forest =
fForest;
2505 auto get_output = [&
e, &forest, &temp, forestSize, nClasses](
UInt_t iClass) {
2506 for (
UInt_t itree = iClass; itree < forestSize; itree += nClasses) {
2507 temp[iClass] += forest[itree]->CheckEvent(
e,
kFALSE);
2517 for (
UInt_t itree = 0; itree < forestSize; ++itree) {
2519 if (++classOfTree == nClasses) classOfTree = 0;
2525 std::transform(temp.begin(), temp.end(), temp.begin(), [](
Double_t d){return exp(d);});
2527 Double_t exp_sum = std::accumulate(temp.begin(), temp.end(), 0.0);
2529 for (
UInt_t i = 0; i < nClasses; i++) {
2530 Double_t p_cls = temp[i] / exp_sum;
2531 (*fMulticlassReturnVal).push_back(p_cls);
2562 vector< Double_t > response(
fForest.size());
2563 vector< Double_t > weight(
fForest.size());
2572 std::vector< std::vector<Double_t> > vtemp;
2573 vtemp.push_back( response );
2574 vtemp.push_back( weight );
2579 while (sumOfWeights <= totalSumOfWeights/2.) {
2580 sumOfWeights += vtemp[1][t];
2608 evT->
SetTarget(0, ( norm > std::numeric_limits<double>::epsilon() ) ? myMVA /= norm : 0 );
2628 Log() << kDEBUG <<
"\tWrite monitoring histograms to file: " <<
BaseDir()->GetPath() <<
Endl;
2650 for (
UInt_t i=0; i< relativeImportance.size(); i++) {
2672 if (ivar < (
UInt_t)relativeImportance.size())
return relativeImportance[ivar];
2673 else Log() << kFATAL <<
"<GetVariableImportance> ivar = " << ivar <<
" is out of range " <<
Endl;
2703 Log() <<
"Boosted Decision Trees are a collection of individual decision" <<
Endl;
2704 Log() <<
"trees which form a multivariate classifier by (weighted) majority " <<
Endl;
2705 Log() <<
"vote of the individual trees. Consecutive decision trees are " <<
Endl;
2706 Log() <<
"trained using the original training data set with re-weighted " <<
Endl;
2707 Log() <<
"events. By default, the AdaBoost method is employed, which gives " <<
Endl;
2708 Log() <<
"events that were misclassified in the previous tree a larger " <<
Endl;
2709 Log() <<
"weight in the training of the following tree." <<
Endl;
2711 Log() <<
"Decision trees are a sequence of binary splits of the data sample" <<
Endl;
2712 Log() <<
"using a single discriminant variable at a time. A test event " <<
Endl;
2713 Log() <<
"ending up after the sequence of left-right splits in a final " <<
Endl;
2714 Log() <<
"(\"leaf\") node is classified as either signal or background" <<
Endl;
2715 Log() <<
"depending on the majority type of training events in that node." <<
Endl;
2719 Log() <<
"By the nature of the binary splits performed on the individual" <<
Endl;
2720 Log() <<
"variables, decision trees do not deal well with linear correlations" <<
Endl;
2721 Log() <<
"between variables (they need to approximate the linear split in" <<
Endl;
2722 Log() <<
"the two dimensional space by a sequence of splits on the two " <<
Endl;
2723 Log() <<
"variables individually). Hence decorrelation could be useful " <<
Endl;
2724 Log() <<
"to optimise the BDT performance." <<
Endl;
2728 Log() <<
"The two most important parameters in the configuration are the " <<
Endl;
2729 Log() <<
"minimal number of events requested by a leaf node as percentage of the " <<
Endl;
2730 Log() <<
" number of training events (option \"MinNodeSize\" replacing the actual number " <<
Endl;
2731 Log() <<
" of events \"nEventsMin\" as given in earlier versions" <<
Endl;
2732 Log() <<
"If this number is too large, detailed features " <<
Endl;
2733 Log() <<
"in the parameter space are hard to be modelled. If it is too small, " <<
Endl;
2734 Log() <<
"the risk to overtrain rises and boosting seems to be less effective" <<
Endl;
2735 Log() <<
" typical values from our current experience for best performance " <<
Endl;
2736 Log() <<
" are between 0.5(%) and 10(%) " <<
Endl;
2738 Log() <<
"The default minimal number is currently set to " <<
Endl;
2739 Log() <<
" max(20, (N_training_events / N_variables^2 / 10)) " <<
Endl;
2740 Log() <<
"and can be changed by the user." <<
Endl;
2742 Log() <<
"The other crucial parameter, the pruning strength (\"PruneStrength\")," <<
Endl;
2743 Log() <<
"is also related to overtraining. It is a regularisation parameter " <<
Endl;
2744 Log() <<
"that is used when determining after the training which splits " <<
Endl;
2745 Log() <<
"are considered statistically insignificant and are removed. The" <<
Endl;
2746 Log() <<
"user is advised to carefully watch the BDT screen output for" <<
Endl;
2747 Log() <<
"the comparison between efficiencies obtained on the training and" <<
Endl;
2748 Log() <<
"the independent test sample. They should be equal within statistical" <<
Endl;
2749 Log() <<
"errors, in order to minimize statistical fluctuations in different samples." <<
Endl;
2761 fout <<
" std::vector<"<<nodeName<<
"*> fForest; // i.e. root nodes of decision trees" << std::endl;
2762 fout <<
" std::vector<double> fBoostWeights; // the weights applied in the individual boosts" << std::endl;
2763 fout <<
"};" << std::endl << std::endl;
2766 fout <<
"std::vector<double> ReadBDTG::GetMulticlassValues__( const std::vector<double>& inputValues ) const" << std::endl;
2767 fout <<
"{" << std::endl;
2768 fout <<
" uint nClasses = " <<
DataInfo().GetNClasses() <<
";" << std::endl;
2769 fout <<
" std::vector<double> fMulticlassReturnVal;" << std::endl;
2770 fout <<
" fMulticlassReturnVal.reserve(nClasses);" << std::endl;
2772 fout <<
" std::vector<double> temp(nClasses);" << std::endl;
2773 fout <<
" auto forestSize = fForest.size();" << std::endl;
2774 fout <<
" // trees 0, nClasses, 2*nClasses, ... belong to class 0" << std::endl;
2775 fout <<
" // trees 1, nClasses+1, 2*nClasses+1, ... belong to class 1 and so forth" << std::endl;
2776 fout <<
" uint classOfTree = 0;" << std::endl;
2777 fout <<
" for (uint itree = 0; itree < forestSize; ++itree) {" << std::endl;
2778 fout <<
" BDTGNode *current = fForest[itree];" << std::endl;
2779 fout <<
" while (current->GetNodeType() == 0) { //intermediate node" << std::endl;
2780 fout <<
" if (current->GoesRight(inputValues)) current=(BDTGNode*)current->GetRight();" << std::endl;
2781 fout <<
" else current=(BDTGNode*)current->GetLeft();" << std::endl;
2782 fout <<
" }" << std::endl;
2783 fout <<
" temp[classOfTree] += current->GetResponse();" << std::endl;
2784 fout <<
" if (++classOfTree == nClasses) classOfTree = 0; // cheap modulo" << std::endl;
2785 fout <<
" }" << std::endl;
2787 fout <<
" // we want to calculate sum of exp(temp[j] - temp[i]) for all i,j (i!=j)" << std::endl;
2788 fout <<
" // first calculate exp(), then replace minus with division." << std::endl;
2789 fout <<
" std::transform(temp.begin(), temp.end(), temp.begin(), [](double d){return exp(d);});" << std::endl;
2791 fout <<
" for(uint iClass=0; iClass<nClasses; iClass++){" << std::endl;
2792 fout <<
" double norm = 0.0;" << std::endl;
2793 fout <<
" for(uint j=0;j<nClasses;j++){" << std::endl;
2794 fout <<
" if(iClass!=j)" << std::endl;
2795 fout <<
" norm += temp[j] / temp[iClass];" << std::endl;
2796 fout <<
" }" << std::endl;
2797 fout <<
" fMulticlassReturnVal.push_back(1.0/(1.0+norm));" << std::endl;
2798 fout <<
" }" << std::endl;
2800 fout <<
" return fMulticlassReturnVal;" << std::endl;
2801 fout <<
"}" << std::endl;
2803 fout <<
"double " << className <<
"::GetMvaValue__( const std::vector<double>& inputValues ) const" << std::endl;
2804 fout <<
"{" << std::endl;
2805 fout <<
" double myMVA = 0;" << std::endl;
2809 fout <<
" if (inputValues["<<ivar<<
"] < " <<
fLowBkgCut[ivar] <<
") return -1; // is background preselection cut" << std::endl;
2812 fout <<
" if (inputValues["<<ivar<<
"] < "<<
fLowSigCut[ivar] <<
") return 1; // is signal preselection cut" << std::endl;
2815 fout <<
" if (inputValues["<<ivar<<
"] > "<<
fHighBkgCut[ivar] <<
") return -1; // is background preselection cut" << std::endl;
2818 fout <<
" if (inputValues["<<ivar<<
"] > "<<
fHighSigCut[ivar]<<
") return 1; // is signal preselection cut" << std::endl;
2824 fout <<
" double norm = 0;" << std::endl;
2826 fout <<
" for (unsigned int itree=0; itree<fForest.size(); itree++){" << std::endl;
2827 fout <<
" "<<nodeName<<
" *current = fForest[itree];" << std::endl;
2828 fout <<
" while (current->GetNodeType() == 0) { //intermediate node" << std::endl;
2829 fout <<
" if (current->GoesRight(inputValues)) current=("<<nodeName<<
"*)current->GetRight();" << std::endl;
2830 fout <<
" else current=("<<nodeName<<
"*)current->GetLeft();" << std::endl;
2831 fout <<
" }" << std::endl;
2833 fout <<
" myMVA += current->GetResponse();" << std::endl;
2835 if (
fUseYesNoLeaf) fout <<
" myMVA += fBoostWeights[itree] * current->GetNodeType();" << std::endl;
2836 else fout <<
" myMVA += fBoostWeights[itree] * current->GetPurity();" << std::endl;
2837 fout <<
" norm += fBoostWeights[itree];" << std::endl;
2839 fout <<
" }" << std::endl;
2841 fout <<
" return 2.0/(1.0+exp(-2.0*myMVA))-1.0;" << std::endl;
2843 else fout <<
" return myMVA /= norm;" << std::endl;
2844 fout <<
"}" << std::endl << std::endl;
2847 fout <<
"void " << className <<
"::Initialize()" << std::endl;
2848 fout <<
"{" << std::endl;
2849 fout <<
" double inf = std::numeric_limits<double>::infinity();" << std::endl;
2850 fout <<
" double nan = std::numeric_limits<double>::quiet_NaN();" << std::endl;
2853 fout <<
" // itree = " << itree << std::endl;
2854 fout <<
" fBoostWeights.push_back(" <<
fBoostWeights[itree] <<
");" << std::endl;
2855 fout <<
" fForest.push_back( " << std::endl;
2857 fout <<
" );" << std::endl;
2859 fout <<
" return;" << std::endl;
2860 fout <<
"};" << std::endl;
2862 fout <<
"// Clean up" << std::endl;
2863 fout <<
"inline void " << className <<
"::Clear() " << std::endl;
2864 fout <<
"{" << std::endl;
2865 fout <<
" for (unsigned int itree=0; itree<fForest.size(); itree++) { " << std::endl;
2866 fout <<
" delete fForest[itree]; " << std::endl;
2867 fout <<
" }" << std::endl;
2868 fout <<
"}" << std::endl;
2880 fout <<
"#include <algorithm>" << std::endl;
2881 fout <<
"#include <limits>" << std::endl;
2884 fout <<
"#define NN new "<<nodeName << std::endl;
2887 fout <<
"#ifndef "<<nodeName<<
"__def" << std::endl;
2888 fout <<
"#define "<<nodeName<<
"__def" << std::endl;
2890 fout <<
"class "<<nodeName<<
" {" << std::endl;
2892 fout <<
"public:" << std::endl;
2894 fout <<
" // constructor of an essentially \"empty\" node floating in space" << std::endl;
2895 fout <<
" "<<nodeName<<
" ( "<<nodeName<<
"* left,"<<nodeName<<
"* right," << std::endl;
2897 fout <<
" int nFisherCoeff," << std::endl;
2899 fout <<
" double fisherCoeff"<<i<<
"," << std::endl;
2902 fout <<
" int selector, double cutValue, bool cutType, " << std::endl;
2903 fout <<
" int nodeType, double purity, double response ) :" << std::endl;
2904 fout <<
" fLeft ( left )," << std::endl;
2905 fout <<
" fRight ( right )," << std::endl;
2906 if (
fUseFisherCuts) fout <<
" fNFisherCoeff ( nFisherCoeff )," << std::endl;
2907 fout <<
" fSelector ( selector )," << std::endl;
2908 fout <<
" fCutValue ( cutValue )," << std::endl;
2909 fout <<
" fCutType ( cutType )," << std::endl;
2910 fout <<
" fNodeType ( nodeType )," << std::endl;
2911 fout <<
" fPurity ( purity )," << std::endl;
2912 fout <<
" fResponse ( response ){" << std::endl;
2915 fout <<
" fFisherCoeff.push_back(fisherCoeff"<<i<<
");" << std::endl;
2918 fout <<
" }" << std::endl << std::endl;
2919 fout <<
" virtual ~"<<nodeName<<
"();" << std::endl << std::endl;
2920 fout <<
" // test event if it descends the tree at this node to the right" << std::endl;
2921 fout <<
" virtual bool GoesRight( const std::vector<double>& inputValues ) const;" << std::endl;
2922 fout <<
" "<<nodeName<<
"* GetRight( void ) {return fRight; };" << std::endl << std::endl;
2923 fout <<
" // test event if it descends the tree at this node to the left " << std::endl;
2924 fout <<
" virtual bool GoesLeft ( const std::vector<double>& inputValues ) const;" << std::endl;
2925 fout <<
" "<<nodeName<<
"* GetLeft( void ) { return fLeft; }; " << std::endl << std::endl;
2926 fout <<
" // return S/(S+B) (purity) at this node (from training)" << std::endl << std::endl;
2927 fout <<
" double GetPurity( void ) const { return fPurity; } " << std::endl;
2928 fout <<
" // return the node type" << std::endl;
2929 fout <<
" int GetNodeType( void ) const { return fNodeType; }" << std::endl;
2930 fout <<
" double GetResponse(void) const {return fResponse;}" << std::endl << std::endl;
2931 fout <<
"private:" << std::endl << std::endl;
2932 fout <<
" "<<nodeName<<
"* fLeft; // pointer to the left daughter node" << std::endl;
2933 fout <<
" "<<nodeName<<
"* fRight; // pointer to the right daughter node" << std::endl;
2935 fout <<
" int fNFisherCoeff; // =0 if this node doesn't use fisher, else =nvar+1 " << std::endl;
2936 fout <<
" std::vector<double> fFisherCoeff; // the fisher coeff (offset at the last element)" << std::endl;
2938 fout <<
" int fSelector; // index of variable used in node selection (decision tree) " << std::endl;
2939 fout <<
" double fCutValue; // cut value applied on this node to discriminate bkg against sig" << std::endl;
2940 fout <<
" bool fCutType; // true: if event variable > cutValue ==> signal , false otherwise" << std::endl;
2941 fout <<
" int fNodeType; // Type of node: -1 == Bkg-leaf, 1 == Signal-leaf, 0 = internal " << std::endl;
2942 fout <<
" double fPurity; // Purity of node from training"<< std::endl;
2943 fout <<
" double fResponse; // Regression response value of node" << std::endl;
2944 fout <<
"}; " << std::endl;
2946 fout <<
"//_______________________________________________________________________" << std::endl;
2947 fout <<
" "<<nodeName<<
"::~"<<nodeName<<
"()" << std::endl;
2948 fout <<
"{" << std::endl;
2949 fout <<
" if (fLeft != NULL) delete fLeft;" << std::endl;
2950 fout <<
" if (fRight != NULL) delete fRight;" << std::endl;
2951 fout <<
"}; " << std::endl;
2953 fout <<
"//_______________________________________________________________________" << std::endl;
2954 fout <<
"bool "<<nodeName<<
"::GoesRight( const std::vector<double>& inputValues ) const" << std::endl;
2955 fout <<
"{" << std::endl;
2956 fout <<
" // test event if it descends the tree at this node to the right" << std::endl;
2957 fout <<
" bool result;" << std::endl;
2959 fout <<
" if (fNFisherCoeff == 0){" << std::endl;
2960 fout <<
" result = (inputValues[fSelector] >= fCutValue );" << std::endl;
2961 fout <<
" }else{" << std::endl;
2962 fout <<
" double fisher = fFisherCoeff.at(fFisherCoeff.size()-1);" << std::endl;
2963 fout <<
" for (unsigned int ivar=0; ivar<fFisherCoeff.size()-1; ivar++)" << std::endl;
2964 fout <<
" fisher += fFisherCoeff.at(ivar)*inputValues.at(ivar);" << std::endl;
2965 fout <<
" result = fisher > fCutValue;" << std::endl;
2966 fout <<
" }" << std::endl;
2968 fout <<
" result = (inputValues[fSelector] >= fCutValue );" << std::endl;
2970 fout <<
" if (fCutType == true) return result; //the cuts are selecting Signal ;" << std::endl;
2971 fout <<
" else return !result;" << std::endl;
2972 fout <<
"}" << std::endl;
2974 fout <<
"//_______________________________________________________________________" << std::endl;
2975 fout <<
"bool "<<nodeName<<
"::GoesLeft( const std::vector<double>& inputValues ) const" << std::endl;
2976 fout <<
"{" << std::endl;
2977 fout <<
" // test event if it descends the tree at this node to the left" << std::endl;
2978 fout <<
" if (!this->GoesRight(inputValues)) return true;" << std::endl;
2979 fout <<
" else return false;" << std::endl;
2980 fout <<
"}" << std::endl;
2982 fout <<
"#endif" << std::endl;
2992 Log() << kFATAL <<
"MakeClassInstantiateNode: started with undefined node" <<
Endl;
2995 fout <<
"NN("<<std::endl;
2996 if (
n->GetLeft() != NULL){
3002 fout <<
", " <<std::endl;
3003 if (
n->GetRight() != NULL){
3009 fout <<
", " << std::endl
3010 << std::setprecision(6);
3012 fout <<
n->GetNFisherCoeff() <<
", ";
3014 if (
n->GetNFisherCoeff() == 0 ){
3017 fout <<
n->GetFisherCoeff(i) <<
", ";
3021 fout <<
n->GetSelector() <<
", "
3022 <<
n->GetCutValue() <<
", "
3023 <<
n->GetCutType() <<
", "
3024 <<
n->GetNodeType() <<
", "
3025 <<
n->GetPurity() <<
","
3026 <<
n->GetResponse() <<
") ";
3038 std::vector<TMVA::BDTEventWrapper> bdtEventSample;
3053 for( std::vector<const TMVA::Event*>::const_iterator it = eventSample.begin(); it != eventSample.end(); ++it ) {
3055 nTotS += (*it)->GetWeight();
3058 nTotB += (*it)->GetWeight();
3065 std::sort( bdtEventSample.begin(),bdtEventSample.end() );
3067 Double_t bkgWeightCtr = 0.0, sigWeightCtr = 0.0;
3068 std::vector<TMVA::BDTEventWrapper>::iterator it = bdtEventSample.begin(), it_end = bdtEventSample.end();
3069 for( ; it != it_end; ++it ) {
3071 sigWeightCtr += (**it)->GetWeight();
3073 bkgWeightCtr += (**it)->GetWeight();
3075 it->SetCumulativeWeight(
false,bkgWeightCtr);
3076 it->SetCumulativeWeight(
true,sigWeightCtr);
3082 Double_t nSelS, nSelB, effS=0.05, effB=0.05, rejS=0.05, rejB=0.05;
3083 Double_t tmpEffS, tmpEffB, tmpRejS, tmpRejB;
3088 for(
UInt_t iev = 1; iev < bdtEventSample.size(); iev++) {
3091 nSelS = bdtEventSample[iev].GetCumulativeWeight(
true);
3092 nSelB = bdtEventSample[iev].GetCumulativeWeight(
false);
3094 tmpEffS=nSelS/nTotS;
3095 tmpEffB=nSelB/nTotB;
3099 else if (nSelB==0 && tmpEffS>effS) {effS=tmpEffS;
fLowSigCut[ivar] = bdtEventSample[iev].GetVal() - dVal;
fIsLowSigCut[ivar]=
kTRUE;}
3106 Log() << kDEBUG <<
" \tfound and suggest the following possible pre-selection cuts " <<
Endl;
3107 if (
fDoPreselection)
Log() << kDEBUG <<
"\tthe training will be done after these cuts... and GetMVA value returns +1, (-1) for a signal (bkg) event that passes these cuts" <<
Endl;
3108 else Log() << kDEBUG <<
"\tas option DoPreselection was not used, these cuts however will not be performed, but the training will see the full sample"<<
Endl;
3111 Log() << kDEBUG <<
" \tfound cut: Bkg if var " << ivar <<
" < " <<
fLowBkgCut[ivar] <<
Endl;
3114 Log() << kDEBUG <<
" \tfound cut: Sig if var " << ivar <<
" < " <<
fLowSigCut[ivar] <<
Endl;
3117 Log() << kDEBUG <<
" \tfound cut: Bkg if var " << ivar <<
" > " <<
fHighBkgCut[ivar] <<
Endl;
3120 Log() << kDEBUG <<
" \tfound cut: Sig if var " << ivar <<
" > " <<
fHighSigCut[ivar] <<
Endl;
#define REGISTER_METHOD(CLASS)
for example
int Int_t
Signed integer 4 bytes (int).
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int).
bool Bool_t
Boolean (0=false, 1=true) (bool).
double Double_t
Double 8 bytes.
long long Long64_t
Portable signed long integer 8 bytes.
float Float_t
Float 4 bytes (float).
TMatrixTSym< Double_t > TMatrixDSym
void SetName(const char *name="") override
Set the name of the TNamed.
void SetTitle(const char *title="") override
Set the title of the TNamed.
1-D histogram with a float per channel (see TH1 documentation)
1-D histogram with an int per channel (see TH1 documentation)
TH1 is the base class of all histogram classes in ROOT.
virtual void SetXTitle(const char *title)
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
virtual void SetYTitle(const char *title)
2-D histogram with a float per channel (see TH1 documentation)
Service class for 2-D histogram classes.
Absolute Deviation BDT Loss Function.
static void SetVarIndex(Int_t iVar)
Executor & GetThreadExecutor()
Get executor class for multi-thread usage In case when MT is not enabled will return a serial executo...
static Config & Instance()
static function: returns TMVA instance
OptionBase * DeclareOptionRef(T &ref, const TString &name, const TString &desc="")
void AddPreDefVal(const T &)
const TString & GetOptions() const
Implementation of the CrossEntropy as separation criterion.
Class that contains all the data information.
static void SetIsTraining(bool on)
Implementation of a Decision Tree.
TMVA::DecisionTreeNode * GetEventNode(const TMVA::Event &e) const
get the pointer to the leaf node where a particular event ends up in... (used in gradient boosting)
static DecisionTree * CreateFromXML(void *node, UInt_t tmva_Version_Code=262657)
re-create a new tree (decision tree or search tree) from XML
Double_t CheckEvent(const TMVA::Event *, Bool_t UseYesNoLeaf=kFALSE) const
the event e is put into the decision tree (starting at the root node) and the output is NodeType (sig...
Float_t GetValue(UInt_t ivar) const
return value of i'th variable
void SetTarget(UInt_t itgt, Float_t value)
set the target value (dimension itgt) to value
Float_t GetTarget(UInt_t itgt) const
void Foreach(Function func, unsigned int nTimes, unsigned nChunks=0)
wrap TExecutor::Foreach
auto Map(F func, unsigned nTimes) -> std::vector< InvokeResult_t< F > >
Wrap TExecutor::Map functions.
unsigned int GetPoolSize() const
Implementation of the GiniIndex With Laplace correction as separation criterion.
Implementation of the GiniIndex as separation criterion.
The TMVA::Interval Class.
Least Squares BDT Loss Function.
The TMVA::Interval Class.
Double_t fCbb
Cost factor.
std::vector< Double_t > fHighBkgCut
void SetBaggedSampleFraction(Double_t f)
Bool_t fBaggedGradBoost
turn bagging in combination with grad boost on/off
Double_t GetMvaValue(Double_t *err=nullptr, Double_t *errUpper=nullptr) override
DecisionTree::EPruneMethod fPruneMethod
method used for pruning
const std::vector< Float_t > & GetMulticlassValues() override
Get the multiclass MVA response for the BDT classifier.
std::vector< const TMVA::Event * > fEventSample
the training events
Double_t fHuberQuantile
the option string determining the quantile for the Huber Loss Function in BDT regression.
void Init(void) override
Common initialisation with defaults for the BDT-Method.
void MakeClassSpecificHeader(std::ostream &, const TString &) const override
Specific class header.
void AddWeightsXMLTo(void *parent) const override
Write weights to XML.
static const Int_t fgDebugLevel
debug level determining some printout/control plots etc.
MethodBDT(const TString &jobName, const TString &methodTitle, DataSetInfo &theData, const TString &theOption="")
The standard constructor for the "boosted decision trees".
Bool_t fBaggedBoost
turn bagging in combination with boost on/off
TString fMinNodeSizeS
string containing min percentage of training events in node
void BoostMonitor(Int_t iTree)
Fills the ROCIntegral vs Itree from the testSample for the monitoring plots during the training .
std::map< const TMVA::Event *, LossFunctionEventInfo > fLossFunctionEventInfo
map event to true value, predicted value, and weight used by different loss functions for BDT regress...
std::vector< const TMVA::Event * > * fTrainSample
pointer to sample actually used in training (fEventSample or fSubSample) for example
std::vector< Bool_t > fIsHighSigCut
Double_t AdaBoostR2(std::vector< const TMVA::Event * > &, DecisionTree *dt)
Adaption of the AdaBoost to regression problems (see H.Drucker 1997).
Double_t PrivateGetMvaValue(const TMVA::Event *ev, Double_t *err=nullptr, Double_t *errUpper=nullptr, UInt_t useNTrees=0)
Return the MVA value (range [-1;1]) that classifies the event according to the majority vote from the...
Bool_t fPairNegWeightsGlobal
pair ev. with neg. and pos. weights in training sample and "annihilate" them
void SetTuneParameters(std::map< TString, Double_t > tuneParameters) override
Set the tuning parameters according to the argument.
Bool_t fSkipNormalization
true for skipping normalization at initialization of trees
std::map< TString, Double_t > OptimizeTuningParameters(TString fomType="ROCIntegral", TString fitType="FitGA") override
Call the Optimizer with the set of parameters and ranges that are meant to be tuned.
Bool_t fUseExclusiveVars
individual variables already used in fisher criterium are not anymore analysed individually for node ...
UInt_t fUseNvars
the number of variables used in the randomised tree splitting
Bool_t HasAnalysisType(Types::EAnalysisType type, UInt_t numberClasses, UInt_t numberTargets) override
BDT can handle classification with multiple classes and regression with one regression-target.
Double_t fCts_sb
Cost factor.
LossFunctionBDT * fRegressionLossFunctionBDTG
void DeterminePreselectionCuts(const std::vector< const TMVA::Event * > &eventSample)
Find useful preselection cuts that will be applied before and Decision Tree training.
Int_t fNCuts
grid used in cut applied in node splitting
Double_t GradBoost(std::vector< const TMVA::Event * > &, DecisionTree *dt, UInt_t cls=0)
Calculate the desired response value for each region.
void SetAdaBoostBeta(Double_t b)
Bool_t fUsePoissonNvars
use "fUseNvars" not as fixed number but as mean of a poisson distr. in each split
Float_t fMinNodeSize
min percentage of training events in node
Bool_t fDoBoostMonitor
create control plot with ROC integral vs tree number
Double_t AdaCost(std::vector< const TMVA::Event * > &, DecisionTree *dt)
The AdaCost boosting algorithm takes a simple cost Matrix (currently fixed for all events....
Bool_t fTrainWithNegWeights
yes there are negative event weights and we don't ignore them
TString fRegressionLossFunctionBDTGS
the option string determining the loss function for BDT regression
std::vector< double > fBoostWeights
the weights applied in the individual boosts
Bool_t fDoPreselection
do or do not perform automatic pre-selection of 100% eff. cuts
std::vector< Double_t > fVariableImportance
the relative importance of the different variables
Int_t fMinNodeEvents
min number of events in node
std::vector< Bool_t > fIsLowBkgCut
void Train(void) override
BDT training.
Double_t Boost(std::vector< const TMVA::Event * > &, DecisionTree *dt, UInt_t cls=0)
Apply the boosting algorithm (the algorithm is selecte via the "option" given in the constructor.
Double_t TestTreeQuality(DecisionTree *dt)
Test the tree quality.. in terms of Misclassification.
std::vector< DecisionTree * > fForest
the collection of decision trees
std::vector< Bool_t > fIsLowSigCut
Double_t Bagging()
Call it boot-strapping, re-sampling or whatever you like, in the end it is nothing else but applying ...
Double_t fErrorFraction
ntuple var: misclassification error fraction
Bool_t fRandomisedTrees
choose a random subset of possible cut variables at each node during training
void ReadWeightsFromStream(std::istream &istr) override
Read the weights (BDT coefficients).
Double_t fBaggedSampleFraction
relative size of bagged event sample to original sample size
Double_t fCss
Cost factor.
void MakeClassSpecific(std::ostream &, const TString &) const override
Make ROOT-independent C++ class for classifier response (classifier-specific implementation).
Bool_t fUseFisherCuts
use multivariate splits using the Fisher criterium
Double_t fPruneStrength
a parameter to set the "amount" of pruning..needs to be adjusted
Int_t fNTrees
number of decision trees requested
void SetMaxDepth(Int_t d)
void UpdateTargets(std::vector< const TMVA::Event * > &, UInt_t cls=0)
Calculate residual for all events.
Double_t fFValidationEvents
fraction of events to use for pruning
std::vector< const TMVA::Event * > fSubSample
subsample for bagged grad boost
void UpdateTargetsRegression(std::vector< const TMVA::Event * > &, Bool_t first=kFALSE)
Calculate residuals for all events and update targets for next iter.
Double_t GradBoostRegression(std::vector< const TMVA::Event * > &, DecisionTree *dt)
Implementation of M_TreeBoost using any loss function as described by Friedman 1999.
std::vector< Double_t > fLowBkgCut
UInt_t fMaxDepth
max depth
void SetShrinkage(Double_t s)
TString fAdaBoostR2Loss
loss type used in AdaBoostR2 (Linear,Quadratic or Exponential)
virtual ~MethodBDT(void)
Destructor.
Double_t GetGradBoostMVA(const TMVA::Event *e, UInt_t nTrees)
Returns MVA value: -1 for background, 1 for signal.
TString fPruneMethodS
prune method option String
Double_t fNodePurityLimit
purity limit for sig/bkg nodes
Int_t fITree
ntuple var: ith tree
Double_t fShrinkage
learning rate for gradient boost;
void SetNodePurityLimit(Double_t l)
TString fSepTypeS
the separation (option string) used in node splitting
Double_t RegBoost(std::vector< const TMVA::Event * > &, DecisionTree *dt)
A special boosting only for Regression (not implemented).
void InitEventSample()
Initialize the event sample (i.e. reset the boost-weights... etc).
void DeclareCompatibilityOptions() override
Options that are used ONLY for the READER to ensure backward compatibility.
void WriteMonitoringHistosToFile(void) const override
Here we could write some histograms created during the processing to the output file.
void DeclareOptions() override
Define the options (their key words).
Double_t ApplyPreselectionCuts(const Event *ev)
Apply the preselection cuts before even bothering about any Decision Trees in the GetMVA .
void SetMinNodeSize(Double_t sizeInPercent)
Double_t fBoostWeight
ntuple var: boost weight
void PreProcessNegativeEventWeights()
O.k.
Bool_t fUseYesNoLeaf
use sig or bkg classification in leave nodes or sig/bkg
void ReadWeightsFromXML(void *parent) override
Reads the BDT from the xml file.
void Reset(void) override
Reset the method, as if it had just been instantiated (forget all training etc.).
std::vector< const TMVA::Event * > fValidationSample
the Validation events
Bool_t fAutomatic
use user given prune strength or automatically determined one using a validation sample
std::vector< Double_t > fLowSigCut
Bool_t fInverseBoostNegWeights
boost ev. with neg. weights with 1/boostweight rather than boostweight
void GetHelpMessage() const override
Get help message text.
Double_t fCtb_ss
Cost factor.
std::map< const TMVA::Event *, std::vector< double > > fResiduals
individual event residuals for gradient boost
UInt_t fNNodesMax
max # of nodes
void MakeClassInstantiateNode(DecisionTreeNode *n, std::ostream &fout, const TString &className) const
Recursively descends a tree and writes the node instance to the output stream.
Double_t AdaBoost(std::vector< const TMVA::Event * > &, DecisionTree *dt)
The AdaBoost implementation.
TTree * fMonitorNtuple
monitoring ntuple
std::vector< Double_t > GetVariableImportance()
Return the relative variable importance, normalized to all variables together having the importance 1...
void SetUseNvars(Int_t n)
Bool_t fNoNegWeightsInTraining
ignore negative event weights in the training
Double_t fAdaBoostBeta
beta parameter for AdaBoost algorithm
void InitGradBoost(std::vector< const TMVA::Event * > &)
Initialize targets for first tree.
const std::vector< Float_t > & GetRegressionValues() override
Get the regression value generated by the BDTs.
void GetBaggedSubSample(std::vector< const TMVA::Event * > &)
Fills fEventSample with fBaggedSampleFraction*NEvents random training events.
std::vector< Double_t > fHighSigCut
const Ranking * CreateRanking() override
Compute ranking of input variables.
SeparationBase * fSepType
the separation used in node splitting
TString fNegWeightTreatment
variable that holds the option of how to treat negative event weights in training
void ProcessOptions() override
The option string is decoded, for available options see "DeclareOptions".
std::vector< Bool_t > fIsHighBkgCut
Double_t fSigToBkgFraction
Signal to Background fraction assumed during training.
Double_t fMinLinCorrForFisher
the minimum linear correlation between two variables demanded for use in fisher criterium in node spl...
UInt_t fUseNTrainEvents
number of randomly picked training events used in randomised (and bagged) trees
TString fBoostType
string specifying the boost type
MethodBase(const TString &jobName, Types::EMVA methodType, const TString &methodTitle, DataSetInfo &dsi, const TString &theOption="")
standard constructor
Bool_t HasTrainingTree() const
const char * GetName() const override
virtual void DeclareCompatibilityOptions()
options that are used ONLY for the READER to ensure backward compatibility they are hence without any...
Bool_t DoMulticlass() const
Types::EAnalysisType GetAnalysisType() const
UInt_t GetTrainingTMVAVersionCode() const
Bool_t IgnoreEventsWithNegWeightsInTraining() const
TDirectory * BaseDir() const
returns the ROOT directory where info/histograms etc of the corresponding MVA method instance are sto...
const Event * GetTestingEvent(Long64_t ievt) const
const TString & GetMethodName() const
Bool_t DoRegression() const
std::vector< Float_t > * fRegressionReturnVal
std::vector< Float_t > * fMulticlassReturnVal
const Event * GetEvent() const
DataSetInfo & DataInfo() const
UInt_t GetNVariables() const
Types::EAnalysisType fAnalysisType
TransformationHandler & GetTransformationHandler(Bool_t takeReroutedIfAvailable=true)
void SetSignalReferenceCut(Double_t cut)
void NoErrorCalc(Double_t *const err, Double_t *const errUpper)
const TString & GetInputLabel(Int_t i) const
Bool_t IsNormalised() const
const Event * GetTrainingEvent(Long64_t ievt) const
virtual Double_t GetROCIntegral(TH1D *histS, TH1D *histB) const
calculate the area (integral) under the ROC curve as a overall quality measure of the classification
IPythonInteractive * fInteractive
Bool_t IsConstructedFromWeightFile() const
Implementation of the MisClassificationError as separation criterion.
std::map< TString, Double_t > optimize()
PDF wrapper for histograms; uses user-defined spline interpolation.
Ranking for variables in method (implementation).
Class that is the base-class for a vector of result.
TGraph * GetGraph(const TString &alias) const
void Store(TObject *obj, const char *alias=nullptr)
TH1 * GetHist(const TString &alias) const
Implementation of the SdivSqrtSplusB as separation criterion.
Timing information for training and evaluation of MVA methods.
TString GetElapsedTime(Bool_t Scientific=kTRUE)
returns pretty string with elapsed time
void DrawProgressBar(Int_t, const TString &comment="")
draws progress bar in color or B&W caution:
Singleton class for Global types used by TMVA.
Double_t Determinant() const override
TMatrixTSym< Element > & Invert(Double_t *det=nullptr)
Invert the matrix and calculate its determinant Notice that the LU decomposition is used instead of B...
const char * GetTitle() const override
Returns title of object.
void Print(Option_t *option="") const override
Print TNamed name and title.
virtual void Delete(Option_t *option="")
Delete this object.
Random number generator class based on M.
virtual Double_t PoissonD(Double_t mean)
Generates a random number according to a Poisson law.
Double_t Atof() const
Return floating-point value contained in string.
Bool_t IsFloat() const
Returns kTRUE if string contains a floating point or integer number.
TString & ReplaceAll(const TString &s1, const TString &s2)
TString & Append(const char *cs)
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
A TTree represents a columnar dataset.
TSeq< unsigned int > TSeqU
create variable transformations
MsgLogger & Endl(MsgLogger &ml)
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Double_t Exp(Double_t x)
Returns the base-e exponential function of x, which is e raised to the power x.
Int_t FloorNint(Double_t x)
Returns the nearest integer of TMath::Floor(x).
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Double_t Sqrt(Double_t x)
Returns the square root of x.
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Int_t CeilNint(Double_t x)
Returns the nearest integer of TMath::Ceil(x).
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
static uint64_t sum(uint64_t i)