47 TMVA::LDA::LDA( Float_t tolerence, Bool_t debug )
48 : fTolerence(tolerence),
53 fLogger( new MsgLogger(
"LDA", (debug?kINFO:kDEBUG)) )
68 void TMVA::LDA::Initialize(
const LDAEvents& inputSignalEvents,
const LDAEvents& inputBackgroundEvents)
70 Log() << kDEBUG <<
"There are: " << inputSignalEvents.size() <<
" input signal events " << Endl;
71 Log() << kDEBUG <<
"There are: " << inputBackgroundEvents.size() <<
" input background events " << Endl;
73 fNumParams = inputSignalEvents[0].size();
75 UInt_t numSignalEvents = inputSignalEvents.size();
76 UInt_t numBackEvents = inputBackgroundEvents.size();
77 UInt_t numTotalEvents = numSignalEvents + numBackEvents;
78 fEventFraction[0] = (Float_t)numBackEvents/numTotalEvents;
79 fEventFraction[1] = (Float_t)numSignalEvents/numTotalEvents;
83 std::vector<Float_t> m_muSignal (fNumParams,0.0);
84 std::vector<Float_t> m_muBackground (fNumParams,0.0);
85 for (UInt_t param=0; param < fNumParams; ++param) {
86 for (UInt_t eventNumber=0; eventNumber < numSignalEvents; ++eventNumber)
87 m_muSignal[param] += inputSignalEvents[eventNumber][param];
88 for (UInt_t eventNumber=0; eventNumber < numBackEvents; ++eventNumber)
89 m_muBackground[param] += inputBackgroundEvents[eventNumber][param]/numBackEvents;
90 if (numSignalEvents > 0) m_muSignal[param] /= numSignalEvents;
91 if (numBackEvents > 0 ) m_muBackground[param] /= numBackEvents;
93 fMu[0] = m_muBackground;
97 Log() << kDEBUG <<
"the signal means" << Endl;
98 for (UInt_t param=0; param < fNumParams; ++param)
99 Log() << kDEBUG << m_muSignal[param] << Endl;
100 Log() << kDEBUG <<
"the background means" << Endl;
101 for (UInt_t param=0; param < inputBackgroundEvents[0].size(); ++param)
102 Log() << kDEBUG << m_muBackground[param] << Endl;
109 TMatrixF sigmaSignal(fNumParams, fNumParams);
110 TMatrixF sigmaBack(fNumParams, fNumParams);
111 if (fSigma!=0)
delete fSigma;
112 fSigma =
new TMatrixF(fNumParams, fNumParams);
113 for (UInt_t row=0; row < fNumParams; ++row) {
114 for (UInt_t col=0; col < fNumParams; ++col) {
115 sigmaSignal[row][col] = 0;
116 sigmaBack[row][col] = 0;
117 (*fSigma)[row][col] = 0;
121 for (UInt_t eventNumber=0; eventNumber < numSignalEvents; ++eventNumber) {
122 for (UInt_t row=0; row < fNumParams; ++row) {
123 for (UInt_t col=0; col < fNumParams; ++col) {
124 sigmaSignal[row][col] += (inputSignalEvents[eventNumber][row] - m_muSignal[row]) * (inputSignalEvents[eventNumber][col] - m_muSignal[col] );
129 for (UInt_t eventNumber=0; eventNumber < numBackEvents; ++eventNumber) {
130 for (UInt_t row=0; row < fNumParams; ++row) {
131 for (UInt_t col=0; col < fNumParams; ++col) {
132 sigmaBack[row][col] += (inputBackgroundEvents[eventNumber][row] - m_muBackground[row]) * (inputBackgroundEvents[eventNumber][col] - m_muBackground[col] );
138 *fSigma = sigmaBack + sigmaSignal;
139 *fSigma *= 1.0/(numTotalEvents - K);
142 Log() <<
"after filling sigmaSignal" <<Endl;
144 Log() <<
"after filling sigmaBack" <<Endl;
146 Log() <<
"after filling total Sigma" <<Endl;
150 TDecompSVD solutionSVD = TDecompSVD( *fSigma );
151 TMatrixF decomposed = TMatrixF( fNumParams, fNumParams );
152 TMatrixF diag ( fNumParams, fNumParams );
153 TMatrixF uTrans( fNumParams, fNumParams );
154 TMatrixF vTrans( fNumParams, fNumParams );
155 if (solutionSVD.Decompose()) {
156 for (UInt_t i = 0; i< fNumParams; ++i) {
157 if (solutionSVD.GetSig()[i] > fTolerence)
158 diag(i,i) = solutionSVD.GetSig()[i];
160 diag(i,i) = fTolerence;
164 Log() <<
"the diagonal" <<Endl;
168 decomposed = solutionSVD.GetV();
170 decomposed *= solutionSVD.GetU();
173 Log() <<
"the decomposition " <<Endl;
177 *fSigmaInverse = uTrans.Transpose(solutionSVD.GetU());
178 *fSigmaInverse /= diag;
179 *fSigmaInverse *= vTrans.Transpose(solutionSVD.GetV());
182 Log() <<
"the SigmaInverse " <<Endl;
183 fSigmaInverse->Print();
185 Log() <<
"the real " <<Endl;
189 Bool_t problem =
false;
190 for (UInt_t i =0; i< fNumParams; ++i) {
191 for (UInt_t j =0; j< fNumParams; ++j) {
192 if (TMath::Abs((Float_t)(*fSigma)(i,j) - (Float_t)(*fSigmaInverse)(i,j)) > 0.01) {
193 Log() <<
"problem, i= "<< i <<
" j= " << j << Endl;
194 Log() <<
"Sigma(i,j)= "<< (*fSigma)(i,j) <<
" SigmaInverse(i,j)= " << (*fSigmaInverse)(i,j) <<Endl;
195 Log() <<
"The difference is : " << TMath::Abs((Float_t)(*fSigma)(i,j) - (Float_t)(*fSigmaInverse)(i,j)) <<Endl;
200 if (problem) Log() << kWARNING <<
"Problem with the inversion!" << Endl;
211 Float_t TMVA::LDA::FSub(
const std::vector<Float_t>& x, Int_t k)
213 Float_t prefactor = 1.0/(TMath::TwoPi()*TMath::Sqrt(fSigma->Determinant()));
214 std::vector<Float_t> m_transPoseTimesSigmaInverse;
216 for (UInt_t j=0; j < fNumParams; ++j) {
218 for (UInt_t i=0; i < fNumParams; ++i) {
219 m_temp += (x[i] - fMu[k][i]) * (*fSigmaInverse)(j,i);
221 m_transPoseTimesSigmaInverse.push_back(m_temp);
224 Float_t exponent = 0.0;
225 for (UInt_t i=0; i< fNumParams; ++i) {
226 exponent += m_transPoseTimesSigmaInverse[i]*(x[i] - fMu[k][i]);
231 return prefactor*TMath::Exp( exponent );
239 Float_t TMVA::LDA::GetProb(
const std::vector<Float_t>& x, Int_t k)
241 Float_t m_numerator = FSub(x,k)*fEventFraction[k];
242 Float_t m_denominator = FSub(x,0)*fEventFraction[0]+FSub(x,1)*fEventFraction[1];
244 return m_numerator/m_denominator;
252 Float_t TMVA::LDA::GetLogLikelihood(
const std::vector<Float_t>& x, Int_t k )
254 return TMath::Log( FSub(x,k)/FSub(x,!k) ) + TMath::Log( fEventFraction[k]/fEventFraction[!k] );