Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
MethodFisher.cxx
Go to the documentation of this file.
1// @(#)root/tmva $Id$
2// Author: Andreas Hoecker, Xavier Prudent, Joerg Stelzer, Helge Voss, Kai Voss
3
4/**********************************************************************************
5 * Project: TMVA - a Root-integrated toolkit for multivariate Data analysis *
6 * Package: TMVA *
7 * Class : MethodFisher *
8 * *
9 * *
10 * Description: *
11 * Implementation (see header for description) *
12 * *
13 * Original author of this Fisher-Discriminant implementation: *
14 * Andre Gaidot, CEA-France; *
15 * (Translation from FORTRAN) *
16 * *
17 * Authors (alphabetical): *
18 * Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland *
19 * Xavier Prudent <prudent@lapp.in2p3.fr> - LAPP, France *
20 * Helge Voss <Helge.Voss@cern.ch> - MPI-K Heidelberg, Germany *
21 * Kai Voss <Kai.Voss@cern.ch> - U. of Victoria, Canada *
22 * *
23 * Copyright (c) 2005: *
24 * CERN, Switzerland *
25 * U. of Victoria, Canada *
26 * MPI-K Heidelberg, Germany *
27 * LAPP, Annecy, France *
28 * *
29 * Redistribution and use in source and binary forms, with or without *
30 * modification, are permitted according to the terms listed in LICENSE *
31 * (see tmva/doc/LICENSE) *
32 **********************************************************************************/
33
34/*! \class TMVA::MethodFisher
35\ingroup TMVA
36
37Fisher and Mahalanobis Discriminants (Linear Discriminant Analysis)
38
39In the method of Fisher discriminants event selection is performed
40in a transformed variable space with zero linear correlations, by
41distinguishing the mean values of the signal and background
42distributions.
43
44The linear discriminant analysis determines an axis in the (correlated)
45hyperspace of the input variables
46such that, when projecting the output classes (signal and background)
47upon this axis, they are pushed as far as possible away from each other,
48while events of a same class are confined in a close vicinity.
49The linearity property of this method is reflected in the metric with
50which "far apart" and "close vicinity" are determined: the covariance
51matrix of the discriminant variable space.
52
53The classification of the events in signal and background classes
54relies on the following characteristics (only): overall sample means, \f$ x_i \f$,
55for each input variable, \f$ i \f$,
56class-specific sample means, \f$ x_{S(B),i}\f$,
57and total covariance matrix \f$ T_{ij} \f$. The covariance matrix
58can be decomposed into the sum of a _within_ (\f$ W_{ij} \f$)
59and a _between-class_ (\f$ B_{ij} \f$) class matrix. They describe
60the dispersion of events relative to the means of their own class (within-class
61matrix), and relative to the overall sample means (between-class matrix).
62The Fisher coefficients, \f$ F_i \f$, are then given by
63
64\f[
65F_i = \frac{\sqrt{N_s N_b}}{N_s + N_b} \sum_{j=1}^{N_{SB}} W_{ij}^{-1} (\bar{X}_{Sj} - \bar{X}_{Bj})
66\f]
67
68where in TMVA is set \f$ N_S = N_B \f$, so that the factor
69in front of the sum simplifies to \f$ \frac{1}{2}\f$.
70The Fisher discriminant then reads
71
72\f[
73X_{Fi} = F_0 + \sum_{i=1}^{N_{SB}} F_i X_i
74\f]
75
76The offset \f$ F_0 \f$ centers the sample mean of \f$ x_{Fi} \f$
77at zero. Instead of using the within-class matrix, the Mahalanobis variant
78determines the Fisher coefficients as follows:
79
80\f[
81F_i = \frac{\sqrt{N_s N_b}}{N_s + N_b} \sum_{j=1}^{N_{SB}} (W + B)_{ij}^{-1} (\bar{X}_{Sj} - \bar{X}_{Bj})
82\f]
83
84with resulting \f$ x_{Ma} \f$ that are very similar to the \f$ x_{Fi} \f$.
85
86TMVA provides two outputs for the ranking of the input variables:
87
88 - __Fisher test:__ the Fisher analysis aims at simultaneously maximising
89the between-class separation, while minimising the within-class dispersion.
90A useful measure of the discrimination power of a variable is hence given
91by the diagonal quantity: \f$ \frac{B_{ii}}{W_{ii}} \f$ .
92
93 - __Discrimination power:__ the value of the Fisher coefficient is a
94measure of the discriminating power of a variable. The discrimination power
95of set of input variables can therefore be measured by the scalar
96
97\f[
98\lambda = \frac{\sqrt{N_s N_b}}{N_s + N_b} \sum_{j=1}^{N_{SB}} F_i (\bar{X}_{Sj} - \bar{X}_{Bj})
99\f]
100
101The corresponding numbers are printed on standard output.
102*/
103
104#include "TMVA/MethodFisher.h"
105
107#include "TMVA/Configurable.h"
108#include "TMVA/DataSet.h"
109#include "TMVA/DataSetInfo.h"
110#include "TMVA/Event.h"
111#include "TMVA/IMethod.h"
112#include "TMVA/MethodBase.h"
113#include "TMVA/MsgLogger.h"
114#include "TMVA/Ranking.h"
115#include "TMVA/Tools.h"
117#include "TMVA/Types.h"
119
120#include "TMath.h"
121#include "TMatrix.h"
122#include "TList.h"
123
124#include <iostream>
125#include <iomanip>
126#include <cassert>
127
129
130
131////////////////////////////////////////////////////////////////////////////////
132/// standard constructor for the "Fisher"
133
135 const TString& methodTitle,
138 MethodBase( jobName, Types::kFisher, methodTitle, dsi, theOption),
139 fMeanMatx ( 0 ),
140 fTheMethod ( "Fisher" ),
141 fFisherMethod ( kFisher ),
142 fBetw ( 0 ),
143 fWith ( 0 ),
144 fCov ( 0 ),
145 fSumOfWeightsS( 0 ),
146 fSumOfWeightsB( 0 ),
147 fDiscrimPow ( 0 ),
148 fFisherCoeff ( 0 ),
149 fF0 ( 0 )
150{
151}
152
153////////////////////////////////////////////////////////////////////////////////
154/// constructor from weight file
155
157 const TString& theWeightFile) :
158 MethodBase( Types::kFisher, dsi, theWeightFile),
159 fMeanMatx ( 0 ),
160 fTheMethod ( "Fisher" ),
161 fFisherMethod ( kFisher ),
162 fBetw ( 0 ),
163 fWith ( 0 ),
164 fCov ( 0 ),
165 fSumOfWeightsS( 0 ),
166 fSumOfWeightsB( 0 ),
167 fDiscrimPow ( 0 ),
168 fFisherCoeff ( 0 ),
169 fF0 ( 0 )
170{
171}
172
173////////////////////////////////////////////////////////////////////////////////
174/// default initialization called by all constructors
175
177{
178 // allocate Fisher coefficients
179 fFisherCoeff = new std::vector<Double_t>( GetNvar() );
180
181 // the minimum requirement to declare an event signal-like
182 SetSignalReferenceCut( 0.0 );
183
184 // this is the preparation for training
185 InitMatrices();
186}
187
188////////////////////////////////////////////////////////////////////////////////
189/// MethodFisher options:
190/// format and syntax of option string: "type"
191/// where type is "Fisher" or "Mahalanobis"
192
194{
195 DeclareOptionRef( fTheMethod = "Fisher", "Method", "Discrimination method" );
196 AddPreDefVal(TString("Fisher"));
197 AddPreDefVal(TString("Mahalanobis"));
198}
199
200////////////////////////////////////////////////////////////////////////////////
201/// process user options
202
204{
205 if (fTheMethod == "Fisher" ) fFisherMethod = kFisher;
206 else fFisherMethod = kMahalanobis;
207
208 // this is the preparation for training
209 InitMatrices();
210}
211
212////////////////////////////////////////////////////////////////////////////////
213/// destructor
214
216{
217 if (fBetw ) { delete fBetw; fBetw = 0; }
218 if (fWith ) { delete fWith; fWith = 0; }
219 if (fCov ) { delete fCov; fCov = 0; }
220 if (fDiscrimPow ) { delete fDiscrimPow; fDiscrimPow = 0; }
221 if (fFisherCoeff) { delete fFisherCoeff; fFisherCoeff = 0; }
222}
223
224////////////////////////////////////////////////////////////////////////////////
225/// Fisher can only handle classification with 2 classes
226
232
233////////////////////////////////////////////////////////////////////////////////
234/// computation of Fisher coefficients by series of matrix operations
235
237{
238 // get mean value of each variables for signal, backgd and signal+backgd
239 GetMean();
240
241 // get the matrix of covariance 'within class'
242 GetCov_WithinClass();
243
244 // get the matrix of covariance 'between class'
245 GetCov_BetweenClass();
246
247 // get the matrix of covariance 'between class'
248 GetCov_Full();
249
250 //--------------------------------------------------------------
251
252 // get the Fisher coefficients
253 GetFisherCoeff();
254
255 // get the discriminating power of each variables
256 GetDiscrimPower();
257
258 // nice output
259 PrintCoefficients();
260
261}
262
263////////////////////////////////////////////////////////////////////////////////
264/// returns the Fisher value (no fixed range)
265
267{
268 const Event * ev = GetEvent();
269 Double_t result = fF0;
270 for (UInt_t ivar=0; ivar<GetNvar(); ivar++)
271 result += (*fFisherCoeff)[ivar]*ev->GetValue(ivar);
272
273 // cannot determine error
274 NoErrorCalc(err, errUpper);
275
276 return result;
277
278}
279
280////////////////////////////////////////////////////////////////////////////////
281/// initialization method; creates global matrices and vectors
282
284{
285 // average value of each variables for S, B, S+B
286 fMeanMatx = new TMatrixD( GetNvar(), 3 );
287
288 // the covariance 'within class' and 'between class' matrices
289 fBetw = new TMatrixD( GetNvar(), GetNvar() );
290 fWith = new TMatrixD( GetNvar(), GetNvar() );
291 fCov = new TMatrixD( GetNvar(), GetNvar() );
292
293 // discriminating power
294 fDiscrimPow = new std::vector<Double_t>( GetNvar() );
295}
296
297////////////////////////////////////////////////////////////////////////////////
298/// compute mean values of variables in each sample, and the overall means
299
301{
302 // initialize internal sum-of-weights variables
303 fSumOfWeightsS = 0;
304 fSumOfWeightsB = 0;
305
306 const UInt_t nvar = DataInfo().GetNVariables();
307
308 // init vectors
309 Double_t* sumS = new Double_t[nvar];
310 Double_t* sumB = new Double_t[nvar];
311 for (UInt_t ivar=0; ivar<nvar; ivar++) { sumS[ivar] = sumB[ivar] = 0; }
312
313 // compute sample means
314 for (Int_t ievt=0; ievt<Data()->GetNEvents(); ievt++) {
315
316 // read the Training Event into "event"
317 const Event * ev = GetEvent(ievt);
318
319 // sum of weights
320 Double_t weight = ev->GetWeight();
321 if (DataInfo().IsSignal(ev)) fSumOfWeightsS += weight;
322 else fSumOfWeightsB += weight;
323
324 Double_t* sum = DataInfo().IsSignal(ev) ? sumS : sumB;
325
326 for (UInt_t ivar=0; ivar<nvar; ivar++) sum[ivar] += ev->GetValue( ivar )*weight;
327 }
328
329 for (UInt_t ivar=0; ivar<nvar; ivar++) {
330 (*fMeanMatx)( ivar, 2 ) = sumS[ivar];
331 (*fMeanMatx)( ivar, 0 ) = sumS[ivar]/fSumOfWeightsS;
332
333 (*fMeanMatx)( ivar, 2 ) += sumB[ivar];
334 (*fMeanMatx)( ivar, 1 ) = sumB[ivar]/fSumOfWeightsB;
335
336 // signal + background
337 (*fMeanMatx)( ivar, 2 ) /= (fSumOfWeightsS + fSumOfWeightsB);
338 }
339
340 // fMeanMatx->Print();
341 delete [] sumS;
342 delete [] sumB;
343}
344
345////////////////////////////////////////////////////////////////////////////////
346/// the matrix of covariance 'within class' reflects the dispersion of the
347/// events relative to the center of gravity of their own class
348
350{
351 // assert required
352 assert( fSumOfWeightsS > 0 && fSumOfWeightsB > 0 );
353
354 // product matrices (x-<x>)(y-<y>) where x;y are variables
355
356 // init
357 const Int_t nvar = GetNvar();
358 const Int_t nvar2 = nvar*nvar;
361 Double_t *xval = new Double_t[nvar];
362 memset(sumSig,0,nvar2*sizeof(Double_t));
363 memset(sumBgd,0,nvar2*sizeof(Double_t));
364
365 // 'within class' covariance
366 for (Int_t ievt=0; ievt<Data()->GetNEvents(); ievt++) {
367
368 // read the Training Event into "event"
369 const Event* ev = GetEvent(ievt);
370
371 Double_t weight = ev->GetWeight(); // may ignore events with negative weights
372
373 for (Int_t x=0; x<nvar; x++) xval[x] = ev->GetValue( x );
374 Int_t k=0;
375 for (Int_t x=0; x<nvar; x++) {
376 for (Int_t y=0; y<nvar; y++) {
377 if (DataInfo().IsSignal(ev)) {
378 Double_t v = ( (xval[x] - (*fMeanMatx)(x, 0))*(xval[y] - (*fMeanMatx)(y, 0)) )*weight;
379 sumSig[k] += v;
380 }else{
381 Double_t v = ( (xval[x] - (*fMeanMatx)(x, 1))*(xval[y] - (*fMeanMatx)(y, 1)) )*weight;
382 sumBgd[k] += v;
383 }
384 k++;
385 }
386 }
387 }
388 Int_t k=0;
389 for (Int_t x=0; x<nvar; x++) {
390 for (Int_t y=0; y<nvar; y++) {
391 //(*fWith)(x, y) = (sumSig[k] + sumBgd[k])/(fSumOfWeightsS + fSumOfWeightsB);
392 // HHV: I am still convinced that THIS is how it should be (below) However, while
393 // the old version corresponded so nicely with LD, the FIXED version does not, unless
394 // we agree to change LD. For LD, it is not "defined" to my knowledge how the weights
395 // are weighted, while it is clear how the "Within" matrix for Fisher should be calculated
396 // (i.e. as seen below). In order to agree with the Fisher classifier, one would have to
397 // weigh signal and background such that they correspond to the same number of effective
398 // (weighted) events.
399 // THAT is NOT done currently, but just "event weights" are used.
400 (*fWith)(x, y) = sumSig[k]/fSumOfWeightsS + sumBgd[k]/fSumOfWeightsB;
401 k++;
402 }
403 }
404
405 delete [] sumSig;
406 delete [] sumBgd;
407 delete [] xval;
408}
409
410////////////////////////////////////////////////////////////////////////////////
411/// the matrix of covariance 'between class' reflects the dispersion of the
412/// events of a class relative to the global center of gravity of all the class
413/// hence the separation between classes
414
416{
417 // assert required
418 assert( fSumOfWeightsS > 0 && fSumOfWeightsB > 0);
419
421
422 for (UInt_t x=0; x<GetNvar(); x++) {
423 for (UInt_t y=0; y<GetNvar(); y++) {
424
425 prodSig = ( ((*fMeanMatx)(x, 0) - (*fMeanMatx)(x, 2))*
426 ((*fMeanMatx)(y, 0) - (*fMeanMatx)(y, 2)) );
427 prodBgd = ( ((*fMeanMatx)(x, 1) - (*fMeanMatx)(x, 2))*
428 ((*fMeanMatx)(y, 1) - (*fMeanMatx)(y, 2)) );
429
430 (*fBetw)(x, y) = (fSumOfWeightsS*prodSig + fSumOfWeightsB*prodBgd) / (fSumOfWeightsS + fSumOfWeightsB);
431 }
432 }
433}
434
435////////////////////////////////////////////////////////////////////////////////
436/// compute full covariance matrix from sum of within and between matrices
437
439{
440 for (UInt_t x=0; x<GetNvar(); x++)
441 for (UInt_t y=0; y<GetNvar(); y++)
442 (*fCov)(x, y) = (*fWith)(x, y) + (*fBetw)(x, y);
443}
444
445////////////////////////////////////////////////////////////////////////////////
446/// Fisher = Sum { [coeff]*[variables] }
447///
448/// let Xs be the array of the mean values of variables for signal evts
449/// let Xb be the array of the mean values of variables for backgd evts
450/// let InvWith be the inverse matrix of the 'within class' correlation matrix
451///
452/// then the array of Fisher coefficients is
453/// [coeff] =sqrt(fNsig*fNbgd)/fNevt*transpose{Xs-Xb}*InvWith
454
456{
457 // assert required
458 assert( fSumOfWeightsS > 0 && fSumOfWeightsB > 0);
459
460 // invert covariance matrix
461 TMatrixD* theMat = 0;
462 switch (GetFisherMethod()) {
463 case kFisher:
464 theMat = fWith;
465 break;
466 case kMahalanobis:
467 theMat = fCov;
468 break;
469 default:
470 Log() << kFATAL << "<GetFisherCoeff> undefined method" << GetFisherMethod() << Endl;
471 }
472
474
475 if ( TMath::Abs(invCov.Determinant()) < 10E-24 ) {
476 Log() << kWARNING << "<GetFisherCoeff> matrix is almost singular with determinant="
477 << TMath::Abs(invCov.Determinant())
478 << " did you use the variables that are linear combinations or highly correlated?"
479 << Endl;
480 }
481 if ( TMath::Abs(invCov.Determinant()) < 10E-120 ) {
482 theMat->Print();
483 Log() << kFATAL << "<GetFisherCoeff> matrix is singular with determinant="
484 << TMath::Abs(invCov.Determinant())
485 << " did you use the variables that are linear combinations? \n"
486 << " do you any clue as to what went wrong in above printout of the covariance matrix? "
487 << Endl;
488 }
489
490 invCov.Invert();
491
492 // apply rescaling factor
493 Double_t xfact = TMath::Sqrt( fSumOfWeightsS*fSumOfWeightsB ) / (fSumOfWeightsS + fSumOfWeightsB);
494
495 // compute difference of mean values
496 std::vector<Double_t> diffMeans( GetNvar() );
498 for (ivar=0; ivar<GetNvar(); ivar++) {
499 (*fFisherCoeff)[ivar] = 0;
500
501 for (jvar=0; jvar<GetNvar(); jvar++) {
502 Double_t d = (*fMeanMatx)(jvar, 0) - (*fMeanMatx)(jvar, 1);
503 (*fFisherCoeff)[ivar] += invCov(ivar, jvar)*d;
504 }
505 // rescale
506 (*fFisherCoeff)[ivar] *= xfact;
507 }
508
509
510 // offset correction
511 fF0 = 0.0;
512 for (ivar=0; ivar<GetNvar(); ivar++){
513 fF0 += (*fFisherCoeff)[ivar]*((*fMeanMatx)(ivar, 0) + (*fMeanMatx)(ivar, 1));
514 }
515 fF0 /= -2.0;
516}
517
518////////////////////////////////////////////////////////////////////////////////
519/// computation of discrimination power indicator for each variable
520/// small values of "fWith" indicates little compactness of sig & of backgd
521/// big values of "fBetw" indicates large separation between sig & backgd
522///
523/// we want signal & backgd classes as compact and separated as possible
524/// the discriminating power is then defined as the ration "fBetw/fWith"
525
527{
528 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
529 if ((*fCov)(ivar, ivar) != 0)
530 (*fDiscrimPow)[ivar] = (*fBetw)(ivar, ivar)/(*fCov)(ivar, ivar);
531 else
532 (*fDiscrimPow)[ivar] = 0;
533 }
534}
535
536////////////////////////////////////////////////////////////////////////////////
537/// computes ranking of input variables
538
540{
541 // create the ranking object
542 fRanking = new Ranking( GetName(), "Discr. power" );
543
544 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
545 fRanking->AddRank( Rank( GetInputLabel(ivar), (*fDiscrimPow)[ivar] ) );
546 }
547
548 return fRanking;
549}
550
551////////////////////////////////////////////////////////////////////////////////
552/// display Fisher coefficients and discriminating power for each variable
553/// check maximum length of variable name
554
556{
557 Log() << kHEADER << "Results for Fisher coefficients:" << Endl;
558
559 if (GetTransformationHandler().GetTransformationList().GetSize() != 0) {
560 Log() << kINFO << "NOTE: The coefficients must be applied to TRANFORMED variables" << Endl;
561 Log() << kINFO << " List of the transformation: " << Endl;
562 TListIter trIt(&GetTransformationHandler().GetTransformationList());
564 Log() << kINFO << " -- " << trf->GetName() << Endl;
565 }
566 }
567 std::vector<TString> vars;
568 std::vector<Double_t> coeffs;
569 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
570 vars .push_back( GetInputLabel(ivar) );
571 coeffs.push_back( (*fFisherCoeff)[ivar] );
572 }
573 vars .push_back( "(offset)" );
574 coeffs.push_back( fF0 );
575 TMVA::gTools().FormattedOutput( coeffs, vars, "Variable" , "Coefficient", Log() );
576
577 // for (int i=0; i<coeffs.size(); i++)
578 // std::cout << "fisher coeff["<<i<<"]="<<coeffs[i]<<std::endl;
579
580 if (IsNormalised()) {
581 Log() << kINFO << "NOTE: You have chosen to use the \"Normalise\" booking option. Hence, the" << Endl;
582 Log() << kINFO << " coefficients must be applied to NORMALISED (') variables as follows:" << Endl;
583 Int_t maxL = 0;
584 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) if (GetInputLabel(ivar).Length() > maxL) maxL = GetInputLabel(ivar).Length();
585
586 // Print normalisation expression (see Tools.cxx): "2*(x - xmin)/(xmax - xmin) - 1.0"
587 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
588 Log() << kINFO
589 << std::setw(maxL+9) << TString("[") + GetInputLabel(ivar) + "]' = 2*("
590 << std::setw(maxL+2) << TString("[") + GetInputLabel(ivar) + "]"
591 << std::setw(3) << (GetXmin(ivar) > 0 ? " - " : " + ")
592 << std::setw(6) << TMath::Abs(GetXmin(ivar)) << std::setw(3) << ")/"
593 << std::setw(6) << (GetXmax(ivar) - GetXmin(ivar) )
594 << std::setw(3) << " - 1"
595 << Endl;
596 }
597 Log() << kINFO << "The TMVA Reader will properly account for this normalisation, but if the" << Endl;
598 Log() << kINFO << "Fisher classifier is applied outside the Reader, the transformation must be" << Endl;
599 Log() << kINFO << "implemented -- or the \"Normalise\" option is removed and Fisher retrained." << Endl;
600 Log() << kINFO << Endl;
601 }
602}
603
604////////////////////////////////////////////////////////////////////////////////
605/// read Fisher coefficients from weight file
606
608{
609 istr >> fF0;
610 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) istr >> (*fFisherCoeff)[ivar];
611}
612
613////////////////////////////////////////////////////////////////////////////////
614/// create XML description of Fisher classifier
615
616void TMVA::MethodFisher::AddWeightsXMLTo( void* parent ) const
617{
618 void* wght = gTools().AddChild(parent, "Weights");
619 gTools().AddAttr( wght, "NCoeff", GetNvar()+1 );
620 void* coeffxml = gTools().AddChild(wght, "Coefficient");
621 gTools().AddAttr( coeffxml, "Index", 0 );
622 gTools().AddAttr( coeffxml, "Value", fF0 );
623 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
624 coeffxml = gTools().AddChild( wght, "Coefficient" );
625 gTools().AddAttr( coeffxml, "Index", ivar+1 );
626 gTools().AddAttr( coeffxml, "Value", (*fFisherCoeff)[ivar] );
627 }
628}
629
630////////////////////////////////////////////////////////////////////////////////
631/// read Fisher coefficients from xml weight file
632
634{
636 gTools().ReadAttr( wghtnode, "NCoeff", ncoeff );
637 fFisherCoeff->resize(ncoeff-1);
638
639 void* ch = gTools().GetChild(wghtnode);
641 while (ch) {
642 gTools().ReadAttr( ch, "Index", coeffidx );
643 gTools().ReadAttr( ch, "Value", coeff );
644 if (coeffidx==0) fF0 = coeff;
645 else (*fFisherCoeff)[coeffidx-1] = coeff;
646 ch = gTools().GetNextChild(ch);
647 }
648}
649
650////////////////////////////////////////////////////////////////////////////////
651/// write Fisher-specific classifier response
652
653void TMVA::MethodFisher::MakeClassSpecific( std::ostream& fout, const TString& className ) const
654{
655 Int_t dp = fout.precision();
656 fout << " double fFisher0;" << std::endl;
657 fout << " std::vector<double> fFisherCoefficients;" << std::endl;
658 fout << "};" << std::endl;
659 fout << "" << std::endl;
660 fout << "inline void " << className << "::Initialize() " << std::endl;
661 fout << "{" << std::endl;
662 fout << " fFisher0 = " << std::setprecision(12) << fF0 << ";" << std::endl;
663 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
664 fout << " fFisherCoefficients.push_back( " << std::setprecision(12) << (*fFisherCoeff)[ivar] << " );" << std::endl;
665 }
666 fout << std::endl;
667 fout << " // sanity check" << std::endl;
668 fout << " if (fFisherCoefficients.size() != fNvars) {" << std::endl;
669 fout << " std::cout << \"Problem in class \\\"\" << fClassName << \"\\\"::Initialize: mismatch in number of input values\"" << std::endl;
670 fout << " << fFisherCoefficients.size() << \" != \" << fNvars << std::endl;" << std::endl;
671 fout << " fStatusIsClean = false;" << std::endl;
672 fout << " } " << std::endl;
673 fout << "}" << std::endl;
674 fout << std::endl;
675 fout << "inline double " << className << "::GetMvaValue__( const std::vector<double>& inputValues ) const" << std::endl;
676 fout << "{" << std::endl;
677 fout << " double retval = fFisher0;" << std::endl;
678 fout << " for (size_t ivar = 0; ivar < fNvars; ivar++) {" << std::endl;
679 fout << " retval += fFisherCoefficients[ivar]*inputValues[ivar];" << std::endl;
680 fout << " }" << std::endl;
681 fout << std::endl;
682 fout << " return retval;" << std::endl;
683 fout << "}" << std::endl;
684 fout << std::endl;
685 fout << "// Clean up" << std::endl;
686 fout << "inline void " << className << "::Clear() " << std::endl;
687 fout << "{" << std::endl;
688 fout << " // clear coefficients" << std::endl;
689 fout << " fFisherCoefficients.clear(); " << std::endl;
690 fout << "}" << std::endl;
691 fout << std::setprecision(dp);
692}
693
694////////////////////////////////////////////////////////////////////////////////
695/// get help message text
696///
697/// typical length of text line:
698/// "|--------------------------------------------------------------|"
699
701{
702 Log() << Endl;
703 Log() << gTools().Color("bold") << "--- Short description:" << gTools().Color("reset") << Endl;
704 Log() << Endl;
705 Log() << "Fisher discriminants select events by distinguishing the mean " << Endl;
706 Log() << "values of the signal and background distributions in a trans- " << Endl;
707 Log() << "formed variable space where linear correlations are removed." << Endl;
708 Log() << Endl;
709 Log() << " (More precisely: the \"linear discriminator\" determines" << Endl;
710 Log() << " an axis in the (correlated) hyperspace of the input " << Endl;
711 Log() << " variables such that, when projecting the output classes " << Endl;
712 Log() << " (signal and background) upon this axis, they are pushed " << Endl;
713 Log() << " as far as possible away from each other, while events" << Endl;
714 Log() << " of a same class are confined in a close vicinity. The " << Endl;
715 Log() << " linearity property of this classifier is reflected in the " << Endl;
716 Log() << " metric with which \"far apart\" and \"close vicinity\" are " << Endl;
717 Log() << " determined: the covariance matrix of the discriminating" << Endl;
718 Log() << " variable space.)" << Endl;
719 Log() << Endl;
720 Log() << gTools().Color("bold") << "--- Performance optimisation:" << gTools().Color("reset") << Endl;
721 Log() << Endl;
722 Log() << "Optimal performance for Fisher discriminants is obtained for " << Endl;
723 Log() << "linearly correlated Gaussian-distributed variables. Any deviation" << Endl;
724 Log() << "from this ideal reduces the achievable separation power. In " << Endl;
725 Log() << "particular, no discrimination at all is achieved for a variable" << Endl;
726 Log() << "that has the same sample mean for signal and background, even if " << Endl;
727 Log() << "the shapes of the distributions are very different. Thus, Fisher " << Endl;
728 Log() << "discriminants often benefit from suitable transformations of the " << Endl;
729 Log() << "input variables. For example, if a variable x in [-1,1] has a " << Endl;
730 Log() << "a parabolic signal distributions, and a uniform background" << Endl;
731 Log() << "distributions, their mean value is zero in both cases, leading " << Endl;
732 Log() << "to no separation. The simple transformation x -> |x| renders this " << Endl;
733 Log() << "variable powerful for the use in a Fisher discriminant." << Endl;
734 Log() << Endl;
735 Log() << gTools().Color("bold") << "--- Performance tuning via configuration options:" << gTools().Color("reset") << Endl;
736 Log() << Endl;
737 Log() << "<None>" << Endl;
738}
#define REGISTER_METHOD(CLASS)
for example
#define d(i)
Definition RSha256.hxx:102
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
TMatrixT< Double_t > TMatrixD
Definition TMatrixDfwd.h:23
Iterator of linked list.
Definition TList.h:196
Class that contains all the data information.
Definition DataSetInfo.h:62
Virtual base Class for all MVA method.
Definition MethodBase.h:82
Fisher and Mahalanobis Discriminants (Linear Discriminant Analysis)
void GetCov_Full(void)
compute full covariance matrix from sum of within and between matrices
void GetHelpMessage() const override
get help message text
MethodFisher(const TString &jobName, const TString &methodTitle, DataSetInfo &dsi, const TString &theOption="Fisher")
standard constructor for the "Fisher"
virtual ~MethodFisher(void)
destructor
Bool_t HasAnalysisType(Types::EAnalysisType type, UInt_t numberClasses, UInt_t numberTargets) override
Fisher can only handle classification with 2 classes.
void AddWeightsXMLTo(void *parent) const override
create XML description of Fisher classifier
void GetDiscrimPower(void)
computation of discrimination power indicator for each variable small values of "fWith" indicates lit...
void PrintCoefficients(void)
display Fisher coefficients and discriminating power for each variable check maximum length of variab...
void GetCov_BetweenClass(void)
the matrix of covariance 'between class' reflects the dispersion of the events of a class relative to...
void Init(void) override
default initialization called by all constructors
void DeclareOptions() override
MethodFisher options: format and syntax of option string: "type" where type is "Fisher" or "Mahalanob...
void MakeClassSpecific(std::ostream &, const TString &) const override
write Fisher-specific classifier response
void ReadWeightsFromXML(void *wghtnode) override
read Fisher coefficients from xml weight file
void GetFisherCoeff(void)
Fisher = Sum { [coeff]*[variables] }.
void GetMean(void)
compute mean values of variables in each sample, and the overall means
void Train(void) override
computation of Fisher coefficients by series of matrix operations
void InitMatrices(void)
initialization method; creates global matrices and vectors
void GetCov_WithinClass(void)
the matrix of covariance 'within class' reflects the dispersion of the events relative to the center ...
Double_t GetMvaValue(Double_t *err=nullptr, Double_t *errUpper=nullptr) override
returns the Fisher value (no fixed range)
void ProcessOptions() override
process user options
const Ranking * CreateRanking() override
computes ranking of input variables
void ReadWeightsFromStream(std::istream &i) override
read Fisher coefficients from weight file
Ranking for variables in method (implementation)
Definition Ranking.h:48
void FormattedOutput(const std::vector< Double_t > &, const std::vector< TString > &, const TString titleVars, const TString titleValues, MsgLogger &logger, TString format="%+1.3f")
formatted output of simple table
Definition Tools.cxx:862
const TString & Color(const TString &)
human readable color strings
Definition Tools.cxx:803
void ReadAttr(void *node, const char *, T &value)
read attribute from xml
Definition Tools.h:329
void * GetChild(void *parent, const char *childname=nullptr)
get child node
Definition Tools.cxx:1125
void AddAttr(void *node, const char *, const T &value, Int_t precision=16)
add attribute to xml
Definition Tools.h:347
void * AddChild(void *parent, const char *childname, const char *content=nullptr, bool isRootNode=false)
add child node
Definition Tools.cxx:1099
void * GetNextChild(void *prevchild, const char *childname=nullptr)
XML helpers.
Definition Tools.cxx:1137
Singleton class for Global types used by TMVA.
Definition Types.h:71
@ kClassification
Definition Types.h:127
Linear interpolation class.
Basic string class.
Definition TString.h:138
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
create variable transformations
Tools & gTools()
MsgLogger & Endl(MsgLogger &ml)
Definition MsgLogger.h:148
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:675
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2338