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 }