00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 #include "TMVA/LDA.h"
00028 
00029 
00030 #include <iostream>
00031 
00032 #ifndef ROOT_TDecompSVD
00033 #include "TDecompSVD.h"       
00034 #endif
00035 #ifndef ROOT_TMatrixF
00036 #include "TMatrixF.h"       
00037 #endif
00038 #ifndef ROOT_TMath
00039 #include "TMath.h"       
00040 #endif
00041 
00042 #ifndef ROOT_TMVA_Types
00043 #include "TMVA/Types.h"       
00044 #endif
00045 #ifndef ROOT_TMVA_MsgLogger
00046 #include "TMVA/MsgLogger.h"       
00047 #endif
00048 
00049 
00050 TMVA::LDA::LDA( Float_t tolerence, Bool_t debug ) 
00051    : fTolerence(tolerence),
00052      fNumParams(0),
00053      fSigma(0),
00054      fSigmaInverse(0),
00055      fDebug(debug),
00056      fLogger( new MsgLogger("LDA", (debug?kINFO:kDEBUG)) )
00057 {
00058    
00059 }
00060 
00061 
00062 TMVA::LDA::~LDA()
00063 {
00064    
00065    delete fLogger;
00066 }
00067 
00068 
00069 void TMVA::LDA::Initialize(const LDAEvents& inputSignalEvents, const LDAEvents& inputBackgroundEvents)
00070 {
00071    
00072    Log() << kDEBUG << "There are: " << inputSignalEvents.size() << " input signal events " << Endl;
00073    Log() << kDEBUG << "There are: " << inputBackgroundEvents.size() << " input background events " << Endl;
00074 
00075    fNumParams = inputSignalEvents[0].size();
00076   
00077    UInt_t numSignalEvents = inputSignalEvents.size();
00078    UInt_t numBackEvents  = inputBackgroundEvents.size();
00079    UInt_t numTotalEvents = numSignalEvents + numBackEvents;
00080    fEventFraction[0] = (Float_t)numBackEvents/numTotalEvents;
00081    fEventFraction[1] = (Float_t)numSignalEvents/numTotalEvents;
00082    UInt_t K = 2;
00083 
00084    
00085    std::vector<Float_t> m_muSignal (fNumParams,0.0);
00086    std::vector<Float_t> m_muBackground (fNumParams,0.0);
00087    for (UInt_t param=0; param < fNumParams; ++param) {
00088       for (UInt_t eventNumber=0; eventNumber < numSignalEvents; ++eventNumber)
00089          m_muSignal[param] += inputSignalEvents[eventNumber][param];
00090       for (UInt_t eventNumber=0; eventNumber < numBackEvents; ++eventNumber)
00091          m_muBackground[param] += inputBackgroundEvents[eventNumber][param]/numBackEvents;
00092       m_muSignal[param] /= numSignalEvents;
00093       m_muBackground[param] /= numBackEvents;
00094    }
00095    fMu[0] = m_muBackground;
00096    fMu[1] = m_muSignal;
00097 
00098    if (fDebug) {
00099       Log() << kDEBUG << "the signal means" << Endl;
00100       for (UInt_t param=0; param < fNumParams; ++param)
00101          Log() << kDEBUG << m_muSignal[param] << Endl;
00102       Log() << kDEBUG << "the background means" << Endl;
00103       for (UInt_t param=0; param < inputBackgroundEvents[0].size(); ++param)
00104          Log() << kDEBUG << m_muBackground[param] << Endl;
00105    }
00106   
00107    
00108    
00109   
00110    
00111    TMatrixF sigmaSignal(fNumParams, fNumParams);
00112    TMatrixF sigmaBack(fNumParams, fNumParams);
00113    if (fSigma!=0) delete fSigma;
00114    fSigma = new TMatrixF(fNumParams, fNumParams);
00115    for (UInt_t row=0; row < fNumParams; ++row) {
00116       for (UInt_t col=0; col < fNumParams; ++col) {
00117          sigmaSignal[row][col] = 0;
00118          sigmaBack[row][col] = 0;
00119          (*fSigma)[row][col] = 0;
00120       }
00121    }
00122 
00123    for (UInt_t eventNumber=0; eventNumber < numSignalEvents; ++eventNumber) {
00124       for (UInt_t row=0; row < fNumParams; ++row) {
00125          for (UInt_t col=0; col < fNumParams; ++col) {
00126             sigmaSignal[row][col] += (inputSignalEvents[eventNumber][row] - m_muSignal[row]) * (inputSignalEvents[eventNumber][col] - m_muSignal[col] );
00127          }
00128       }
00129    }
00130   
00131    for (UInt_t eventNumber=0; eventNumber < numBackEvents; ++eventNumber) {
00132       for (UInt_t row=0; row < fNumParams; ++row) {
00133          for (UInt_t col=0; col < fNumParams; ++col) {
00134             sigmaBack[row][col] += (inputBackgroundEvents[eventNumber][row] - m_muBackground[row]) * (inputBackgroundEvents[eventNumber][col] - m_muBackground[col] );
00135          }
00136       }
00137    }   
00138 
00139    
00140    *fSigma = sigmaBack + sigmaSignal;
00141    *fSigma *= 1.0/(numTotalEvents - K);
00142   
00143    if (fDebug) {
00144       Log() << "after filling sigmaSignal" <<Endl;
00145       sigmaSignal.Print();
00146       Log() << "after filling sigmaBack" <<Endl;
00147       sigmaBack.Print();
00148       Log() << "after filling total Sigma" <<Endl;
00149       fSigma->Print();
00150    }
00151 
00152    TDecompSVD solutionSVD = TDecompSVD( *fSigma );
00153    TMatrixF   decomposed  = TMatrixF( fNumParams, fNumParams );
00154    TMatrixF diag  ( fNumParams, fNumParams );
00155    TMatrixF uTrans( fNumParams, fNumParams );
00156    TMatrixF vTrans( fNumParams, fNumParams );
00157    if (solutionSVD.Decompose()) {
00158       for (UInt_t i = 0; i< fNumParams; ++i) {
00159          if (solutionSVD.GetSig()[i] > fTolerence)
00160             diag(i,i) = solutionSVD.GetSig()[i];
00161          else
00162             diag(i,i) = fTolerence;
00163       }
00164 
00165       if (fDebug) {
00166          Log() << "the diagonal" <<Endl;
00167          diag.Print();
00168       }
00169 
00170       decomposed = solutionSVD.GetV();
00171       decomposed *= diag;
00172       decomposed *= solutionSVD.GetU();
00173     
00174       if (fDebug) {
00175          Log() << "the decomposition " <<Endl;
00176          decomposed.Print();
00177       }
00178     
00179       *fSigmaInverse = uTrans.Transpose(solutionSVD.GetU());
00180       *fSigmaInverse /= diag;
00181       *fSigmaInverse *= vTrans.Transpose(solutionSVD.GetV());
00182 
00183       if (fDebug) {
00184          Log() << "the SigmaInverse " <<Endl;
00185          fSigmaInverse->Print();
00186         
00187          Log() << "the real " <<Endl;
00188          fSigma->Invert();
00189          fSigma->Print();
00190       
00191          Bool_t problem = false;
00192          for (UInt_t i =0; i< fNumParams; ++i) {
00193             for (UInt_t j =0; j< fNumParams; ++j) {
00194                if (TMath::Abs((Float_t)(*fSigma)(i,j) - (Float_t)(*fSigmaInverse)(i,j)) > 0.01) {
00195                   Log() << "problem, i= "<< i << " j= " << j << Endl; 
00196                   Log() << "Sigma(i,j)= "<< (*fSigma)(i,j) << " SigmaInverse(i,j)= " << (*fSigmaInverse)(i,j) <<Endl; 
00197                   Log() << "The difference is : " << TMath::Abs((Float_t)(*fSigma)(i,j) - (Float_t)(*fSigmaInverse)(i,j)) <<Endl;
00198                   problem = true;
00199                }
00200             }
00201          }
00202          if (problem) Log() << kWARNING << "Problem with the inversion!" << Endl;
00203          
00204       }    
00205    }
00206 }
00207 
00208 
00209 Float_t TMVA::LDA::FSub(const std::vector<Float_t>& x, Int_t k)
00210 {
00211    
00212    
00213    
00214    Float_t prefactor  = 1.0/(TMath::TwoPi()*TMath::Sqrt(fSigma->Determinant()));
00215    std::vector<Float_t> m_transPoseTimesSigmaInverse;
00216   
00217    for (UInt_t j=0; j < fNumParams; ++j) {
00218       Float_t m_temp = 0;
00219       for (UInt_t i=0; i < fNumParams; ++i) {
00220          m_temp += (x[i] - fMu[k][i]) * (*fSigmaInverse)(j,i);
00221       }
00222       m_transPoseTimesSigmaInverse.push_back(m_temp);
00223    }
00224   
00225    Float_t exponent = 0.0;
00226    for (UInt_t i=0; i< fNumParams; ++i) {
00227       exponent += m_transPoseTimesSigmaInverse[i]*(x[i] - fMu[k][i]);
00228    }
00229   
00230    exponent *= -0.5;
00231 
00232    return prefactor*TMath::Exp( exponent );
00233 }
00234 
00235 
00236 Float_t TMVA::LDA::GetProb(const std::vector<Float_t>& x, Int_t k)
00237 {
00238    
00239    
00240    
00241    Float_t m_numerator = FSub(x,k)*fEventFraction[k];
00242    Float_t m_denominator = FSub(x,0)*fEventFraction[0]+FSub(x,1)*fEventFraction[1];
00243 
00244    return m_numerator/m_denominator;
00245 }
00246 
00247 
00248 Float_t TMVA::LDA::GetLogLikelihood( const std::vector<Float_t>& x, Int_t k )
00249 {
00250    
00251    
00252    
00253    return TMath::Log( FSub(x,k)/FSub(x,!k) ) + TMath::Log( fEventFraction[k]/fEventFraction[!k] );
00254 }