00001 // @(#)root/tmva $Id: TNeuron.cxx 36966 2010-11-26 09:50:13Z evt $ 00002 // Author: Matt Jachowski 00003 00004 /********************************************************************************** 00005 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis * 00006 * Package: TMVA * 00007 * Class : TNeuron * 00008 * Web : http://tmva.sourceforge.net * 00009 * * 00010 * Description: * 00011 * Implementation (see header for description) * 00012 * * 00013 * Authors (alphabetical): * 00014 * Matt Jachowski <jachowski@stanford.edu> - Stanford University, USA * 00015 * * 00016 * Copyright (c) 2005: * 00017 * CERN, Switzerland * 00018 * * 00019 * Redistribution and use in source and binary forms, with or without * 00020 * modification, are permitted according to the terms listed in LICENSE * 00021 * (http://tmva.sourceforge.net/LICENSE) * 00022 **********************************************************************************/ 00023 00024 //_______________________________________________________________________ 00025 // 00026 // Neuron class used by TMVA artificial neural network methods 00027 // 00028 //_______________________________________________________________________ 00029 00030 #include "TH1D.h" 00031 00032 #ifndef ROOT_TMVA_MsgLogger 00033 #include "TMVA/MsgLogger.h" 00034 #endif 00035 #ifndef ROOT_TMVA_TNeuron 00036 #include "TMVA/TNeuron.h" 00037 #endif 00038 #ifndef ROOT_TMVA_TActivation 00039 #include "TMVA/TActivation.h" 00040 #endif 00041 #ifndef ROOT_TMVA_Tools 00042 #include "TMVA/Tools.h" 00043 #endif 00044 #ifndef ROOT_TMVA_TNeuronInput 00045 #include "TMVA/TNeuronInput.h" 00046 #endif 00047 00048 static const Int_t UNINITIALIZED = -1; 00049 00050 using std::vector; 00051 00052 ClassImp(TMVA::TNeuron) 00053 00054 TMVA::MsgLogger* TMVA::TNeuron::fgLogger = 0; 00055 00056 //______________________________________________________________________________ 00057 TMVA::TNeuron::TNeuron() 00058 { 00059 // standard constructor 00060 if (!fgLogger) fgLogger = new MsgLogger("TNeuron",kDEBUG); 00061 InitNeuron(); 00062 } 00063 00064 TMVA::TNeuron::~TNeuron() 00065 { 00066 // destructor 00067 if (fLinksIn != NULL) delete fLinksIn; 00068 if (fLinksOut != NULL) delete fLinksOut; 00069 } 00070 00071 void TMVA::TNeuron::InitNeuron() 00072 { 00073 // initialize the neuron, most variables still need to be set via setters 00074 fLinksIn = new TObjArray(); 00075 fLinksOut = new TObjArray(); 00076 fValue = UNINITIALIZED; 00077 fActivationValue = UNINITIALIZED; 00078 fDelta = UNINITIALIZED; 00079 fDEDw = UNINITIALIZED; 00080 fError = UNINITIALIZED; 00081 fActivation = NULL; 00082 fForcedValue = kFALSE; 00083 fInputCalculator = NULL; 00084 } 00085 00086 //______________________________________________________________________________ 00087 void TMVA::TNeuron::ForceValue(Double_t value) 00088 { 00089 // force the value, typically for input and bias neurons 00090 fValue = value; 00091 fForcedValue = kTRUE; 00092 } 00093 00094 //______________________________________________________________________________ 00095 void TMVA::TNeuron::CalculateValue() 00096 { 00097 // calculate neuron input 00098 if (fForcedValue) return; 00099 fValue = fInputCalculator->GetInput(this); 00100 } 00101 00102 //______________________________________________________________________________ 00103 void TMVA::TNeuron::CalculateActivationValue() 00104 { 00105 // calculate neuron activation/output 00106 00107 if (fActivation == NULL) { 00108 PrintMessage( kWARNING ,"No activation equation specified." ); 00109 fActivationValue = UNINITIALIZED; 00110 return; 00111 } 00112 fActivationValue = fActivation->Eval(fValue); 00113 } 00114 00115 00116 //______________________________________________________________________________ 00117 void TMVA::TNeuron::CalculateDelta() 00118 { 00119 // calculate error field 00120 00121 // no need to adjust input neurons 00122 if (IsInputNeuron()) { 00123 fDelta = 0.0; 00124 return; 00125 } 00126 00127 Double_t error; 00128 00129 // output neuron should have error set all ready 00130 if (IsOutputNeuron()) error = fError; 00131 00132 // need to calculate error for any other neuron 00133 else { 00134 error = 0.0; 00135 TSynapse* synapse = NULL; 00136 TObjArrayIter* iter = (TObjArrayIter*)fLinksOut->MakeIterator(); 00137 00138 while (true) { 00139 synapse = (TSynapse*) iter->Next(); 00140 if (synapse == NULL) break; 00141 error += synapse->GetWeightedDelta(); 00142 } 00143 00144 delete iter; 00145 } 00146 00147 fDelta = error * fActivation->EvalDerivative(GetValue()); 00148 } 00149 00150 //______________________________________________________________________________ 00151 void TMVA::TNeuron::SetInputCalculator(TNeuronInput* calculator) 00152 { 00153 // set input calculator 00154 if (fInputCalculator != NULL) delete fInputCalculator; 00155 fInputCalculator = calculator; 00156 } 00157 00158 //______________________________________________________________________________ 00159 void TMVA::TNeuron::SetActivationEqn(TActivation* activation) 00160 { 00161 // set activation equation 00162 if (fActivation != NULL) delete fActivation; 00163 fActivation = activation; 00164 } 00165 00166 //______________________________________________________________________________ 00167 void TMVA::TNeuron::AddPreLink(TSynapse* pre) 00168 { 00169 // add synapse as a pre-link to this neuron 00170 if (IsInputNeuron()) return; 00171 fLinksIn->Add(pre); 00172 } 00173 00174 //______________________________________________________________________________ 00175 void TMVA::TNeuron::AddPostLink(TSynapse* post) 00176 { 00177 // add synapse as a post-link to this neuron 00178 if (IsOutputNeuron()) return; 00179 fLinksOut->Add(post); 00180 } 00181 00182 //______________________________________________________________________________ 00183 void TMVA::TNeuron::DeletePreLinks() 00184 { 00185 // delete all pre-links 00186 DeleteLinksArray(fLinksIn); 00187 } 00188 00189 //______________________________________________________________________________ 00190 void TMVA::TNeuron::DeleteLinksArray(TObjArray*& links) 00191 { 00192 // delete an array of TSynapses 00193 00194 if (links == NULL) return; 00195 00196 TSynapse* synapse = NULL; 00197 Int_t numLinks = links->GetEntriesFast(); 00198 for (Int_t i=0; i<numLinks; i++) { 00199 synapse = (TSynapse*)links->At(i); 00200 if (synapse != NULL) delete synapse; 00201 } 00202 delete links; 00203 links = NULL; 00204 } 00205 00206 //______________________________________________________________________________ 00207 void TMVA::TNeuron::SetError(Double_t error) 00208 { 00209 // set error, this should only be done for an output neuron 00210 if (!IsOutputNeuron()) 00211 PrintMessage( kWARNING, "Warning! Setting an error on a non-output neuron is probably not what you want to do." ); 00212 00213 fError = error; 00214 } 00215 00216 //______________________________________________________________________________ 00217 void TMVA::TNeuron::UpdateSynapsesBatch() 00218 { 00219 // update and adjust the pre-synapses for each neuron (input neuron has no pre-synapse) 00220 // this method should only be called in batch mode 00221 00222 if (IsInputNeuron()) return; 00223 00224 TSynapse* synapse = NULL; 00225 TObjArrayIter* iter = (TObjArrayIter*) fLinksIn->MakeIterator(); 00226 00227 while (true) { 00228 synapse = (TSynapse*) iter->Next(); 00229 if (synapse == NULL) break; 00230 synapse->CalculateDelta(); 00231 } 00232 00233 delete iter; 00234 } 00235 00236 //______________________________________________________________________________ 00237 void TMVA::TNeuron::UpdateSynapsesSequential() 00238 { 00239 // update the pre-synapses for each neuron (input neuron has no pre-synapse) 00240 // this method should only be called in sequential mode 00241 00242 if (IsInputNeuron()) return; 00243 00244 TSynapse* synapse = NULL; 00245 TObjArrayIter* iter = (TObjArrayIter*) fLinksIn->MakeIterator(); 00246 00247 while (true) { 00248 synapse = (TSynapse*) iter->Next(); 00249 if (synapse == NULL) break; 00250 synapse->InitDelta(); 00251 synapse->CalculateDelta(); 00252 synapse->AdjustWeight(); 00253 } 00254 00255 delete iter; 00256 } 00257 00258 //______________________________________________________________________________ 00259 void TMVA::TNeuron::AdjustSynapseWeights() 00260 { 00261 // adjust the pre-synapses' weights for each neuron (input neuron has no pre-synapse) 00262 // this method should only be called in batch mode 00263 00264 if (IsInputNeuron()) return; 00265 00266 TSynapse* synapse = NULL; 00267 TObjArrayIter* iter = (TObjArrayIter*) fLinksIn->MakeIterator(); 00268 00269 while (true) { 00270 synapse = (TSynapse*) iter->Next(); 00271 if (synapse == NULL) break; 00272 synapse->AdjustWeight(); 00273 } 00274 00275 delete iter; 00276 } 00277 00278 //______________________________________________________________________________ 00279 void TMVA::TNeuron::InitSynapseDeltas() 00280 { 00281 // initialize the error fields of all pre-neurons 00282 // this method should only be called in batch mode 00283 00284 // an input neuron has no pre-weights to adjust 00285 if (IsInputNeuron()) return; 00286 00287 TSynapse* synapse = NULL; 00288 TObjArrayIter* iter = (TObjArrayIter*) fLinksIn->MakeIterator(); 00289 00290 while (true) { 00291 synapse = (TSynapse*) iter->Next(); 00292 if (synapse == NULL) break; 00293 synapse->InitDelta(); 00294 } 00295 00296 delete iter; 00297 } 00298 00299 //______________________________________________________________________________ 00300 void TMVA::TNeuron::PrintLinks(TObjArray* links) const 00301 { 00302 // print an array of TSynapses, for debugging 00303 00304 if (links == NULL) { 00305 Log() << kDEBUG << "\t\t\t<none>" << Endl; 00306 return; 00307 } 00308 00309 TSynapse* synapse; 00310 00311 Int_t numLinks = links->GetEntriesFast(); 00312 for (Int_t i = 0; i < numLinks; i++) { 00313 synapse = (TSynapse*)links->At(i); 00314 Log() << kDEBUG << 00315 "\t\t\tweighta: " << synapse->GetWeight() 00316 << "\t\tw-value: " << synapse->GetWeightedValue() 00317 << "\t\tw-delta: " << synapse->GetWeightedDelta() 00318 << "\t\tl-rate: " << synapse->GetLearningRate() 00319 << Endl; 00320 } 00321 } 00322 00323 //______________________________________________________________________________ 00324 void TMVA::TNeuron::PrintActivationEqn() 00325 { 00326 // print activation equation, for debugging 00327 if (fActivation != NULL) Log() << kDEBUG << fActivation->GetExpression() << Endl; 00328 else Log() << kDEBUG << "<none>" << Endl; 00329 } 00330 00331 //______________________________________________________________________________ 00332 void TMVA::TNeuron::PrintMessage( EMsgType type, TString message) 00333 { 00334 // print message, for debugging 00335 Log() << type << message << Endl; 00336 }