88 REGISTER_METHOD(CFMlpANN)
90 using std::stringstream;
94 ClassImp(TMVA::MethodCFMlpANN);
132 TMVA::MethodCFMlpANN::MethodCFMlpANN( const TString& jobName,
133 const TString& methodTitle,
134 DataSetInfo& theData,
135 const TString& theOption ) :
136 TMVA::MethodBase( jobName, Types::kCFMlpANN, methodTitle, theData, theOption),
143 MethodCFMlpANN_nsel(0)
145 MethodCFMlpANN_Utils::SetLogger(&Log());
151 TMVA::MethodCFMlpANN::MethodCFMlpANN( DataSetInfo& theData,
152 const TString& theWeightFile):
153 TMVA::MethodBase( Types::kCFMlpANN, theData, theWeightFile),
160 MethodCFMlpANN_nsel(0)
167 Bool_t TMVA::MethodCFMlpANN::HasAnalysisType( Types::EAnalysisType type, UInt_t numberClasses, UInt_t )
169 if (type == Types::kClassification && numberClasses == 2)
return kTRUE;
178 void TMVA::MethodCFMlpANN::DeclareOptions()
180 DeclareOptionRef( fNcycles =3000,
"NCycles",
"Number of training cycles" );
181 DeclareOptionRef( fLayerSpec=
"N,N-1",
"HiddenLayers",
"Specification of hidden layer architecture" );
187 void TMVA::MethodCFMlpANN::ProcessOptions()
189 fNodes =
new Int_t[20];
191 Int_t currentHiddenLayer = 1;
192 TString layerSpec(fLayerSpec);
193 while(layerSpec.Length()>0) {
195 if (layerSpec.First(
',')<0) {
200 sToAdd = layerSpec(0,layerSpec.First(
','));
201 layerSpec = layerSpec(layerSpec.First(
',')+1,layerSpec.Length());
204 if (sToAdd.BeginsWith(
"N") || sToAdd.BeginsWith(
"n")) { sToAdd.Remove(0,1); nNodes = GetNvar(); }
205 nNodes += atoi(sToAdd);
206 fNodes[currentHiddenLayer++] = nNodes;
209 fNodes[0] = GetNvar();
210 fNodes[fNlayers-1] = 2;
212 if (IgnoreEventsWithNegWeightsInTraining()) {
213 Log() << kFATAL <<
"Mechanism to ignore events with negative weights in training not yet available for method: "
214 << GetMethodTypeName()
215 <<
" --> please remove \"IgnoreNegWeightsInTraining\" option from booking string."
219 Log() << kINFO <<
"Use configuration (nodes per layer): in=";
220 for (Int_t i=0; i<fNlayers-1; i++) Log() << kINFO << fNodes[i] <<
":";
221 Log() << kINFO << fNodes[fNlayers-1] <<
"=out" << Endl;
224 Log() <<
"Use " << fNcycles <<
" training cycles" << Endl;
226 Int_t nEvtTrain = Data()->GetNTrainingEvents();
232 fData =
new TMatrix( nEvtTrain, GetNvar() );
233 fClass =
new std::vector<Int_t>( nEvtTrain );
238 for (Int_t ievt=0; ievt<nEvtTrain; ievt++) {
239 const Event * ev = GetEvent(ievt);
242 (*fClass)[ievt] = DataInfo().IsSignal(ev) ? 1 : 2;
245 for (ivar=0; ivar<GetNvar(); ivar++) {
246 (*fData)( ievt, ivar ) = ev->GetValue(ivar);
259 void TMVA::MethodCFMlpANN::Init(
void )
262 SetNormalised( kTRUE );
265 MethodCFMlpANN_nsel = 0;
271 TMVA::MethodCFMlpANN::~MethodCFMlpANN(
void )
278 for (Int_t i=0; i<fNlayers; i++)
delete[] fYNN[i];
287 void TMVA::MethodCFMlpANN::Train(
void )
290 Int_t ntrain(Data()->GetNTrainingEvents());
292 Int_t nvar(GetNvar());
293 Int_t nlayers(fNlayers);
294 Int_t *nodes =
new Int_t[nlayers];
295 Int_t ncycles(fNcycles);
297 for (Int_t i=0; i<nlayers; i++) nodes[i] = fNodes[i];
300 for (Int_t i=0; i<fNlayers; i++)
delete[] fYNN[i];
304 fYNN =
new Double_t*[nlayers];
305 for (Int_t layer=0; layer<nlayers; layer++)
306 fYNN[layer] =
new Double_t[fNodes[layer]];
310 Train_nn( &dumDat, &dumDat, &ntrain, &ntest, &nvar, &nlayers, nodes, &ncycles );
312 Log() << kWARNING <<
"<Train> sorry CFMlpANN does not run on Windows" << Endl;
323 Double_t TMVA::MethodCFMlpANN::GetMvaValue( Double_t* err, Double_t* errUpper )
327 const Event* ev = GetEvent();
330 std::vector<Double_t> inputVec( GetNvar() );
331 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) inputVec[ivar] = ev->GetValue(ivar);
333 Double_t myMVA = EvalANN( inputVec, isOK );
334 if (!isOK) Log() << kFATAL <<
"EvalANN returns (!isOK) for event " << Endl;
337 NoErrorCalc(err, errUpper);
345 Double_t TMVA::MethodCFMlpANN::EvalANN( std::vector<Double_t>& inVar, Bool_t& isOK )
348 Double_t* xeev =
new Double_t[GetNvar()];
349 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) xeev[ivar] = inVar[ivar];
353 for (UInt_t jvar=0; jvar<GetNvar(); jvar++) {
355 if (fVarn_1.xmax[jvar] < xeev[jvar]) xeev[jvar] = fVarn_1.xmax[jvar];
356 if (fVarn_1.xmin[jvar] > xeev[jvar]) xeev[jvar] = fVarn_1.xmin[jvar];
357 if (fVarn_1.xmax[jvar] == fVarn_1.xmin[jvar]) {
362 xeev[jvar] = xeev[jvar] - ((fVarn_1.xmax[jvar] + fVarn_1.xmin[jvar])/2);
363 xeev[jvar] = xeev[jvar] / ((fVarn_1.xmax[jvar] - fVarn_1.xmin[jvar])/2);
369 Double_t retval = 0.5*(1.0 + fYNN[fParam_1.layerm-1][0]);
379 void TMVA::MethodCFMlpANN::NN_ava( Double_t* xeev )
381 for (Int_t ivar=0; ivar<fNeur_1.neuron[0]; ivar++) fYNN[0][ivar] = xeev[ivar];
383 for (Int_t layer=1; layer<fParam_1.layerm; layer++) {
384 for (Int_t j=1; j<=fNeur_1.neuron[layer]; j++) {
386 Double_t x = Ww_ref(fNeur_1.ww, layer+1,j);
388 for (Int_t k=1; k<=fNeur_1.neuron[layer-1]; k++) {
389 x += fYNN[layer-1][k-1]*W_ref(fNeur_1.w, layer+1, j, k);
391 fYNN[layer][j-1] = NN_fonc( layer, x );
399 Double_t TMVA::MethodCFMlpANN::NN_fonc( Int_t i, Double_t u )
const
403 if (u/fDel_1.temp[i] > 170) f = +1;
404 else if (u/fDel_1.temp[i] < -170) f = -1;
406 Double_t yy = TMath::Exp(-u/fDel_1.temp[i]);
407 f = (1 - yy)/(1 + yy);
416 void TMVA::MethodCFMlpANN::ReadWeightsFromStream( std::istream & istr )
421 UInt_t nva(0), lclass(0);
422 istr >> nva >> lclass;
424 if (GetNvar() != nva)
425 Log() << kFATAL <<
"<ReadWeightsFromFile> mismatch in number of variables" << Endl;
429 Log() << kFATAL <<
"<ReadWeightsFromFile> mismatch in number of classes" << Endl;
433 Log() << kFATAL <<
"<ReadWeightsFromStream> reached EOF prematurely " << Endl;
436 for (UInt_t ivar=0; ivar<GetNvar(); ivar++)
437 istr >> fVarn_1.xmax[ivar] >> fVarn_1.xmin[ivar];
440 istr >> fParam_1.layerm;
443 for (Int_t i=0; i<fNlayers; i++)
delete[] fYNN[i];
447 fYNN =
new Double_t*[fParam_1.layerm];
448 for (Int_t layer=0; layer<fParam_1.layerm; layer++) {
451 istr >> fNeur_1.neuron[layer];
452 fYNN[layer] =
new Double_t[fNeur_1.neuron[layer]];
456 const Int_t nchar( 100 );
457 char* dumchar =
new char[nchar];
460 for (Int_t layer=1; layer<=fParam_1.layerm-1; layer++) {
462 Int_t nq = fNeur_1.neuron[layer]/10;
463 Int_t nr = fNeur_1.neuron[layer] - nq*10;
469 for (Int_t k=1; k<=kk; k++) {
470 Int_t jmin = 10*k - 9;
472 if (fNeur_1.neuron[layer]<jmax) jmax = fNeur_1.neuron[layer];
473 for (Int_t j=jmin; j<=jmax; j++) {
474 istr >> Ww_ref(fNeur_1.ww, layer+1, j);
476 for (Int_t i=1; i<=fNeur_1.neuron[layer-1]; i++) {
477 for (Int_t j=jmin; j<=jmax; j++) {
478 istr >> W_ref(fNeur_1.w, layer+1, j, i);
482 istr.getline( dumchar, nchar );
486 for (Int_t layer=0; layer<fParam_1.layerm; layer++) {
489 istr.getline( dumchar, nchar );
490 istr.getline( dumchar, nchar );
492 istr >> fDel_1.temp[layer];
496 if ((Int_t)GetNvar() != fNeur_1.neuron[0]) {
497 Log() << kFATAL <<
"<ReadWeightsFromFile> mismatch in zeroth layer:"
498 << GetNvar() <<
" " << fNeur_1.neuron[0] << Endl;
501 fNlayers = fParam_1.layerm;
508 Int_t TMVA::MethodCFMlpANN::DataInterface( Double_t* , Double_t* ,
510 Int_t* , Int_t* nvar,
511 Double_t* xpg, Int_t* iclass, Int_t* ikend )
519 Log() << kFATAL <<
"ERROR in MethodCFMlpANN_DataInterface zero pointer xpg" << Endl;
521 if (*nvar != (Int_t)this->GetNvar()) {
522 Log() << kFATAL <<
"ERROR in MethodCFMlpANN_DataInterface mismatch in num of variables: "
523 << *nvar <<
" " << this->GetNvar() << Endl;
527 *iclass = (int)this->GetClass( MethodCFMlpANN_nsel );
528 for (UInt_t ivar=0; ivar<this->GetNvar(); ivar++)
529 xpg[ivar] = (
double)this->GetData( MethodCFMlpANN_nsel, ivar );
531 ++MethodCFMlpANN_nsel;
539 void TMVA::MethodCFMlpANN::AddWeightsXMLTo(
void* parent )
const
541 void *wght = gTools().AddChild(parent,
"Weights");
542 gTools().AddAttr(wght,
"NVars",fParam_1.nvar);
543 gTools().AddAttr(wght,
"NClasses",fParam_1.lclass);
544 gTools().AddAttr(wght,
"NLayers",fParam_1.layerm);
545 void* minmaxnode = gTools().AddChild(wght,
"VarMinMax");
548 for (Int_t ivar=0; ivar<fParam_1.nvar; ivar++)
549 s << std::scientific << fVarn_1.xmin[ivar] <<
" " << fVarn_1.xmax[ivar] <<
" ";
550 gTools().AddRawLine( minmaxnode, s.str().c_str() );
551 void* neurons = gTools().AddChild(wght,
"NNeurons");
554 for (Int_t layer=0; layer<fParam_1.layerm; layer++)
555 n << std::scientific << fNeur_1.neuron[layer] <<
" ";
556 gTools().AddRawLine( neurons, n.str().c_str() );
557 for (Int_t layer=1; layer<fParam_1.layerm; layer++) {
558 void* layernode = gTools().AddChild(wght,
"Layer"+gTools().StringFromInt(layer));
559 gTools().AddAttr(layernode,
"NNeurons",fNeur_1.neuron[layer]);
560 void* neuronnode=NULL;
561 for (Int_t neuron=0; neuron<fNeur_1.neuron[layer]; neuron++) {
562 neuronnode = gTools().AddChild(layernode,
"Neuron"+gTools().StringFromInt(neuron));
563 stringstream weights;
564 weights.precision( 16 );
565 weights << std::scientific << Ww_ref(fNeur_1.ww, layer+1, neuron+1);
566 for (Int_t i=0; i<fNeur_1.neuron[layer-1]; i++) {
567 weights <<
" " << std::scientific << W_ref(fNeur_1.w, layer+1, neuron+1, i+1);
569 gTools().AddRawLine( neuronnode, weights.str().c_str() );
572 void* tempnode = gTools().AddChild(wght,
"LayerTemp");
574 temp.precision( 16 );
575 for (Int_t layer=0; layer<fParam_1.layerm; layer++) {
576 temp << std::scientific << fDel_1.temp[layer] <<
" ";
578 gTools().AddRawLine(tempnode, temp.str().c_str() );
583 void TMVA::MethodCFMlpANN::ReadWeightsFromXML(
void* wghtnode )
585 gTools().ReadAttr( wghtnode,
"NLayers",fParam_1.layerm );
586 void* minmaxnode = gTools().GetChild(wghtnode);
587 const char* minmaxcontent = gTools().GetContent(minmaxnode);
588 stringstream content(minmaxcontent);
589 for (UInt_t ivar=0; ivar<GetNvar(); ivar++)
590 content >> fVarn_1.xmin[ivar] >> fVarn_1.xmax[ivar];
592 for (Int_t i=0; i<fNlayers; i++)
delete[] fYNN[i];
596 fYNN =
new Double_t*[fParam_1.layerm];
597 void *layernode=gTools().GetNextChild(minmaxnode);
598 const char* neuronscontent = gTools().GetContent(layernode);
599 stringstream ncontent(neuronscontent);
600 for (Int_t layer=0; layer<fParam_1.layerm; layer++) {
603 ncontent >> fNeur_1.neuron[layer];
604 fYNN[layer] =
new Double_t[fNeur_1.neuron[layer]];
606 for (Int_t layer=1; layer<fParam_1.layerm; layer++) {
607 layernode=gTools().GetNextChild(layernode);
608 void* neuronnode=NULL;
609 neuronnode = gTools().GetChild(layernode);
610 for (Int_t neuron=0; neuron<fNeur_1.neuron[layer]; neuron++) {
611 const char* neuronweights = gTools().GetContent(neuronnode);
612 stringstream weights(neuronweights);
613 weights >> Ww_ref(fNeur_1.ww, layer+1, neuron+1);
614 for (Int_t i=0; i<fNeur_1.neuron[layer-1]; i++) {
615 weights >> W_ref(fNeur_1.w, layer+1, neuron+1, i+1);
617 neuronnode=gTools().GetNextChild(neuronnode);
620 void* tempnode=gTools().GetNextChild(layernode);
621 const char* temp = gTools().GetContent(tempnode);
622 stringstream t(temp);
623 for (Int_t layer=0; layer<fParam_1.layerm; layer++) {
624 t >> fDel_1.temp[layer];
626 fNlayers = fParam_1.layerm;
632 void TMVA::MethodCFMlpANN::PrintWeights( std::ostream & o )
const
635 o <<
"Number of vars " << fParam_1.nvar << std::endl;
636 o <<
"Output nodes " << fParam_1.lclass << std::endl;
639 for (Int_t ivar=0; ivar<fParam_1.nvar; ivar++)
640 o <<
"Var " << ivar <<
" [" << fVarn_1.xmin[ivar] <<
" - " << fVarn_1.xmax[ivar] <<
"]" << std::endl;
643 o <<
"Number of layers " << fParam_1.layerm << std::endl;
645 o <<
"Nodes per layer ";
646 for (Int_t layer=0; layer<fParam_1.layerm; layer++)
648 o << fNeur_1.neuron[layer] <<
" ";
652 for (Int_t layer=1; layer<=fParam_1.layerm-1; layer++) {
654 Int_t nq = fNeur_1.neuron[layer]/10;
655 Int_t nr = fNeur_1.neuron[layer] - nq*10;
661 for (Int_t k=1; k<=kk; k++) {
662 Int_t jmin = 10*k - 9;
665 if (fNeur_1.neuron[layer]<jmax) jmax = fNeur_1.neuron[layer];
666 for (j=jmin; j<=jmax; j++) {
669 o << Ww_ref(fNeur_1.ww, layer+1, j) <<
" ";
674 for (i=1; i<=fNeur_1.neuron[layer-1]; i++) {
675 for (j=jmin; j<=jmax; j++) {
677 o << W_ref(fNeur_1.w, layer+1, j, i) <<
" ";
686 for (Int_t layer=0; layer<fParam_1.layerm; layer++) {
687 o <<
"Del.temp in layer " << layer <<
" : " << fDel_1.temp[layer] << std::endl;
693 void TMVA::MethodCFMlpANN::MakeClassSpecific( std::ostream& fout,
const TString& className )
const
696 fout <<
" // not implemented for class: \"" << className <<
"\"" << std::endl;
697 fout <<
"};" << std::endl;
703 void TMVA::MethodCFMlpANN::MakeClassSpecificHeader( std::ostream& ,
const TString& )
const
713 void TMVA::MethodCFMlpANN::GetHelpMessage()
const
716 Log() << gTools().Color(
"bold") <<
"--- Short description:" << gTools().Color(
"reset") << Endl;
718 Log() <<
"<None>" << Endl;
720 Log() << gTools().Color(
"bold") <<
"--- Performance optimisation:" << gTools().Color(
"reset") << Endl;
722 Log() <<
"<None>" << Endl;
724 Log() << gTools().Color(
"bold") <<
"--- Performance tuning via configuration options:" << gTools().Color(
"reset") << Endl;
726 Log() <<
"<None>" << Endl;