ROOT logo
// @(#)root/tmva $Id$
// Author: Matt Jachowski

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : TNeuron                                                               *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Implementation (see header for description)                               *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Matt Jachowski  <jachowski@stanford.edu> - Stanford University, USA       *
 *                                                                                *
 * Copyright (c) 2005:                                                            *
 *      CERN, Switzerland                                                         *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without             *
 * modification, are permitted according to the terms listed in LICENSE           *
 * (http://tmva.sourceforge.net/LICENSE)                                          *
 **********************************************************************************/

//_______________________________________________________________________
//
// Neuron class used by TMVA artificial neural network methods
//
//_______________________________________________________________________

#include "TH1D.h"

#ifndef ROOT_TMVA_MsgLogger
#include "TMVA/MsgLogger.h"
#endif
#ifndef ROOT_TMVA_TNeuron
#include "TMVA/TNeuron.h"
#endif
#ifndef ROOT_TMVA_TActivation
#include "TMVA/TActivation.h"
#endif
#ifndef ROOT_TMVA_Tools
#include "TMVA/Tools.h"
#endif
#ifndef ROOT_TMVA_TNeuronInput
#include "TMVA/TNeuronInput.h"
#endif

static const Int_t UNINITIALIZED = -1;

using std::vector;

ClassImp(TMVA::TNeuron)

TMVA::MsgLogger* TMVA::TNeuron::fgLogger = 0;

//______________________________________________________________________________
TMVA::TNeuron::TNeuron()
{
   // standard constructor
   if (!fgLogger) fgLogger = new MsgLogger("TNeuron",kDEBUG);
   InitNeuron();
}

TMVA::TNeuron::~TNeuron()
{
   // destructor
   if (fLinksIn != NULL)  delete fLinksIn;
   if (fLinksOut != NULL) delete fLinksOut;
}

void TMVA::TNeuron::InitNeuron()
{
   // initialize the neuron, most variables still need to be set via setters
   fLinksIn = new TObjArray();
   fLinksOut = new TObjArray();
   fValue = UNINITIALIZED;
   fActivationValue = UNINITIALIZED;
   fDelta = UNINITIALIZED;
   fDEDw = UNINITIALIZED;
   fError = UNINITIALIZED;
   fActivation = NULL;
   fForcedValue = kFALSE;
   fInputCalculator = NULL;
}

//______________________________________________________________________________
void TMVA::TNeuron::ForceValue(Double_t value)
{
   // force the value, typically for input and bias neurons
   fValue = value;
   fForcedValue = kTRUE;
}

//______________________________________________________________________________
void TMVA::TNeuron::CalculateValue()
{
   // calculate neuron input
   if (fForcedValue) return;
   fValue = fInputCalculator->GetInput(this);
}

//______________________________________________________________________________
void TMVA::TNeuron::CalculateActivationValue()
{
   // calculate neuron activation/output

   if (fActivation == NULL) {
      PrintMessage( kWARNING ,"No activation equation specified." );
      fActivationValue = UNINITIALIZED;
      return;
   }
   fActivationValue = fActivation->Eval(fValue);
}


//______________________________________________________________________________
void TMVA::TNeuron::CalculateDelta()
{
   // calculate error field

   // no need to adjust input neurons
   if (IsInputNeuron()) {
      fDelta = 0.0;
      return;
   }

   Double_t error;


   // output neuron should have error set all ready
   if (IsOutputNeuron()) error = fError;

   // need to calculate error for any other neuron
   else {
      error = 0.0;
      TSynapse* synapse = NULL;
      // Replaced TObjArrayIter pointer by object, as creating it on the stack
      // is much faster (5-10% improvement seen) than re-allocating the new
      // memory for the pointer each time. Thansk to Peter Elmer who pointed this out
      //      TObjArrayIter* iter = (TObjArrayIter*)fLinksOut->MakeIterator();
      TObjArrayIter iter(fLinksOut);
      while (true) {
         synapse = (TSynapse*) iter.Next();
         if (synapse == NULL) break;
         error += synapse->GetWeightedDelta();
      }

   }

   fDelta = error * fActivation->EvalDerivative(GetValue());
}

//______________________________________________________________________________
void TMVA::TNeuron::SetInputCalculator(TNeuronInput* calculator)
{
   // set input calculator
   if (fInputCalculator != NULL) delete fInputCalculator; 
   fInputCalculator = calculator;
}

//______________________________________________________________________________
void TMVA::TNeuron::SetActivationEqn(TActivation* activation)
{
   // set activation equation
   if (fActivation != NULL) delete fActivation;
   fActivation = activation;
}

//______________________________________________________________________________
void TMVA::TNeuron::AddPreLink(TSynapse* pre)
{
   // add synapse as a pre-link to this neuron
   if (IsInputNeuron()) return;
   fLinksIn->Add(pre);
}

//______________________________________________________________________________
void TMVA::TNeuron::AddPostLink(TSynapse* post)
{
   // add synapse as a post-link to this neuron
   if (IsOutputNeuron()) return;
   fLinksOut->Add(post);
}

//______________________________________________________________________________
void TMVA::TNeuron::DeletePreLinks()
{
   // delete all pre-links
   DeleteLinksArray(fLinksIn);
}

//______________________________________________________________________________
void TMVA::TNeuron::DeleteLinksArray(TObjArray*& links)
{
   // delete an array of TSynapses

   if (links == NULL) return;

   TSynapse* synapse = NULL;
   Int_t numLinks = links->GetEntriesFast();
   for (Int_t i=0; i<numLinks; i++) {
      synapse = (TSynapse*)links->At(i);
      if (synapse != NULL) delete synapse;
   }
   delete links;
   links = NULL;
}

//______________________________________________________________________________
void TMVA::TNeuron::SetError(Double_t error)
{
   // set error, this should only be done for an output neuron
   if (!IsOutputNeuron())
      PrintMessage( kWARNING, "Warning! Setting an error on a non-output neuron is probably not what you want to do." );

   fError = error;
}

//______________________________________________________________________________
void TMVA::TNeuron::UpdateSynapsesBatch()
{
   // update and adjust the pre-synapses for each neuron (input neuron has no pre-synapse)
   // this method should only be called in batch mode

   if (IsInputNeuron()) return;

   TSynapse* synapse = NULL;
   TObjArrayIter iter(fLinksIn);
   while (true) {
      synapse = (TSynapse*) iter.Next();
      if (synapse == NULL) break;
      synapse->CalculateDelta();
   }

}

//______________________________________________________________________________
void TMVA::TNeuron::UpdateSynapsesSequential()
{
   // update the pre-synapses for each neuron (input neuron has no pre-synapse)
   // this method should only be called in sequential mode

   if (IsInputNeuron()) return;

   TSynapse* synapse = NULL;
   TObjArrayIter iter(fLinksIn);

   while (true) {
      synapse = (TSynapse*) iter.Next();
      if (synapse == NULL) break;
      synapse->InitDelta();
      synapse->CalculateDelta();
      synapse->AdjustWeight();
   }

}

//______________________________________________________________________________
void TMVA::TNeuron::AdjustSynapseWeights()
{
   // adjust the pre-synapses' weights for each neuron (input neuron has no pre-synapse)
   // this method should only be called in batch mode

   if (IsInputNeuron()) return;

   TSynapse* synapse = NULL;
   TObjArrayIter iter(fLinksIn);


   while (true) {
      synapse = (TSynapse*) iter.Next();
      if (synapse == NULL) break;
      synapse->AdjustWeight();
   }

}

//______________________________________________________________________________
void TMVA::TNeuron::InitSynapseDeltas()
{
   // initialize the error fields of all pre-neurons
   // this method should only be called in batch mode

   // an input neuron has no pre-weights to adjust
   if (IsInputNeuron()) return;

   TSynapse* synapse = NULL;
   TObjArrayIter iter(fLinksIn);

   while (true) {
      synapse = (TSynapse*) iter.Next();

      if (synapse == NULL) break;
      synapse->InitDelta();
   }

}

//______________________________________________________________________________
void TMVA::TNeuron::PrintLinks(TObjArray* links) const 
{
   // print an array of TSynapses, for debugging

   if (links == NULL) {
      Log() << kDEBUG << "\t\t\t<none>" << Endl;
      return;
   }

   TSynapse* synapse;

   Int_t numLinks = links->GetEntriesFast();
   for  (Int_t i = 0; i < numLinks; i++) {
      synapse = (TSynapse*)links->At(i);
      Log() << kDEBUG <<  
         "\t\t\tweighta: " << synapse->GetWeight()
            << "\t\tw-value: " << synapse->GetWeightedValue()
            << "\t\tw-delta: " << synapse->GetWeightedDelta()
            << "\t\tl-rate: "  << synapse->GetLearningRate()
            << Endl;
   }
}

//______________________________________________________________________________
void TMVA::TNeuron::PrintActivationEqn()
{
   // print activation equation, for debugging
   if (fActivation != NULL) Log() << kDEBUG << fActivation->GetExpression() << Endl;
   else                     Log() << kDEBUG << "<none>" << Endl;
}

//______________________________________________________________________________
void TMVA::TNeuron::PrintMessage( EMsgType type, TString message)
{
   // print message, for debugging
   Log() << type << message << Endl;
}
 TNeuron.cxx:1
 TNeuron.cxx:2
 TNeuron.cxx:3
 TNeuron.cxx:4
 TNeuron.cxx:5
 TNeuron.cxx:6
 TNeuron.cxx:7
 TNeuron.cxx:8
 TNeuron.cxx:9
 TNeuron.cxx:10
 TNeuron.cxx:11
 TNeuron.cxx:12
 TNeuron.cxx:13
 TNeuron.cxx:14
 TNeuron.cxx:15
 TNeuron.cxx:16
 TNeuron.cxx:17
 TNeuron.cxx:18
 TNeuron.cxx:19
 TNeuron.cxx:20
 TNeuron.cxx:21
 TNeuron.cxx:22
 TNeuron.cxx:23
 TNeuron.cxx:24
 TNeuron.cxx:25
 TNeuron.cxx:26
 TNeuron.cxx:27
 TNeuron.cxx:28
 TNeuron.cxx:29
 TNeuron.cxx:30
 TNeuron.cxx:31
 TNeuron.cxx:32
 TNeuron.cxx:33
 TNeuron.cxx:34
 TNeuron.cxx:35
 TNeuron.cxx:36
 TNeuron.cxx:37
 TNeuron.cxx:38
 TNeuron.cxx:39
 TNeuron.cxx:40
 TNeuron.cxx:41
 TNeuron.cxx:42
 TNeuron.cxx:43
 TNeuron.cxx:44
 TNeuron.cxx:45
 TNeuron.cxx:46
 TNeuron.cxx:47
 TNeuron.cxx:48
 TNeuron.cxx:49
 TNeuron.cxx:50
 TNeuron.cxx:51
 TNeuron.cxx:52
 TNeuron.cxx:53
 TNeuron.cxx:54
 TNeuron.cxx:55
 TNeuron.cxx:56
 TNeuron.cxx:57
 TNeuron.cxx:58
 TNeuron.cxx:59
 TNeuron.cxx:60
 TNeuron.cxx:61
 TNeuron.cxx:62
 TNeuron.cxx:63
 TNeuron.cxx:64
 TNeuron.cxx:65
 TNeuron.cxx:66
 TNeuron.cxx:67
 TNeuron.cxx:68
 TNeuron.cxx:69
 TNeuron.cxx:70
 TNeuron.cxx:71
 TNeuron.cxx:72
 TNeuron.cxx:73
 TNeuron.cxx:74
 TNeuron.cxx:75
 TNeuron.cxx:76
 TNeuron.cxx:77
 TNeuron.cxx:78
 TNeuron.cxx:79
 TNeuron.cxx:80
 TNeuron.cxx:81
 TNeuron.cxx:82
 TNeuron.cxx:83
 TNeuron.cxx:84
 TNeuron.cxx:85
 TNeuron.cxx:86
 TNeuron.cxx:87
 TNeuron.cxx:88
 TNeuron.cxx:89
 TNeuron.cxx:90
 TNeuron.cxx:91
 TNeuron.cxx:92
 TNeuron.cxx:93
 TNeuron.cxx:94
 TNeuron.cxx:95
 TNeuron.cxx:96
 TNeuron.cxx:97
 TNeuron.cxx:98
 TNeuron.cxx:99
 TNeuron.cxx:100
 TNeuron.cxx:101
 TNeuron.cxx:102
 TNeuron.cxx:103
 TNeuron.cxx:104
 TNeuron.cxx:105
 TNeuron.cxx:106
 TNeuron.cxx:107
 TNeuron.cxx:108
 TNeuron.cxx:109
 TNeuron.cxx:110
 TNeuron.cxx:111
 TNeuron.cxx:112
 TNeuron.cxx:113
 TNeuron.cxx:114
 TNeuron.cxx:115
 TNeuron.cxx:116
 TNeuron.cxx:117
 TNeuron.cxx:118
 TNeuron.cxx:119
 TNeuron.cxx:120
 TNeuron.cxx:121
 TNeuron.cxx:122
 TNeuron.cxx:123
 TNeuron.cxx:124
 TNeuron.cxx:125
 TNeuron.cxx:126
 TNeuron.cxx:127
 TNeuron.cxx:128
 TNeuron.cxx:129
 TNeuron.cxx:130
 TNeuron.cxx:131
 TNeuron.cxx:132
 TNeuron.cxx:133
 TNeuron.cxx:134
 TNeuron.cxx:135
 TNeuron.cxx:136
 TNeuron.cxx:137
 TNeuron.cxx:138
 TNeuron.cxx:139
 TNeuron.cxx:140
 TNeuron.cxx:141
 TNeuron.cxx:142
 TNeuron.cxx:143
 TNeuron.cxx:144
 TNeuron.cxx:145
 TNeuron.cxx:146
 TNeuron.cxx:147
 TNeuron.cxx:148
 TNeuron.cxx:149
 TNeuron.cxx:150
 TNeuron.cxx:151
 TNeuron.cxx:152
 TNeuron.cxx:153
 TNeuron.cxx:154
 TNeuron.cxx:155
 TNeuron.cxx:156
 TNeuron.cxx:157
 TNeuron.cxx:158
 TNeuron.cxx:159
 TNeuron.cxx:160
 TNeuron.cxx:161
 TNeuron.cxx:162
 TNeuron.cxx:163
 TNeuron.cxx:164
 TNeuron.cxx:165
 TNeuron.cxx:166
 TNeuron.cxx:167
 TNeuron.cxx:168
 TNeuron.cxx:169
 TNeuron.cxx:170
 TNeuron.cxx:171
 TNeuron.cxx:172
 TNeuron.cxx:173
 TNeuron.cxx:174
 TNeuron.cxx:175
 TNeuron.cxx:176
 TNeuron.cxx:177
 TNeuron.cxx:178
 TNeuron.cxx:179
 TNeuron.cxx:180
 TNeuron.cxx:181
 TNeuron.cxx:182
 TNeuron.cxx:183
 TNeuron.cxx:184
 TNeuron.cxx:185
 TNeuron.cxx:186
 TNeuron.cxx:187
 TNeuron.cxx:188
 TNeuron.cxx:189
 TNeuron.cxx:190
 TNeuron.cxx:191
 TNeuron.cxx:192
 TNeuron.cxx:193
 TNeuron.cxx:194
 TNeuron.cxx:195
 TNeuron.cxx:196
 TNeuron.cxx:197
 TNeuron.cxx:198
 TNeuron.cxx:199
 TNeuron.cxx:200
 TNeuron.cxx:201
 TNeuron.cxx:202
 TNeuron.cxx:203
 TNeuron.cxx:204
 TNeuron.cxx:205
 TNeuron.cxx:206
 TNeuron.cxx:207
 TNeuron.cxx:208
 TNeuron.cxx:209
 TNeuron.cxx:210
 TNeuron.cxx:211
 TNeuron.cxx:212
 TNeuron.cxx:213
 TNeuron.cxx:214
 TNeuron.cxx:215
 TNeuron.cxx:216
 TNeuron.cxx:217
 TNeuron.cxx:218
 TNeuron.cxx:219
 TNeuron.cxx:220
 TNeuron.cxx:221
 TNeuron.cxx:222
 TNeuron.cxx:223
 TNeuron.cxx:224
 TNeuron.cxx:225
 TNeuron.cxx:226
 TNeuron.cxx:227
 TNeuron.cxx:228
 TNeuron.cxx:229
 TNeuron.cxx:230
 TNeuron.cxx:231
 TNeuron.cxx:232
 TNeuron.cxx:233
 TNeuron.cxx:234
 TNeuron.cxx:235
 TNeuron.cxx:236
 TNeuron.cxx:237
 TNeuron.cxx:238
 TNeuron.cxx:239
 TNeuron.cxx:240
 TNeuron.cxx:241
 TNeuron.cxx:242
 TNeuron.cxx:243
 TNeuron.cxx:244
 TNeuron.cxx:245
 TNeuron.cxx:246
 TNeuron.cxx:247
 TNeuron.cxx:248
 TNeuron.cxx:249
 TNeuron.cxx:250
 TNeuron.cxx:251
 TNeuron.cxx:252
 TNeuron.cxx:253
 TNeuron.cxx:254
 TNeuron.cxx:255
 TNeuron.cxx:256
 TNeuron.cxx:257
 TNeuron.cxx:258
 TNeuron.cxx:259
 TNeuron.cxx:260
 TNeuron.cxx:261
 TNeuron.cxx:262
 TNeuron.cxx:263
 TNeuron.cxx:264
 TNeuron.cxx:265
 TNeuron.cxx:266
 TNeuron.cxx:267
 TNeuron.cxx:268
 TNeuron.cxx:269
 TNeuron.cxx:270
 TNeuron.cxx:271
 TNeuron.cxx:272
 TNeuron.cxx:273
 TNeuron.cxx:274
 TNeuron.cxx:275
 TNeuron.cxx:276
 TNeuron.cxx:277
 TNeuron.cxx:278
 TNeuron.cxx:279
 TNeuron.cxx:280
 TNeuron.cxx:281
 TNeuron.cxx:282
 TNeuron.cxx:283
 TNeuron.cxx:284
 TNeuron.cxx:285
 TNeuron.cxx:286
 TNeuron.cxx:287
 TNeuron.cxx:288
 TNeuron.cxx:289
 TNeuron.cxx:290
 TNeuron.cxx:291
 TNeuron.cxx:292
 TNeuron.cxx:293
 TNeuron.cxx:294
 TNeuron.cxx:295
 TNeuron.cxx:296
 TNeuron.cxx:297
 TNeuron.cxx:298
 TNeuron.cxx:299
 TNeuron.cxx:300
 TNeuron.cxx:301
 TNeuron.cxx:302
 TNeuron.cxx:303
 TNeuron.cxx:304
 TNeuron.cxx:305
 TNeuron.cxx:306
 TNeuron.cxx:307
 TNeuron.cxx:308
 TNeuron.cxx:309
 TNeuron.cxx:310
 TNeuron.cxx:311
 TNeuron.cxx:312
 TNeuron.cxx:313
 TNeuron.cxx:314
 TNeuron.cxx:315
 TNeuron.cxx:316
 TNeuron.cxx:317
 TNeuron.cxx:318
 TNeuron.cxx:319
 TNeuron.cxx:320
 TNeuron.cxx:321
 TNeuron.cxx:322
 TNeuron.cxx:323
 TNeuron.cxx:324
 TNeuron.cxx:325
 TNeuron.cxx:326
 TNeuron.cxx:327
 TNeuron.cxx:328
 TNeuron.cxx:329
 TNeuron.cxx:330
 TNeuron.cxx:331
 TNeuron.cxx:332
 TNeuron.cxx:333
 TNeuron.cxx:334
 TNeuron.cxx:335
 TNeuron.cxx:336