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
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <vector>
00039 #include <cstdlib>
00040 #include <stdexcept>
00041
00042 #include "TString.h"
00043 #include "TTree.h"
00044 #include "TDirectory.h"
00045 #include "Riostream.h"
00046 #include "TRandom3.h"
00047 #include "TH2F.h"
00048 #include "TH1.h"
00049
00050 #include "TMVA/MethodBase.h"
00051 #include "TMVA/MethodANNBase.h"
00052 #include "TMVA/TNeuron.h"
00053 #include "TMVA/TSynapse.h"
00054 #include "TMVA/TActivationChooser.h"
00055 #include "TMVA/Types.h"
00056 #include "TMVA/Tools.h"
00057 #include "TMVA/TNeuronInputChooser.h"
00058 #include "TMVA/Ranking.h"
00059
00060 using std::vector;
00061
00062 ClassImp(TMVA::MethodANNBase)
00063
00064
00065 TMVA::MethodANNBase::MethodANNBase( const TString& jobName,
00066 Types::EMVA methodType,
00067 const TString& methodTitle,
00068 DataSetInfo& theData,
00069 const TString& theOption,
00070 TDirectory* theTargetDir )
00071 : TMVA::MethodBase( jobName, methodType, methodTitle, theData, theOption, theTargetDir )
00072 , fEstimator(kMSE)
00073 , fUseRegulator(kFALSE)
00074 , fRandomSeed(0)
00075 {
00076
00077
00078
00079
00080 InitANNBase();
00081
00082 DeclareOptions();
00083 }
00084
00085
00086 TMVA::MethodANNBase::MethodANNBase( Types::EMVA methodType,
00087 DataSetInfo& theData,
00088 const TString& theWeightFile,
00089 TDirectory* theTargetDir )
00090 : TMVA::MethodBase( methodType, theData, theWeightFile, theTargetDir )
00091 , fEstimator(kMSE)
00092 , fUseRegulator(kFALSE)
00093 , fRandomSeed(0)
00094 {
00095
00096 InitANNBase();
00097
00098 DeclareOptions();
00099 }
00100
00101
00102 void TMVA::MethodANNBase::DeclareOptions()
00103 {
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 DeclareOptionRef( fNcycles = 500, "NCycles", "Number of training cycles" );
00114 DeclareOptionRef( fLayerSpec = "N,N-1", "HiddenLayers", "Specification of hidden layer architecture" );
00115 DeclareOptionRef( fNeuronType = "sigmoid", "NeuronType", "Neuron activation function type" );
00116 DeclareOptionRef( fRandomSeed = 1, "RandomSeed", "Random seed for initial synapse weights (0 means unique seed for each run; default value '1')");
00117
00118 DeclareOptionRef(fEstimatorS="MSE", "EstimatorType",
00119 "MSE (Mean Square Estimator) for Gaussian Likelihood or CE(Cross-Entropy) for Bernoulli Likelihood" );
00120 AddPreDefVal(TString("MSE"));
00121 AddPreDefVal(TString("CE"));
00122
00123
00124 TActivationChooser aChooser;
00125 vector<TString>* names = aChooser.GetAllActivationNames();
00126 Int_t nTypes = names->size();
00127 for (Int_t i = 0; i < nTypes; i++)
00128 AddPreDefVal(names->at(i));
00129 delete names;
00130
00131 DeclareOptionRef(fNeuronInputType="sum", "NeuronInputType","Neuron input function type");
00132 TNeuronInputChooser iChooser;
00133 names = iChooser.GetAllNeuronInputNames();
00134 nTypes = names->size();
00135 for (Int_t i = 0; i < nTypes; i++) AddPreDefVal(names->at(i));
00136 delete names;
00137 }
00138
00139
00140
00141 void TMVA::MethodANNBase::ProcessOptions()
00142 {
00143
00144 if ( DoRegression() || DoMulticlass()) fEstimatorS = "MSE";
00145 if (fEstimatorS == "MSE" ) fEstimator = kMSE;
00146 else if (fEstimatorS == "CE") fEstimator = kCE;
00147 vector<Int_t>* layout = ParseLayoutString(fLayerSpec);
00148 BuildNetwork(layout);
00149 delete layout;
00150 }
00151
00152
00153 vector<Int_t>* TMVA::MethodANNBase::ParseLayoutString(TString layerSpec)
00154 {
00155
00156
00157 vector<Int_t>* layout = new vector<Int_t>();
00158 layout->push_back((Int_t)GetNvar());
00159 while(layerSpec.Length()>0) {
00160 TString sToAdd="";
00161 if (layerSpec.First(',')<0) {
00162 sToAdd = layerSpec;
00163 layerSpec = "";
00164 }
00165 else {
00166 sToAdd = layerSpec(0,layerSpec.First(','));
00167 layerSpec = layerSpec(layerSpec.First(',')+1,layerSpec.Length());
00168 }
00169 int nNodes = 0;
00170 if (sToAdd.BeginsWith("n") || sToAdd.BeginsWith("N")) { sToAdd.Remove(0,1); nNodes = GetNvar(); }
00171 nNodes += atoi(sToAdd);
00172 layout->push_back(nNodes);
00173 }
00174 if( DoRegression() )
00175 layout->push_back( DataInfo().GetNTargets() );
00176 else if( DoMulticlass() )
00177 layout->push_back( DataInfo().GetNClasses() );
00178 else
00179 layout->push_back(1);
00180
00181 int n = 0;
00182 for( std::vector<Int_t>::iterator it = layout->begin(); it != layout->end(); it++ ){
00183 n++;
00184 }
00185
00186 return layout;
00187 }
00188
00189
00190 void TMVA::MethodANNBase::InitANNBase()
00191 {
00192
00193 fNetwork = NULL;
00194 frgen = NULL;
00195 fActivation = NULL;
00196 fOutput = NULL;
00197 fIdentity = NULL;
00198 fInputCalculator = NULL;
00199 fSynapses = NULL;
00200 fEstimatorHistTrain = NULL;
00201 fEstimatorHistTest = NULL;
00202
00203
00204 fEpochMonHistS.clear();
00205 fEpochMonHistB.clear();
00206 fEpochMonHistW.clear();
00207
00208
00209 fInputLayer = NULL;
00210 fOutputNeurons.clear();
00211
00212 frgen = new TRandom3(fRandomSeed);
00213
00214 fSynapses = new TObjArray();
00215 }
00216
00217
00218 TMVA::MethodANNBase::~MethodANNBase()
00219 {
00220
00221 DeleteNetwork();
00222 }
00223
00224
00225 void TMVA::MethodANNBase::DeleteNetwork()
00226 {
00227
00228 if (fNetwork != NULL) {
00229 TObjArray *layer;
00230 Int_t numLayers = fNetwork->GetEntriesFast();
00231 for (Int_t i = 0; i < numLayers; i++) {
00232 layer = (TObjArray*)fNetwork->At(i);
00233 DeleteNetworkLayer(layer);
00234 }
00235 delete fNetwork;
00236 }
00237
00238 if (frgen != NULL) delete frgen;
00239 if (fActivation != NULL) delete fActivation;
00240 if (fOutput != NULL) delete fOutput;
00241 if (fIdentity != NULL) delete fIdentity;
00242 if (fInputCalculator != NULL) delete fInputCalculator;
00243 if (fSynapses != NULL) delete fSynapses;
00244
00245 fNetwork = NULL;
00246 frgen = NULL;
00247 fActivation = NULL;
00248 fOutput = NULL;
00249 fIdentity = NULL;
00250 fInputCalculator = NULL;
00251 fSynapses = NULL;
00252 }
00253
00254
00255 void TMVA::MethodANNBase::DeleteNetworkLayer( TObjArray*& layer )
00256 {
00257
00258 TNeuron* neuron;
00259 Int_t numNeurons = layer->GetEntriesFast();
00260 for (Int_t i = 0; i < numNeurons; i++) {
00261 neuron = (TNeuron*)layer->At(i);
00262 neuron->DeletePreLinks();
00263 delete neuron;
00264 }
00265 delete layer;
00266 }
00267
00268
00269 void TMVA::MethodANNBase::BuildNetwork( vector<Int_t>* layout, vector<Double_t>* weights, Bool_t fromFile )
00270 {
00271
00272
00273
00274 if (fEstimator!=kMSE && fEstimator!=kCE) {
00275 if (fEstimatorS == "MSE") fEstimator = kMSE;
00276 else if (fEstimatorS == "CE") fEstimator = kCE;
00277 }
00278 if (fEstimator!=kMSE && fEstimator!=kCE) Log()<<kWARNING<<"Estimator type unspecified \t"<<Endl;
00279
00280
00281
00282 Log() << kINFO << "Building Network" << Endl;
00283
00284 DeleteNetwork();
00285 InitANNBase();
00286
00287
00288 TActivationChooser aChooser;
00289 fActivation = aChooser.CreateActivation(fNeuronType);
00290 fIdentity = aChooser.CreateActivation("linear");
00291 if (fEstimator==kMSE) fOutput = aChooser.CreateActivation("linear");
00292 else if (fEstimator==kCE) fOutput = aChooser.CreateActivation("sigmoid");
00293 TNeuronInputChooser iChooser;
00294 fInputCalculator = iChooser.CreateNeuronInput(fNeuronInputType);
00295
00296 fNetwork = new TObjArray();
00297 fRegulatorIdx.clear();
00298 fRegulators.clear();
00299 BuildLayers( layout, fromFile );
00300
00301
00302 fInputLayer = (TObjArray*)fNetwork->At(0);
00303 TObjArray* outputLayer = (TObjArray*)fNetwork->At(fNetwork->GetEntriesFast()-1);
00304 fOutputNeurons.clear();
00305 for (Int_t i = 0; i < outputLayer->GetEntries(); i++) {
00306 fOutputNeurons.push_back( (TNeuron*)outputLayer->At(i) );
00307 }
00308
00309 if (weights == NULL) InitWeights();
00310 else ForceWeights(weights);
00311 }
00312
00313
00314 void TMVA::MethodANNBase::BuildLayers( vector<Int_t>* layout, Bool_t fromFile )
00315 {
00316
00317
00318 TObjArray* curLayer;
00319 TObjArray* prevLayer = NULL;
00320
00321 Int_t numLayers = layout->size();
00322
00323 for (Int_t i = 0; i < numLayers; i++) {
00324 curLayer = new TObjArray();
00325 BuildLayer(layout->at(i), curLayer, prevLayer, i, numLayers, fromFile);
00326 prevLayer = curLayer;
00327 fNetwork->Add(curLayer);
00328 }
00329
00330
00331 for (Int_t i = 0; i < numLayers; i++) {
00332 TObjArray* layer = (TObjArray*)fNetwork->At(i);
00333 Int_t numNeurons = layer->GetEntriesFast();
00334 if (i!=0 && i!=numLayers-1) fRegulators.push_back(0.);
00335 for (Int_t j = 0; j < numNeurons; j++) {
00336 if (i==0) fRegulators.push_back(0.);
00337 TNeuron* neuron = (TNeuron*)layer->At(j);
00338 Int_t numSynapses = neuron->NumPostLinks();
00339 for (Int_t k = 0; k < numSynapses; k++) {
00340 TSynapse* synapse = neuron->PostLinkAt(k);
00341 fSynapses->Add(synapse);
00342 fRegulatorIdx.push_back(fRegulators.size()-1);
00343 }
00344 }
00345 }
00346 }
00347
00348
00349 void TMVA::MethodANNBase::BuildLayer( Int_t numNeurons, TObjArray* curLayer,
00350 TObjArray* prevLayer, Int_t layerIndex,
00351 Int_t numLayers, Bool_t fromFile )
00352 {
00353
00354
00355
00356 TNeuron* neuron;
00357 for (Int_t j = 0; j < numNeurons; j++) {
00358 if (fromFile && (layerIndex != numLayers-1) && (j==numNeurons-1)){
00359 neuron = new TNeuron();
00360 neuron->SetActivationEqn(fIdentity);
00361 neuron->SetBiasNeuron();
00362 neuron->ForceValue(1.0);
00363 curLayer->Add(neuron);
00364 }
00365 else {
00366 neuron = new TNeuron();
00367 neuron->SetInputCalculator(fInputCalculator);
00368
00369
00370 if (layerIndex == 0) {
00371 neuron->SetActivationEqn(fIdentity);
00372 neuron->SetInputNeuron();
00373 }
00374 else {
00375
00376 if (layerIndex == numLayers-1) {
00377 neuron->SetOutputNeuron();
00378 neuron->SetActivationEqn(fOutput);
00379 }
00380
00381 else neuron->SetActivationEqn(fActivation);
00382 AddPreLinks(neuron, prevLayer);
00383 }
00384
00385 curLayer->Add(neuron);
00386 }
00387 }
00388
00389
00390 if(!fromFile){
00391 if (layerIndex != numLayers-1) {
00392 neuron = new TNeuron();
00393 neuron->SetActivationEqn(fIdentity);
00394 neuron->SetBiasNeuron();
00395 neuron->ForceValue(1.0);
00396 curLayer->Add(neuron);
00397 }
00398 }
00399 }
00400
00401
00402 void TMVA::MethodANNBase::AddPreLinks(TNeuron* neuron, TObjArray* prevLayer)
00403 {
00404
00405
00406 TSynapse* synapse;
00407 int numNeurons = prevLayer->GetEntriesFast();
00408 TNeuron* preNeuron;
00409
00410 for (Int_t i = 0; i < numNeurons; i++) {
00411 preNeuron = (TNeuron*)prevLayer->At(i);
00412 synapse = new TSynapse();
00413 synapse->SetPreNeuron(preNeuron);
00414 synapse->SetPostNeuron(neuron);
00415 preNeuron->AddPostLink(synapse);
00416 neuron->AddPreLink(synapse);
00417 }
00418 }
00419
00420
00421 void TMVA::MethodANNBase::InitWeights()
00422 {
00423
00424 PrintMessage("Initializing weights");
00425
00426
00427 Int_t numSynapses = fSynapses->GetEntriesFast();
00428 TSynapse* synapse;
00429 for (Int_t i = 0; i < numSynapses; i++) {
00430 synapse = (TSynapse*)fSynapses->At(i);
00431 synapse->SetWeight(4.0*frgen->Rndm() - 2.0);
00432 }
00433 }
00434
00435
00436 void TMVA::MethodANNBase::ForceWeights(vector<Double_t>* weights)
00437 {
00438
00439 PrintMessage("Forcing weights");
00440
00441 Int_t numSynapses = fSynapses->GetEntriesFast();
00442 TSynapse* synapse;
00443 for (Int_t i = 0; i < numSynapses; i++) {
00444 synapse = (TSynapse*)fSynapses->At(i);
00445 synapse->SetWeight(weights->at(i));
00446 }
00447 }
00448
00449
00450 void TMVA::MethodANNBase::ForceNetworkInputs( const Event* ev, Int_t ignoreIndex)
00451 {
00452
00453
00454
00455 Double_t x;
00456 TNeuron* neuron;
00457
00458
00459 for (UInt_t j = 0; j < GetNvar(); j++) {
00460
00461 x = (j != (UInt_t)ignoreIndex)?ev->GetValue(j):0;
00462
00463 neuron = GetInputNeuron(j);
00464 neuron->ForceValue(x);
00465 }
00466 }
00467
00468
00469 void TMVA::MethodANNBase::ForceNetworkCalculations()
00470 {
00471
00472
00473 TObjArray* curLayer;
00474 TNeuron* neuron;
00475 Int_t numLayers = fNetwork->GetEntriesFast();
00476 Int_t numNeurons;
00477
00478 for (Int_t i = 0; i < numLayers; i++) {
00479 curLayer = (TObjArray*)fNetwork->At(i);
00480 numNeurons = curLayer->GetEntriesFast();
00481
00482 for (Int_t j = 0; j < numNeurons; j++) {
00483 neuron = (TNeuron*) curLayer->At(j);
00484 neuron->CalculateValue();
00485 neuron->CalculateActivationValue();
00486
00487 }
00488 }
00489 }
00490
00491
00492 void TMVA::MethodANNBase::PrintMessage(TString message, Bool_t force) const
00493 {
00494
00495 if (Verbose() || Debug() || force) Log() << kINFO << message << Endl;
00496 }
00497
00498
00499 void TMVA::MethodANNBase::WaitForKeyboard()
00500 {
00501
00502 string dummy;
00503 Log() << kINFO << "***Type anything to continue (q to quit): ";
00504 getline(cin, dummy);
00505 if (dummy == "q" || dummy == "Q") {
00506 PrintMessage( "quit" );
00507 delete this;
00508 exit(0);
00509 }
00510 }
00511
00512
00513 void TMVA::MethodANNBase::PrintNetwork() const
00514 {
00515
00516 if (!Debug()) return;
00517
00518 Log() << kINFO << Endl;
00519 PrintMessage( "Printing network " );
00520 Log() << kINFO << "-------------------------------------------------------------------" << Endl;
00521
00522 TObjArray* curLayer;
00523 Int_t numLayers = fNetwork->GetEntriesFast();
00524
00525 for (Int_t i = 0; i < numLayers; i++) {
00526
00527 curLayer = (TObjArray*)fNetwork->At(i);
00528 Int_t numNeurons = curLayer->GetEntriesFast();
00529
00530 Log() << kINFO << "Layer #" << i << " (" << numNeurons << " neurons):" << Endl;
00531 PrintLayer( curLayer );
00532 }
00533 }
00534
00535
00536 void TMVA::MethodANNBase::PrintLayer(TObjArray* layer) const
00537 {
00538
00539
00540 Int_t numNeurons = layer->GetEntriesFast();
00541 TNeuron* neuron;
00542
00543 for (Int_t j = 0; j < numNeurons; j++) {
00544 neuron = (TNeuron*) layer->At(j);
00545 Log() << kINFO << "\tNeuron #" << j << " (LinksIn: " << neuron->NumPreLinks()
00546 << " , LinksOut: " << neuron->NumPostLinks() << ")" << Endl;
00547 PrintNeuron( neuron );
00548 }
00549 }
00550
00551
00552 void TMVA::MethodANNBase::PrintNeuron(TNeuron* neuron) const
00553 {
00554
00555 Log() << kINFO
00556 << "\t\tValue:\t" << neuron->GetValue()
00557 << "\t\tActivation: " << neuron->GetActivationValue()
00558 << "\t\tDelta: " << neuron->GetDelta() << Endl;
00559 Log() << kINFO << "\t\tActivationEquation:\t";
00560 neuron->PrintActivationEqn();
00561 Log() << kINFO << "\t\tLinksIn:" << Endl;
00562 neuron->PrintPreLinks();
00563 Log() << kINFO << "\t\tLinksOut:" << Endl;
00564 neuron->PrintPostLinks();
00565 }
00566
00567
00568 Double_t TMVA::MethodANNBase::GetMvaValue( Double_t* err, Double_t* errUpper )
00569 {
00570
00571 TNeuron* neuron;
00572
00573 TObjArray* inputLayer = (TObjArray*)fNetwork->At(0);
00574
00575 const Event * ev = GetEvent();
00576
00577 for (UInt_t i = 0; i < GetNvar(); i++) {
00578 neuron = (TNeuron*)inputLayer->At(i);
00579 neuron->ForceValue( ev->GetValue(i) );
00580 }
00581 ForceNetworkCalculations();
00582
00583
00584 TObjArray* outputLayer = (TObjArray*)fNetwork->At( fNetwork->GetEntriesFast()-1 );
00585 neuron = (TNeuron*)outputLayer->At(0);
00586
00587
00588 NoErrorCalc(err, errUpper);
00589
00590 return neuron->GetActivationValue();
00591 }
00592
00593
00594 const std::vector<Float_t> &TMVA::MethodANNBase::GetRegressionValues()
00595 {
00596
00597 TNeuron* neuron;
00598
00599 TObjArray* inputLayer = (TObjArray*)fNetwork->At(0);
00600
00601 const Event * ev = GetEvent();
00602
00603 for (UInt_t i = 0; i < GetNvar(); i++) {
00604 neuron = (TNeuron*)inputLayer->At(i);
00605 neuron->ForceValue( ev->GetValue(i) );
00606 }
00607 ForceNetworkCalculations();
00608
00609
00610 TObjArray* outputLayer = (TObjArray*)fNetwork->At( fNetwork->GetEntriesFast()-1 );
00611
00612 if (fRegressionReturnVal == NULL) fRegressionReturnVal = new std::vector<Float_t>();
00613 fRegressionReturnVal->clear();
00614
00615 Event * evT = new Event(*ev);
00616 UInt_t ntgts = outputLayer->GetEntriesFast();
00617 for (UInt_t itgt = 0; itgt < ntgts; itgt++) {
00618 evT->SetTarget(itgt,((TNeuron*)outputLayer->At(itgt))->GetActivationValue());
00619 }
00620
00621 const Event* evT2 = GetTransformationHandler().InverseTransform( evT );
00622 for (UInt_t itgt = 0; itgt < ntgts; itgt++) {
00623 fRegressionReturnVal->push_back( evT2->GetTarget(itgt) );
00624 }
00625
00626 delete evT;
00627
00628 return *fRegressionReturnVal;
00629 }
00630
00631
00632 const std::vector<Float_t> &TMVA::MethodANNBase::GetMulticlassValues()
00633 {
00634
00635 TNeuron* neuron;
00636
00637 TObjArray* inputLayer = (TObjArray*)fNetwork->At(0);
00638
00639 const Event * ev = GetEvent();
00640
00641 for (UInt_t i = 0; i < GetNvar(); i++) {
00642 neuron = (TNeuron*)inputLayer->At(i);
00643 neuron->ForceValue( ev->GetValue(i) );
00644 }
00645 ForceNetworkCalculations();
00646
00647
00648
00649 if (fMulticlassReturnVal == NULL) fMulticlassReturnVal = new std::vector<Float_t>();
00650 fMulticlassReturnVal->clear();
00651 std::vector<Float_t> temp;
00652
00653 UInt_t nClasses = DataInfo().GetNClasses();
00654 for (UInt_t icls = 0; icls < nClasses; icls++) {
00655 temp.push_back(GetOutputNeuron( icls )->GetActivationValue() );
00656 }
00657
00658 for(UInt_t iClass=0; iClass<nClasses; iClass++){
00659 Double_t norm = 0.0;
00660 for(UInt_t j=0;j<nClasses;j++){
00661 if(iClass!=j)
00662 norm+=exp(temp[j]-temp[iClass]);
00663 }
00664 (*fMulticlassReturnVal).push_back(1.0/(1.0+norm));
00665 }
00666
00667 return *fMulticlassReturnVal;
00668 }
00669
00670
00671
00672 void TMVA::MethodANNBase::AddWeightsXMLTo( void* parent ) const
00673 {
00674
00675 Int_t numLayers = fNetwork->GetEntriesFast();
00676 void* wght = gTools().xmlengine().NewChild(parent, 0, "Weights");
00677 void* xmlLayout = gTools().xmlengine().NewChild(wght, 0, "Layout");
00678 gTools().xmlengine().NewAttr(xmlLayout, 0, "NLayers", gTools().StringFromInt(fNetwork->GetEntriesFast()) );
00679 TString weights = "";
00680 for (Int_t i = 0; i < numLayers; i++) {
00681 TObjArray* layer = (TObjArray*)fNetwork->At(i);
00682 Int_t numNeurons = layer->GetEntriesFast();
00683 void* layerxml = gTools().xmlengine().NewChild(xmlLayout, 0, "Layer");
00684 gTools().xmlengine().NewAttr(layerxml, 0, "Index", gTools().StringFromInt(i) );
00685 gTools().xmlengine().NewAttr(layerxml, 0, "NNeurons", gTools().StringFromInt(numNeurons) );
00686 for (Int_t j = 0; j < numNeurons; j++) {
00687 TNeuron* neuron = (TNeuron*)layer->At(j);
00688 Int_t numSynapses = neuron->NumPostLinks();
00689 void* neuronxml = gTools().AddChild(layerxml, "Neuron");
00690 gTools().AddAttr(neuronxml, "NSynapses", gTools().StringFromInt(numSynapses) );
00691 if(numSynapses==0) continue;
00692 stringstream s("");
00693 s.precision( 16 );
00694 for (Int_t k = 0; k < numSynapses; k++) {
00695 TSynapse* synapse = neuron->PostLinkAt(k);
00696 s << std::scientific << synapse->GetWeight() << " ";
00697 }
00698 gTools().AddRawLine( neuronxml, s.str().c_str() );
00699 }
00700 }
00701
00702
00703 if( fInvHessian.GetNcols()>0 ){
00704 void* xmlInvHessian = gTools().xmlengine().NewChild(wght, 0, "InverseHessian");
00705
00706
00707 Int_t nElements = fInvHessian.GetNoElements();
00708 Int_t nRows = fInvHessian.GetNrows();
00709 Int_t nCols = fInvHessian.GetNcols();
00710 gTools().xmlengine().NewAttr(xmlInvHessian, 0, "NElements", gTools().StringFromInt(nElements) );
00711 gTools().xmlengine().NewAttr(xmlInvHessian, 0, "NRows", gTools().StringFromInt(nRows) );
00712 gTools().xmlengine().NewAttr(xmlInvHessian, 0, "NCols", gTools().StringFromInt(nCols) );
00713
00714
00715 Double_t* elements = new Double_t[nElements+10];
00716 fInvHessian.GetMatrix2Array( elements );
00717
00718
00719 Int_t index = 0;
00720 for( Int_t row = 0; row < nRows; ++row ){
00721 void* xmlRow = gTools().xmlengine().NewChild(xmlInvHessian, 0, "Row");
00722 gTools().xmlengine().NewAttr(xmlRow, 0, "Index", gTools().StringFromInt(row) );
00723
00724
00725 stringstream s("");
00726 s.precision( 16 );
00727 for( Int_t col = 0; col < nCols; ++col ){
00728 s << std::scientific << (*(elements+index)) << " ";
00729 ++index;
00730 }
00731 gTools().xmlengine().AddRawLine( xmlRow, s.str().c_str() );
00732 }
00733 delete[] elements;
00734 }
00735 }
00736
00737
00738
00739 void TMVA::MethodANNBase::ReadWeightsFromXML( void* wghtnode )
00740 {
00741
00742
00743
00744 Bool_t fromFile = kTRUE;
00745 vector<Int_t>* layout = new vector<Int_t>();
00746
00747 void* xmlLayout = NULL;
00748 xmlLayout = gTools().GetChild(wghtnode, "Layout");
00749 if( !xmlLayout )
00750 xmlLayout = wghtnode;
00751
00752 UInt_t nLayers;
00753 gTools().ReadAttr( xmlLayout, "NLayers", nLayers );
00754 layout->resize( nLayers );
00755
00756 void* ch = gTools().xmlengine().GetChild(xmlLayout);
00757 UInt_t index;
00758 UInt_t nNeurons;
00759 while (ch) {
00760 gTools().ReadAttr( ch, "Index", index );
00761 gTools().ReadAttr( ch, "NNeurons", nNeurons );
00762 layout->at(index) = nNeurons;
00763 ch = gTools().GetNextChild(ch);
00764 }
00765
00766 BuildNetwork( layout, NULL, fromFile );
00767
00768 UInt_t nSyn;
00769 Float_t weight;
00770 ch = gTools().xmlengine().GetChild(xmlLayout);
00771 UInt_t iLayer = 0;
00772 while (ch) {
00773 TObjArray* layer = (TObjArray*)fNetwork->At(iLayer);
00774 gTools().ReadAttr( ch, "Index", index );
00775 gTools().ReadAttr( ch, "NNeurons", nNeurons );
00776
00777 void* nodeN = gTools().GetChild(ch);
00778 UInt_t iNeuron = 0;
00779 while( nodeN ){
00780 TNeuron *neuron = (TNeuron*)layer->At(iNeuron);
00781 gTools().ReadAttr( nodeN, "NSynapses", nSyn );
00782 if( nSyn > 0 ){
00783 const char* content = gTools().GetContent(nodeN);
00784 std::stringstream s(content);
00785 for (UInt_t iSyn = 0; iSyn<nSyn; iSyn++) {
00786
00787 TSynapse* synapse = neuron->PostLinkAt(iSyn);
00788 s >> weight;
00789
00790 synapse->SetWeight(weight);
00791 }
00792 }
00793 nodeN = gTools().GetNextChild(nodeN);
00794 iNeuron++;
00795 }
00796 ch = gTools().GetNextChild(ch);
00797 iLayer++;
00798 }
00799
00800 delete layout;
00801
00802 void* xmlInvHessian = NULL;
00803 xmlInvHessian = gTools().GetChild(wghtnode, "InverseHessian");
00804 if( !xmlInvHessian )
00805
00806 return;
00807
00808 fUseRegulator = kTRUE;
00809
00810 Int_t nElements = 0;
00811 Int_t nRows = 0;
00812 Int_t nCols = 0;
00813 gTools().ReadAttr( xmlInvHessian, "NElements", nElements );
00814 gTools().ReadAttr( xmlInvHessian, "NRows", nRows );
00815 gTools().ReadAttr( xmlInvHessian, "NCols", nCols );
00816
00817
00818 fInvHessian.ResizeTo( nRows, nCols );
00819
00820
00821 Double_t* elements = new Double_t[nElements+10];
00822
00823
00824
00825 void* xmlRow = gTools().xmlengine().GetChild(xmlInvHessian);
00826 Int_t row = 0;
00827 index = 0;
00828 while (xmlRow) {
00829 gTools().ReadAttr( xmlRow, "Index", row );
00830
00831 const char* content = gTools().xmlengine().GetNodeContent(xmlRow);
00832
00833 std::stringstream s(content);
00834 for (Int_t iCol = 0; iCol<nCols; iCol++) {
00835 s >> (*(elements+index));
00836 ++index;
00837 }
00838 xmlRow = gTools().xmlengine().GetNext(xmlRow);
00839 ++row;
00840 }
00841
00842 fInvHessian.SetMatrixArray( elements );
00843
00844 delete[] elements;
00845 }
00846
00847
00848
00849 void TMVA::MethodANNBase::ReadWeightsFromStream( istream & istr)
00850 {
00851
00852
00853
00854
00855 TString dummy;
00856
00857
00858 Double_t weight;
00859 vector<Double_t>* weights = new vector<Double_t>();
00860 istr>> dummy;
00861 while (istr>> dummy >> weight) weights->push_back(weight);
00862
00863 ForceWeights(weights);
00864
00865
00866 delete weights;
00867 }
00868
00869
00870 const TMVA::Ranking* TMVA::MethodANNBase::CreateRanking()
00871 {
00872
00873
00874
00875 fRanking = new Ranking( GetName(), "Importance" );
00876
00877 TNeuron* neuron;
00878 TSynapse* synapse;
00879 Double_t importance, avgVal;
00880 TString varName;
00881
00882 for (UInt_t ivar = 0; ivar < GetNvar(); ivar++) {
00883
00884 neuron = GetInputNeuron(ivar);
00885 Int_t numSynapses = neuron->NumPostLinks();
00886 importance = 0;
00887 varName = GetInputVar(ivar);
00888
00889
00890 Double_t meanS, meanB, rmsS, rmsB, xmin, xmax;
00891 Statistics( TMVA::Types::kTraining, varName,
00892 meanS, meanB, rmsS, rmsB, xmin, xmax );
00893
00894 avgVal = (meanS + meanB) / 2.0;
00895 if (IsNormalised()) avgVal = 0.5*(1 + gTools().NormVariable( avgVal, GetXmin( ivar ), GetXmax( ivar )));
00896
00897 for (Int_t j = 0; j < numSynapses; j++) {
00898 synapse = neuron->PostLinkAt(j);
00899 importance += synapse->GetWeight() * synapse->GetWeight();
00900 }
00901
00902 importance *= avgVal * avgVal;
00903
00904 fRanking->AddRank( Rank( varName, importance ) );
00905 }
00906
00907 return fRanking;
00908 }
00909
00910
00911 void TMVA::MethodANNBase::CreateWeightMonitoringHists( const TString& bulkname,
00912 std::vector<TH1*>* hv ) const
00913 {
00914 TH2F* hist;
00915 Int_t numLayers = fNetwork->GetEntriesFast();
00916
00917 for (Int_t i = 0; i < numLayers-1; i++) {
00918
00919 TObjArray* layer1 = (TObjArray*)fNetwork->At(i);
00920 TObjArray* layer2 = (TObjArray*)fNetwork->At(i+1);
00921 Int_t numNeurons1 = layer1->GetEntriesFast();
00922 Int_t numNeurons2 = layer2->GetEntriesFast();
00923
00924 TString name = Form("%s%i%i", bulkname.Data(), i, i+1);
00925 hist = new TH2F(name + "", name + "",
00926 numNeurons1, 0, numNeurons1, numNeurons2, 0, numNeurons2);
00927
00928 for (Int_t j = 0; j < numNeurons1; j++) {
00929
00930 TNeuron* neuron = (TNeuron*)layer1->At(j);
00931 Int_t numSynapses = neuron->NumPostLinks();
00932
00933 for (Int_t k = 0; k < numSynapses; k++) {
00934
00935 TSynapse* synapse = neuron->PostLinkAt(k);
00936 hist->SetBinContent(j+1, k+1, synapse->GetWeight());
00937
00938 }
00939 }
00940
00941 if (hv) hv->push_back( hist );
00942 else {
00943 hist->Write();
00944 delete hist;
00945 }
00946 }
00947 }
00948
00949
00950 void TMVA::MethodANNBase::WriteMonitoringHistosToFile() const
00951 {
00952
00953 PrintMessage(Form("Write special histos to file: %s", BaseDir()->GetPath()), kTRUE);
00954
00955 if (fEstimatorHistTrain) fEstimatorHistTrain->Write();
00956 if (fEstimatorHistTest ) fEstimatorHistTest ->Write();
00957
00958
00959 CreateWeightMonitoringHists( "weights_hist" );
00960
00961
00962 static int epochMonitoringDirectoryNumber = 0;
00963 TDirectory* epochdir = NULL;
00964 if( epochMonitoringDirectoryNumber == 0 )
00965 epochdir = BaseDir()->mkdir( "EpochMonitoring" );
00966 else
00967 epochdir = BaseDir()->mkdir( Form("EpochMonitoring_%4d",epochMonitoringDirectoryNumber) );
00968 ++epochMonitoringDirectoryNumber;
00969
00970 epochdir->cd();
00971 for (std::vector<TH1*>::const_iterator it = fEpochMonHistS.begin(); it != fEpochMonHistS.end(); it++) {
00972 (*it)->Write();
00973 delete (*it);
00974 }
00975 for (std::vector<TH1*>::const_iterator it = fEpochMonHistB.begin(); it != fEpochMonHistB.end(); it++) {
00976 (*it)->Write();
00977 delete (*it);
00978 }
00979 for (std::vector<TH1*>::const_iterator it = fEpochMonHistW.begin(); it != fEpochMonHistW.end(); it++) {
00980 (*it)->Write();
00981 delete (*it);
00982 }
00983 BaseDir()->cd();
00984 }
00985
00986
00987 void TMVA::MethodANNBase::MakeClassSpecific( std::ostream& fout, const TString& className ) const
00988 {
00989
00990 Int_t numLayers = fNetwork->GetEntries();
00991
00992 fout << endl;
00993 fout << " double ActivationFnc(double x) const;" << endl;
00994 fout << " double OutputActivationFnc(double x) const;" << endl;
00995 fout << endl;
00996 fout << " int fLayers;" << endl;
00997 fout << " int fLayerSize["<<numLayers<<"];" << endl;
00998 int numNodesFrom = -1;
00999 for (Int_t lIdx = 0; lIdx < numLayers; lIdx++) {
01000 int numNodesTo = ((TObjArray*)fNetwork->At(lIdx))->GetEntries();
01001 if (numNodesFrom<0) { numNodesFrom=numNodesTo; continue; }
01002 fout << " double fWeightMatrix" << lIdx-1 << "to" << lIdx << "[" << numNodesTo << "][" << numNodesFrom << "];";
01003 fout << " // weight matrix from layer " << lIdx-1 << " to " << lIdx << endl;
01004 numNodesFrom = numNodesTo;
01005 }
01006 fout << endl;
01007 fout << " double * fWeights["<<numLayers<<"];" << endl;
01008 fout << "};" << endl;
01009
01010 fout << endl;
01011
01012 fout << "inline void " << className << "::Initialize()" << endl;
01013 fout << "{" << endl;
01014 fout << " // build network structure" << endl;
01015 fout << " fLayers = " << numLayers << ";" << endl;
01016 for (Int_t lIdx = 0; lIdx < numLayers; lIdx++) {
01017 TObjArray* layer = (TObjArray*)fNetwork->At(lIdx);
01018 int numNodes = layer->GetEntries();
01019 fout << " fLayerSize[" << lIdx << "] = " << numNodes << "; fWeights["<<lIdx<<"] = new double["<<numNodes<<"]; " << endl;
01020 }
01021
01022 for (Int_t i = 0; i < numLayers-1; i++) {
01023 fout << " // weight matrix from layer " << i << " to " << i+1 << endl;
01024 TObjArray* layer = (TObjArray*)fNetwork->At(i);
01025 Int_t numNeurons = layer->GetEntriesFast();
01026 for (Int_t j = 0; j < numNeurons; j++) {
01027 TNeuron* neuron = (TNeuron*)layer->At(j);
01028 Int_t numSynapses = neuron->NumPostLinks();
01029 for (Int_t k = 0; k < numSynapses; k++) {
01030 TSynapse* synapse = neuron->PostLinkAt(k);
01031 fout << " fWeightMatrix" << i << "to" << i+1 << "[" << k << "][" << j << "] = " << synapse->GetWeight() << ";" << endl;
01032 }
01033 }
01034 }
01035
01036 fout << "}" << endl;
01037 fout << endl;
01038
01039
01040 fout << "inline double " << className << "::GetMvaValue__( const std::vector<double>& inputValues ) const" << endl;
01041 fout << "{" << endl;
01042 fout << " if (inputValues.size() != (unsigned int)fLayerSize[0]-1) {" << endl;
01043 fout << " std::cout << \"Input vector needs to be of size \" << fLayerSize[0]-1 << std::endl;" << endl;
01044 fout << " return 0;" << endl;
01045 fout << " }" << endl;
01046 fout << endl;
01047 fout << " for (int l=0; l<fLayers; l++)" << endl;
01048 fout << " for (int i=0; i<fLayerSize[l]; i++) fWeights[l][i]=0;" << endl;
01049 fout << endl;
01050 fout << " for (int l=0; l<fLayers-1; l++)" << endl;
01051 fout << " fWeights[l][fLayerSize[l]-1]=1;" << endl;
01052 fout << endl;
01053 fout << " for (int i=0; i<fLayerSize[0]-1; i++)" << endl;
01054 fout << " fWeights[0][i]=inputValues[i];" << endl;
01055 fout << endl;
01056 for (Int_t i = 0; i < numLayers-1; i++) {
01057 fout << " // layer " << i << " to " << i+1 << endl;
01058 if (i+1 == numLayers-1) {
01059 fout << " for (int o=0; o<fLayerSize[" << i+1 << "]; o++) {" << endl;
01060 }
01061 else {
01062 fout << " for (int o=0; o<fLayerSize[" << i+1 << "]-1; o++) {" << endl;
01063 }
01064 fout << " for (int i=0; i<fLayerSize[" << i << "]; i++) {" << endl;
01065 fout << " double inputVal = fWeightMatrix" << i << "to" << i+1 << "[o][i] * fWeights[" << i << "][i];" << endl;
01066
01067 if ( fNeuronInputType == "sum") {
01068 fout << " fWeights[" << i+1 << "][o] += inputVal;" << endl;
01069 }
01070 else if ( fNeuronInputType == "sqsum") {
01071 fout << " fWeights[" << i+1 << "][o] += inputVal*inputVal;" << endl;
01072 }
01073 else {
01074 fout << " fWeights[" << i+1 << "][o] += fabs(inputVal);" << endl;
01075 }
01076 fout << " }" << endl;
01077 if (i+1 != numLayers-1)
01078 fout << " fWeights[" << i+1 << "][o] = ActivationFnc(fWeights[" << i+1 << "][o]);" << endl;
01079 else fout << " fWeights[" << i+1 << "][o] = OutputActivationFnc(fWeights[" << i+1 << "][o]);" << endl;
01080 fout << " }" << endl;
01081 }
01082 fout << endl;
01083 fout << " return fWeights[" << numLayers-1 << "][0];" << endl;
01084 fout << "}" << endl;
01085
01086 fout << endl;
01087 TString fncName = className+"::ActivationFnc";
01088 fActivation->MakeFunction(fout, fncName);
01089 fncName = className+"::OutputActivationFnc";
01090 fOutput->MakeFunction(fout, fncName);
01091
01092 fout << " " << endl;
01093 fout << "// Clean up" << endl;
01094 fout << "inline void " << className << "::Clear() " << endl;
01095 fout << "{" << endl;
01096 fout << " // nothing to clear" << endl;
01097 fout << "}" << endl;
01098 }
01099
01100
01101 Bool_t TMVA::MethodANNBase::Debug() const
01102 {
01103
01104 return fgDEBUG;
01105 }