00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "TROOT.h"
00024 #include "TSynapse.h"
00025 #include "TNeuron.h"
00026 #include "TMultiLayerPerceptron.h"
00027 #include "TMLPAnalyzer.h"
00028 #include "TTree.h"
00029 #include "TTreeFormula.h"
00030 #include "TEventList.h"
00031 #include "TH1D.h"
00032 #include "TProfile.h"
00033 #include "THStack.h"
00034 #include "TLegend.h"
00035 #include "TPad.h"
00036 #include "TCanvas.h"
00037 #include "TGaxis.h"
00038 #include "TRegexp.h"
00039 #include "TMath.h"
00040 #include "Riostream.h"
00041 #include <stdlib.h>
00042
00043 ClassImp(TMLPAnalyzer)
00044
00045
00046 TMLPAnalyzer::~TMLPAnalyzer()
00047 {
00048
00049 delete fAnalysisTree;
00050 delete fIOTree;
00051 }
00052
00053
00054 Int_t TMLPAnalyzer::GetLayers()
00055 {
00056
00057
00058 TString fStructure = fNetwork->GetStructure();
00059 return fStructure.CountChar(':')+1;
00060 }
00061
00062
00063 Int_t TMLPAnalyzer::GetNeurons(Int_t layer)
00064 {
00065
00066
00067 if(layer==1) {
00068 TString fStructure = fNetwork->GetStructure();
00069 TString input = TString(fStructure(0, fStructure.First(':')));
00070 return input.CountChar(',')+1;
00071 }
00072 else if(layer==GetLayers()) {
00073 TString fStructure = fNetwork->GetStructure();
00074 TString output = TString(fStructure(fStructure.Last(':') + 1,
00075 fStructure.Length() - fStructure.Last(':')));
00076 return output.CountChar(',')+1;
00077 }
00078 else {
00079 Int_t cnt=1;
00080 TString fStructure = fNetwork->GetStructure();
00081 TString hidden = TString(fStructure(fStructure.First(':') + 1,
00082 fStructure.Last(':') - fStructure.First(':') - 1));
00083 Int_t beg = 0;
00084 Int_t end = hidden.Index(":", beg + 1);
00085 Int_t num = 0;
00086 while (end != -1) {
00087 num = atoi(TString(hidden(beg, end - beg)).Data());
00088 cnt++;
00089 beg = end + 1;
00090 end = hidden.Index(":", beg + 1);
00091 if(layer==cnt) return num;
00092 }
00093 num = atoi(TString(hidden(beg, hidden.Length() - beg)).Data());
00094 cnt++;
00095 if(layer==cnt) return num;
00096 }
00097 return -1;
00098 }
00099
00100
00101 TString TMLPAnalyzer::GetNeuronFormula(Int_t idx)
00102 {
00103
00104
00105
00106 TString fStructure = fNetwork->GetStructure();
00107 TString input = TString(fStructure(0, fStructure.First(':')));
00108 Int_t beg = 0;
00109 Int_t end = input.Index(",", beg + 1);
00110 TString brName;
00111 Int_t cnt = 0;
00112 while (end != -1) {
00113 brName = TString(input(beg, end - beg));
00114 if (brName[0]=='@')
00115 brName = brName(1,brName.Length()-1);
00116 beg = end + 1;
00117 end = input.Index(",", beg + 1);
00118 if(cnt==idx) return brName;
00119 cnt++;
00120 }
00121 brName = TString(input(beg, input.Length() - beg));
00122 if (brName[0]=='@')
00123 brName = brName(1,brName.Length()-1);
00124 return brName;
00125 }
00126
00127
00128 const char* TMLPAnalyzer::GetInputNeuronTitle(Int_t in)
00129 {
00130
00131 TNeuron* neuron=(TNeuron*)fNetwork->fFirstLayer[in];
00132 return neuron ? neuron->GetName() : "NO SUCH NEURON";
00133 }
00134
00135
00136 const char* TMLPAnalyzer::GetOutputNeuronTitle(Int_t out)
00137 {
00138
00139 TNeuron* neuron=(TNeuron*)fNetwork->fLastLayer[out];
00140 return neuron ? neuron->GetName() : "NO SUCH NEURON";
00141 }
00142
00143
00144 void TMLPAnalyzer::CheckNetwork()
00145 {
00146
00147
00148 TString fStructure = fNetwork->GetStructure();
00149 cout << "Network with structure: " << fStructure.Data() << endl;
00150 cout << "inputs with low values in the differences plot may not be needed" << endl;
00151
00152 char var[64], sel[64];
00153 for (Int_t i = 0; i < GetNeurons(1); i++) {
00154 snprintf(var,64,"diff>>tmp%d",i);
00155 snprintf(sel,64,"inNeuron==%d",i);
00156 fAnalysisTree->Draw(var, sel, "goff");
00157 TH1F* tmp = (TH1F*)gDirectory->Get(Form("tmp%d",i));
00158 if (!tmp) continue;
00159 cout << GetInputNeuronTitle(i)
00160 << " -> " << tmp->GetMean()
00161 << " +/- " << tmp->GetRMS() << endl;
00162 }
00163 }
00164
00165
00166 void TMLPAnalyzer::GatherInformations()
00167 {
00168
00169
00170
00171
00172 Double_t shift = 0.1;
00173 TTree* data = fNetwork->fData;
00174 TEventList* test = fNetwork->fTest;
00175 Int_t nEvents = test->GetN();
00176 Int_t nn = GetNeurons(1);
00177 Double_t* params = new Double_t[nn];
00178 Double_t* rms = new Double_t[nn];
00179 TTreeFormula** formulas = new TTreeFormula*[nn];
00180 Int_t* index = new Int_t[nn];
00181 TString formula;
00182 TRegexp re("{[0-9]+}$");
00183 Ssiz_t len = formula.Length();
00184 Ssiz_t pos = -1;
00185 Int_t i(0), j(0), k(0), l(0);
00186 for(i=0; i<nn; i++){
00187 formula = GetNeuronFormula(i);
00188 pos = re.Index(formula,&len);
00189 if(pos==-1 || len<3) {
00190 formulas[i] = new TTreeFormula(Form("NF%lu",(ULong_t)this),formula,data);
00191 index[i] = 0;
00192 }
00193 else {
00194 TString newformula(formula,pos);
00195 TString val = formula(pos+1,len-2);
00196 formulas[i] = new TTreeFormula(Form("NF%lu",(ULong_t)this),newformula,data);
00197 formula = newformula;
00198 index[i] = val.Atoi();
00199 }
00200 TH1D tmp("tmpb", "tmpb", 1, -FLT_MAX, FLT_MAX);
00201 data->Draw(Form("%s>>tmpb",formula.Data()),"","goff");
00202 rms[i] = tmp.GetRMS();
00203 }
00204 Int_t inNeuron = 0;
00205 Double_t diff = 0.;
00206 if(fAnalysisTree) delete fAnalysisTree;
00207 fAnalysisTree = new TTree("result","analysis");
00208 fAnalysisTree->SetDirectory(0);
00209 fAnalysisTree->Branch("inNeuron",&inNeuron,"inNeuron/I");
00210 fAnalysisTree->Branch("diff",&diff,"diff/D");
00211 Int_t numOutNodes=GetNeurons(GetLayers());
00212 Double_t *outVal=new Double_t[numOutNodes];
00213 Double_t *trueVal=new Double_t[numOutNodes];
00214
00215 delete fIOTree;
00216 fIOTree=new TTree("MLP_iotree","MLP_iotree");
00217 fIOTree->SetDirectory(0);
00218 TString leaflist;
00219 for (i=0; i<nn; i++)
00220 leaflist+=Form("In%d/D:",i);
00221 leaflist.Remove(leaflist.Length()-1);
00222 fIOTree->Branch("In", params, leaflist);
00223
00224 leaflist="";
00225 for (i=0; i<numOutNodes; i++)
00226 leaflist+=Form("Out%d/D:",i);
00227 leaflist.Remove(leaflist.Length()-1);
00228 fIOTree->Branch("Out", outVal, leaflist);
00229
00230 leaflist="";
00231 for (i=0; i<numOutNodes; i++)
00232 leaflist+=Form("True%d/D:",i);
00233 leaflist.Remove(leaflist.Length()-1);
00234 fIOTree->Branch("True", trueVal, leaflist);
00235 Double_t v1 = 0.;
00236 Double_t v2 = 0.;
00237
00238 for(j=0; j< nEvents; j++) {
00239 fNetwork->GetEntry(test->GetEntry(j));
00240
00241 for(k=0; k<GetNeurons(1); k++) {
00242 params[k] = formulas[k]->EvalInstance(index[k]);
00243 }
00244 for(k=0; k<GetNeurons(GetLayers()); k++) {
00245 outVal[k] = fNetwork->Evaluate(k,params);
00246 trueVal[k] = ((TNeuron*)fNetwork->fLastLayer[k])->GetBranch();
00247 }
00248 fIOTree->Fill();
00249
00250
00251 for (i = 0; i < GetNeurons(1); i++) {
00252 inNeuron = i;
00253 diff = 0;
00254
00255 for(l=0; l<GetNeurons(GetLayers()); l++){
00256 params[i] += shift*rms[i];
00257 v1 = fNetwork->Evaluate(l,params);
00258 params[i] -= 2*shift*rms[i];
00259 v2 = fNetwork->Evaluate(l,params);
00260 diff += (v1-v2)*(v1-v2);
00261
00262 params[i] += shift*rms[i];
00263 }
00264 diff = TMath::Sqrt(diff);
00265 fAnalysisTree->Fill();
00266 }
00267 }
00268 delete[] params;
00269 delete[] rms;
00270 delete[] outVal;
00271 delete[] trueVal;
00272 delete[] index;
00273 for(i=0; i<GetNeurons(1); i++) delete formulas[i]; delete [] formulas;
00274 fAnalysisTree->ResetBranchAddresses();
00275 fIOTree->ResetBranchAddresses();
00276 }
00277
00278
00279 void TMLPAnalyzer::DrawDInput(Int_t i)
00280 {
00281
00282
00283
00284
00285 char sel[64];
00286 snprintf(sel,64, "inNeuron==%d", i);
00287 fAnalysisTree->Draw("diff", sel);
00288 }
00289
00290
00291 void TMLPAnalyzer::DrawDInputs()
00292 {
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 THStack* stack = new THStack("differences","differences (impact of variables on ANN)");
00313 TLegend* legend = new TLegend(0.75,0.75,0.95,0.95);
00314 TH1F* tmp = 0;
00315 char var[64], sel[64];
00316 for(Int_t i = 0; i < GetNeurons(1); i++) {
00317 snprintf(var,64, "diff>>tmp%d", i);
00318 snprintf(sel,64, "inNeuron==%d", i);
00319 fAnalysisTree->Draw(var, sel, "goff");
00320 tmp = (TH1F*)gDirectory->Get(Form("tmp%d",i));
00321 tmp->SetDirectory(0);
00322 tmp->SetLineColor(i+1);
00323 stack->Add(tmp);
00324 legend->AddEntry(tmp,GetInputNeuronTitle(i),"l");
00325 }
00326 stack->Draw("nostack");
00327 legend->Draw();
00328 gPad->SetLogy();
00329 }
00330
00331
00332 void TMLPAnalyzer::DrawNetwork(Int_t neuron, const char* signal, const char* bg)
00333 {
00334
00335
00336
00337
00338 TTree* data = fNetwork->fData;
00339 TEventList* test = fNetwork->fTest;
00340 TEventList* current = data->GetEventList();
00341 data->SetEventList(test);
00342 THStack* stack = new THStack("__NNout_TMLPA",Form("Neural net output (neuron %d)",neuron));
00343 TH1F *bgh = new TH1F("__bgh_TMLPA", "NN output", 50, -0.5, 1.5);
00344 TH1F *sigh = new TH1F("__sigh_TMLPA", "NN output", 50, -0.5, 1.5);
00345 bgh->SetDirectory(0);
00346 sigh->SetDirectory(0);
00347 Int_t nEvents = 0;
00348 Int_t j=0;
00349
00350 TEventList* signal_list = new TEventList("__tmpSig_MLPA");
00351 TEventList* bg_list = new TEventList("__tmpBkg_MLPA");
00352 data->Draw(">>__tmpSig_MLPA",signal,"goff");
00353 data->Draw(">>__tmpBkg_MLPA",bg,"goff");
00354
00355
00356 nEvents = bg_list->GetN();
00357 for(j=0; j< nEvents; j++) {
00358 bgh->Fill(fNetwork->Result(bg_list->GetEntry(j),neuron));
00359 }
00360
00361 nEvents = signal_list->GetN();
00362 for(j=0; j< nEvents; j++) {
00363 sigh->Fill(fNetwork->Result(signal_list->GetEntry(j),neuron));
00364 }
00365
00366 bgh->SetLineColor(kBlue);
00367 bgh->SetFillStyle(3008);
00368 bgh->SetFillColor(kBlue);
00369 sigh->SetLineColor(kRed);
00370 sigh->SetFillStyle(3003);
00371 sigh->SetFillColor(kRed);
00372 bgh->SetStats(0);
00373 sigh->SetStats(0);
00374 stack->Add(bgh);
00375 stack->Add(sigh);
00376 TLegend *legend = new TLegend(.75, .80, .95, .95);
00377 legend->AddEntry(bgh, "Background");
00378 legend->AddEntry(sigh,"Signal");
00379 stack->Draw("nostack");
00380 legend->Draw();
00381
00382 data->SetEventList(current);
00383 delete signal_list;
00384 delete bg_list;
00385 }
00386
00387
00388 TProfile* TMLPAnalyzer::DrawTruthDeviation(Int_t outnode ,
00389 Option_t *option )
00390 {
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 if (!fIOTree) GatherInformations();
00401 TString pipehist=Form("MLP_truthdev_%d",outnode);
00402 TString drawline;
00403 drawline.Form("Out.Out%d-True.True%d:True.True%d>>",
00404 outnode, outnode, outnode);
00405 fIOTree->Draw(drawline+pipehist+"(20)", "", "goff prof");
00406 TProfile* h=(TProfile*)gDirectory->Get(pipehist);
00407 h->SetDirectory(0);
00408 const char* title=GetOutputNeuronTitle(outnode);
00409 if (title) {
00410 h->SetTitle(Form("#Delta(output - truth) vs. truth for %s",
00411 title));
00412 h->GetXaxis()->SetTitle(title);
00413 h->GetYaxis()->SetTitle(Form("#Delta(output - truth) for %s", title));
00414 }
00415 if (!strstr(option,"goff"))
00416 h->Draw();
00417 return h;
00418 }
00419
00420
00421 THStack* TMLPAnalyzer::DrawTruthDeviations(Option_t *option )
00422 {
00423
00424
00425
00426
00427
00428
00429
00430
00431 THStack *hs=new THStack("MLP_TruthDeviation",
00432 "Deviation of MLP output from truth");
00433
00434
00435 TLegend *leg=0;
00436 if (!option || !strstr(option,"goff"))
00437 leg=new TLegend(.4,.85,.95,.95,"#Delta(output - truth) vs. truth for:");
00438
00439 const char* xAxisTitle=0;
00440
00441
00442
00443 for (Int_t outnode=0; outnode<GetNeurons(GetLayers()); outnode++) {
00444 TProfile* h=DrawTruthDeviation(outnode, "goff");
00445 h->SetLineColor(1+outnode);
00446 hs->Add(h, option);
00447 if (leg) leg->AddEntry(h,GetOutputNeuronTitle(outnode));
00448 if (!outnode)
00449
00450 xAxisTitle=h->GetXaxis()->GetTitle();
00451 }
00452
00453 if (leg) {
00454 hs->Draw("nostack");
00455 leg->Draw();
00456
00457 hs->GetXaxis()->SetTitle(xAxisTitle);
00458 hs->GetYaxis()->SetTitle("#Delta(output - truth)");
00459 }
00460
00461 return hs;
00462 }
00463
00464
00465 TProfile* TMLPAnalyzer::DrawTruthDeviationInOut(Int_t innode,
00466 Int_t outnode ,
00467 Option_t *option )
00468 {
00469
00470
00471
00472
00473
00474
00475
00476 if (!fIOTree) GatherInformations();
00477 TString pipehist=Form("MLP_truthdev_i%d_o%d", innode, outnode);
00478 TString drawline;
00479 drawline.Form("Out.Out%d-True.True%d:In.In%d>>",
00480 outnode, outnode, innode);
00481 fIOTree->Draw(drawline+pipehist+"(50)", "", "goff prof");
00482 TProfile* h=(TProfile*)gROOT->FindObject(pipehist);
00483 h->SetDirectory(0);
00484 const char* titleInNeuron=GetInputNeuronTitle(innode);
00485 const char* titleOutNeuron=GetOutputNeuronTitle(outnode);
00486 h->SetTitle(Form("#Delta(output - truth) of %s vs. input %s",
00487 titleOutNeuron, titleInNeuron));
00488 h->GetXaxis()->SetTitle(Form("%s", titleInNeuron));
00489 h->GetYaxis()->SetTitle(Form("#Delta(output - truth) for %s",
00490 titleOutNeuron));
00491 if (!strstr(option,"goff"))
00492 h->Draw(option);
00493 return h;
00494 }
00495
00496
00497 THStack* TMLPAnalyzer::DrawTruthDeviationInsOut(Int_t outnode ,
00498 Option_t *option )
00499 {
00500
00501
00502
00503
00504
00505
00506 TString sName;
00507 sName.Form("MLP_TruthDeviationIO_%d", outnode);
00508 const char* outputNodeTitle=GetOutputNeuronTitle(outnode);
00509 THStack *hs=new THStack(sName,
00510 Form("Deviation of MLP output %s from truth",
00511 outputNodeTitle));
00512
00513
00514 TLegend *leg=0;
00515 if (!option || !strstr(option,"goff"))
00516 leg=new TLegend(.4,.75,.95,.95,
00517 Form("#Delta(output - truth) of %s vs. input for:",
00518 outputNodeTitle));
00519
00520
00521
00522 Int_t numInNodes=GetNeurons(1);
00523 Int_t innode=0;
00524 for (innode=0; innode<numInNodes; innode++) {
00525 TProfile* h=DrawTruthDeviationInOut(innode, outnode, "goff");
00526 h->SetLineColor(1+innode);
00527 hs->Add(h, option);
00528 if (leg) leg->AddEntry(h,h->GetXaxis()->GetTitle());
00529 }
00530
00531 if (leg) {
00532 hs->Draw("nostack");
00533 leg->Draw();
00534
00535 hs->GetXaxis()->SetTitle("Input value");
00536 hs->GetYaxis()->SetTitle(Form("#Delta(output - truth) for %s",
00537 outputNodeTitle));
00538 }
00539
00540 return hs;
00541 }