MethodANNBase.cxx

Go to the documentation of this file.
00001 // @(#)root/tmva $Id: MethodANNBase.cxx 37399 2010-12-08 15:22:07Z evt $
00002 // Author: Andreas Hoecker, Peter Speckmayer, Matt Jachowski
00003 
00004 /**********************************************************************************
00005  * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
00006  * Package: TMVA                                                                  *
00007  * Class  : MethodANNBase                                                         *
00008  * Web    : http://tmva.sourceforge.net                                           *
00009  *                                                                                *
00010  * Description:                                                                   *
00011  *      Artificial neural network base class for the discrimination of signal     *
00012  *      from background.                                                          *
00013  *                                                                                *
00014  * Authors (alphabetical):                                                        *
00015  *      Krzysztof Danielowski <danielow@cern.ch>       - IFJ & AGH, Poland        *
00016  *      Andreas Hoecker       <Andreas.Hocker@cern.ch> - CERN, Switzerland        *
00017  *      Matt Jachowski        <jachowski@stanford.edu> - Stanford University, USA *
00018  *      Kamil Kraszewski      <kalq@cern.ch>           - IFJ & UJ, Poland         *
00019  *      Maciej Kruk           <mkruk@cern.ch>          - IFJ & AGH, Poland        *
00020  *      Peter Speckmayer      <peter.speckmayer@cern.ch> - CERN, Switzerland      *
00021  *      Joerg Stelzer         <stelzer@cern.ch>        - DESY, Germany            *
00022  *      Jiahang Zhong         <Jiahang.Zhong@cern.ch>  - Academia Sinica, Taipei  *
00023  *                                                                                *
00024  * Copyright (c) 2005:                                                            *
00025  *      CERN, Switzerland                                                         *
00026  *                                                                                *
00027  * Redistribution and use in source and binary forms, with or without             *
00028  * modification, are permitted according to the terms listed in LICENSE           *
00029  * (http://tmva.sourceforge.net/LICENSE)                                          *
00030  **********************************************************************************/
00031 
00032 //_______________________________________________________________________
00033 //
00034 // Base class for all TMVA methods using artificial neural networks
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    // standard constructor
00077    // Note: Right now it is an option to choose the neuron input function,
00078    // but only the input function "sum" leads to weight convergence --
00079    // otherwise the weights go to nan and lead to an ABORT.
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    // construct the Method from the weight file
00096    InitANNBase();
00097 
00098    DeclareOptions();
00099 }
00100 
00101 //______________________________________________________________________________
00102 void TMVA::MethodANNBase::DeclareOptions()
00103 {
00104    // define the options (their key words) that can be set in the option string
00105    // here the options valid for ALL MVA methods are declared.
00106    // know options: NCycles=xx              :the number of training cycles
00107    //               Normalize=kTRUE,kFALSe  :if normalised in put variables should be used
00108    //               HiddenLayser="N-1,N-2"  :the specification of the hidden layers
00109    //               NeuronType=sigmoid,tanh,radial,linar  : the type of activation function
00110    //                                                       used at the neuronn
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" ); //zjh
00120    AddPreDefVal(TString("MSE"));  //zjh
00121    AddPreDefVal(TString("CE"));   //zjh
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    // do nothing specific at this moment
00144    if      ( DoRegression() || DoMulticlass())  fEstimatorS = "MSE";    //zjh
00145    if      (fEstimatorS == "MSE" )  fEstimator = kMSE;   
00146    else if (fEstimatorS == "CE")    fEstimator = kCE;      //zjh
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    // parse layout specification string and return a vector, each entry
00156    // containing the number of neurons to go in each successive layer
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() );  // one output node for each target
00176    else if( DoMulticlass() )
00177       layout->push_back( DataInfo().GetNClasses() );  // one output node for each class
00178    else
00179       layout->push_back(1);  // one output node (for signal/background classification)
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    // initialize ANNBase object
00193    fNetwork         = NULL;
00194    frgen            = NULL;
00195    fActivation      = NULL;
00196    fOutput          = NULL; //zjh
00197    fIdentity        = NULL;
00198    fInputCalculator = NULL;
00199    fSynapses        = NULL;
00200    fEstimatorHistTrain = NULL;
00201    fEstimatorHistTest  = NULL;
00202 
00203    // reset monitorign histogram vectors
00204    fEpochMonHistS.clear();
00205    fEpochMonHistB.clear();
00206    fEpochMonHistW.clear();
00207 
00208    // these will be set in BuildNetwork()
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    // destructor
00221    DeleteNetwork();
00222 }
00223 
00224 //______________________________________________________________________________
00225 void TMVA::MethodANNBase::DeleteNetwork()
00226 {
00227    // delete/clear network
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;  //zjh
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; //zjh
00249    fIdentity        = NULL;
00250    fInputCalculator = NULL;
00251    fSynapses        = NULL;
00252 }
00253 
00254 //______________________________________________________________________________
00255 void TMVA::MethodANNBase::DeleteNetworkLayer( TObjArray*& layer )
00256 {
00257    // delete a network layer
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    // build network given a layout (number of neurons in each layer)
00272    // and optional weights array
00273 
00274    if (fEstimator!=kMSE && fEstimator!=kCE) {
00275       if (fEstimatorS == "MSE")  fEstimator = kMSE;    //zjh
00276       else if (fEstimatorS == "CE")    fEstimator = kCE;      //zjh
00277    }
00278    if (fEstimator!=kMSE && fEstimator!=kCE) Log()<<kWARNING<<"Estimator type unspecified \t"<<Endl; //zjh
00279 
00280 
00281 
00282    Log() << kINFO << "Building Network" << Endl;
00283 
00284    DeleteNetwork();
00285    InitANNBase();
00286 
00287    // set activation and input functions
00288    TActivationChooser aChooser;
00289    fActivation = aChooser.CreateActivation(fNeuronType);
00290    fIdentity   = aChooser.CreateActivation("linear");
00291    if (fEstimator==kMSE)  fOutput = aChooser.CreateActivation("linear");  //zjh
00292    else if (fEstimator==kCE)   fOutput = aChooser.CreateActivation("sigmoid"); //zjh
00293    TNeuronInputChooser iChooser;
00294    fInputCalculator = iChooser.CreateNeuronInput(fNeuronInputType);
00295 
00296    fNetwork = new TObjArray();
00297    fRegulatorIdx.clear();               //zjh
00298    fRegulators.clear();                 //zjh
00299    BuildLayers( layout, fromFile );
00300 
00301    // cache input layer and output neuron for fast access
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    // build the network layers
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    // cache pointers to synapses for fast access, the order matters
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.);  //zjh
00335       for (Int_t j = 0; j < numNeurons; j++) {
00336          if (i==0) fRegulators.push_back(0.);                   //zjh
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);      //zjh
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    // build a single layer with neurons and synapses connecting this
00354    // layer to the previous layer
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          // input layer
00370          if (layerIndex == 0) {
00371             neuron->SetActivationEqn(fIdentity);
00372             neuron->SetInputNeuron();
00373          }
00374          else {
00375             // output layer
00376             if (layerIndex == numLayers-1) {
00377                neuron->SetOutputNeuron();
00378                neuron->SetActivationEqn(fOutput);     //zjh
00379          }
00380             // hidden layers
00381             else neuron->SetActivationEqn(fActivation);
00382             AddPreLinks(neuron, prevLayer);
00383          }
00384          
00385          curLayer->Add(neuron);
00386       }
00387    }
00388 
00389    // add bias neutron (except to output layer)
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    // add synapses connecting a neuron to its preceding layer
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    // initialize the synapse weights randomly
00424    PrintMessage("Initializing weights");
00425    
00426    // init synapse weights
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    // force the synapse weights
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    // force the input values of the input neurons
00453    // force the value for each input neuron
00454 
00455    Double_t x;
00456    TNeuron* neuron;
00457 
00458    //   const Event* ev = GetEvent();
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    // calculate input values to each neuron
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    // print messages, turn off printing by setting verbose and debug flag appropriately
00495    if (Verbose() || Debug() || force) Log() << kINFO << message << Endl;
00496 }
00497 
00498 //______________________________________________________________________________
00499 void TMVA::MethodANNBase::WaitForKeyboard()
00500 {
00501    // wait for keyboard input, for debugging
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    // print network representation, for debugging
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    // print a single layer, for debugging
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    // print a neuron, for debugging
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    // get the mva value generated by the NN
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    // check the output of the network
00584    TObjArray* outputLayer = (TObjArray*)fNetwork->At( fNetwork->GetEntriesFast()-1 );
00585    neuron = (TNeuron*)outputLayer->At(0);
00586 
00587    // cannot determine error
00588    NoErrorCalc(err, errUpper);
00589 
00590    return neuron->GetActivationValue();
00591 }
00592 
00593 //_______________________________________________________________________
00594 const std::vector<Float_t> &TMVA::MethodANNBase::GetRegressionValues() 
00595 {
00596    // get the regression value generated by the NN
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    // check the output of the network
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    // get the multiclass classification values generated by the NN
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    // check the output of the network
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    // create XML description of ANN classifier
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    // if inverse hessian exists, write inverse hessian to weight file
00703    if( fInvHessian.GetNcols()>0 ){
00704       void* xmlInvHessian = gTools().xmlengine().NewChild(wght, 0, "InverseHessian");
00705 
00706       // get the matrix dimensions
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       // read in the matrix elements
00715       Double_t* elements = new Double_t[nElements+10];
00716       fInvHessian.GetMatrix2Array( elements );
00717 
00718       // store the matrix elements row-wise
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          // create the rows
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    // read MLP from xml weight file
00742 
00743    // build the layout first
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    // fill the weights of the synapses
00768    UInt_t nSyn;
00769    Float_t weight;
00770    ch = gTools().xmlengine().GetChild(xmlLayout);
00771    UInt_t iLayer = 0;
00772    while (ch) {  // layers
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 ){ // neurons
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++) { // synapses
00786 
00787                TSynapse* synapse = neuron->PostLinkAt(iSyn);
00788                s >> weight;
00789                //Log() << kWARNING << neuron << " " << weight <<  Endl;
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       // no inverse hessian available
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    // adjust the matrix dimensions
00818    fInvHessian.ResizeTo( nRows, nCols );
00819 
00820    // prepare an array to read in the values
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) {  // rows
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++) { // columns
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    // destroy/clear the network then read it back in from the weights file
00852 
00853    // delete network so we can reconstruct network from scratch
00854 
00855    TString dummy;
00856 
00857    // synapse weights
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); // use w/ slower write-out
00862 
00863    ForceWeights(weights);
00864    
00865 
00866    delete weights;
00867 }
00868 
00869 //_______________________________________________________________________
00870 const TMVA::Ranking* TMVA::MethodANNBase::CreateRanking()
00871 {
00872    // compute ranking of input variables by summing function of weights
00873 
00874    // create the ranking object
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); // fix this line
00888 
00889       // figure out average value of variable i
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; // change this into a real weighted average
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    // write histograms to file
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    // histograms containing weights for architecture plotting (used in macro "network.C")
00959    CreateWeightMonitoringHists( "weights_hist" );
00960 
00961    // now save all the epoch-wise monitoring information
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    // write specific classifier response
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;     //zjh
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    // writing of the GetMvaValue__ method
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 { // fNeuronInputType == TNeuronInputChooser::kAbsSum
01074          fout << "         fWeights[" << i+1 << "][o] += fabs(inputVal);" << endl;
01075       }
01076       fout << "      }" << endl;
01077       if (i+1 != numLayers-1) // in the last layer no activation function is applied
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; //zjh
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";         //zjh
01090    fOutput->MakeFunction(fout, fncName);                        //zjh
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    // who the hell makes such strange Debug flags that even use "global pointers"..
01104    return fgDEBUG; 
01105 }

Generated on Tue Jul 5 15:25:00 2011 for ROOT_528-00b_version by  doxygen 1.5.1