// Class: ReadMLPBNN // Automatically generated by MethodBase::MakeClass // /* configuration options ===================================================== #GEN -*-*-*-*-*-*-*-*-*-*-*- general info -*-*-*-*-*-*-*-*-*-*-*- Method : MLP::MLPBNN TMVA Release : 4.2.1 [262657] ROOT Release : 6.41/01 [403713] Creator : root Date : Tue May 19 20:08:03 2026 Host : Linux d4f37374721b 4.18.0-553.117.1.el8_10.x86_64 #1 SMP Sun Apr 5 23:14:32 EDT 2026 x86_64 GNU/Linux Dir : /github/home/master/notebooks Training events: 2000 Analysis type : [Classification] #OPT -*-*-*-*-*-*-*-*-*-*-*-*- options -*-*-*-*-*-*-*-*-*-*-*-*- # Set by User: NCycles: "60" [Number of training cycles] HiddenLayers: "N+5" [Specification of hidden layer architecture] NeuronType: "tanh" [Neuron activation function type] V: "False" [Verbose output (short form of "VerbosityLevel" below - overrides the latter one)] VarTransform: "N" [List of variable transformations performed before training, e.g., "D_Background,P_Signal,G,N_AllClasses" for: "Decorrelation, PCA-transformation, Gaussianisation, Normalisation, each for the given class of events ('AllClasses' denotes all events of all classes, if no class indication is given, 'All' is assumed)"] H: "True" [Print method-specific help message] TrainingMethod: "BFGS" [Train with Back-Propagation (BP), BFGS Algorithm (BFGS), or Genetic Algorithm (GA - slower and worse)] TestRate: "5" [Test for overtraining performed at each #th epochs] UseRegulator: "True" [Use regulator to avoid over-training] # Default: RandomSeed: "1" [Random seed for initial synapse weights (0 means unique seed for each run; default value '1')] EstimatorType: "CE" [MSE (Mean Square Estimator) for Gaussian Likelihood or CE(Cross-Entropy) for Bernoulli Likelihood] NeuronInputType: "sum" [Neuron input function type] VerbosityLevel: "Default" [Verbosity level] CreateMVAPdfs: "False" [Create PDFs for classifier outputs (signal and background)] IgnoreNegWeightsInTraining: "False" [Events with negative weights are ignored in the training (but are included for testing and performance evaluation)] LearningRate: "2.000000e-02" [ANN learning rate parameter] DecayRate: "1.000000e-02" [Decay rate for learning parameter] EpochMonitoring: "False" [Provide epoch-wise monitoring plots according to TestRate (caution: causes big ROOT output file!)] Sampling: "1.000000e+00" [Only 'Sampling' (randomly selected) events are trained each epoch] SamplingEpoch: "1.000000e+00" [Sampling is used for the first 'SamplingEpoch' epochs, afterwards, all events are taken for training] SamplingImportance: "1.000000e+00" [ The sampling weights of events in epochs which successful (worse estimator than before) are multiplied with SamplingImportance, else they are divided.] SamplingTraining: "True" [The training sample is sampled] SamplingTesting: "False" [The testing sample is sampled] ResetStep: "50" [How often BFGS should reset history] Tau: "3.000000e+00" [LineSearch "size step"] BPMode: "sequential" [Back-propagation learning mode: sequential or batch] BatchSize: "-1" [Batch size: number of events/batch, only set if in Batch Mode, -1 for BatchSize=number_of_events] ConvergenceImprove: "1.000000e-30" [Minimum improvement which counts as improvement (<0 means automatic convergence check is turned off)] ConvergenceTests: "-1" [Number of steps (without improvement) required for convergence (<0 means automatic convergence check is turned off)] UpdateLimit: "10000" [Maximum times of regulator update] CalculateErrors: "False" [Calculates inverse Hessian matrix at the end of the training to be able to calculate the uncertainties of an MVA value] WeightRange: "1.000000e+00" [Take the events for the estimator calculations from small deviations from the desired value to large deviations only over the weight range] ## #VAR -*-*-*-*-*-*-*-*-*-*-*-* variables *-*-*-*-*-*-*-*-*-*-*-*- NVar 4 var1+var2 myvar1 myvar1 myvar1 'F' [-9.23118686676,7.07192516327] var1-var2 myvar2 myvar2 Expression 2 'F' [-3.70671987534,4.02912044525] var3 var3 var3 Variable 3 units 'F' [-5.15695810318,4.15070819855] var4 var4 var4 Variable 4 units 'F' [-6.31600189209,4.52105665207] NSpec 2 var1*2 spec1 spec1 Spectator 1 units 'F' [-9.63254642487,9.05203056335] var1*3 spec2 spec2 Spectator 2 units 'F' [-14.4488201141,13.578045845] ============================================================================ */ #include #include #include #include #include #ifndef IClassifierReader__def #define IClassifierReader__def class IClassifierReader { public: // constructor IClassifierReader() : fStatusIsClean( true ) {} virtual ~IClassifierReader() {} // return classifier response virtual double GetMvaValue( const std::vector& inputValues ) const = 0; // returns classifier status bool IsStatusClean() const { return fStatusIsClean; } protected: bool fStatusIsClean; }; #endif class ReadMLPBNN : public IClassifierReader { public: // constructor ReadMLPBNN( std::vector& theInputVars ) : IClassifierReader(), fClassName( "ReadMLPBNN" ), fNvars( 4 ) { // the training input variables const char* inputVars[] = { "var1+var2", "var1-var2", "var3", "var4" }; // sanity checks if (theInputVars.size() <= 0) { std::cout << "Problem in class \"" << fClassName << "\": empty input vector" << std::endl; fStatusIsClean = false; } if (theInputVars.size() != fNvars) { std::cout << "Problem in class \"" << fClassName << "\": mismatch in number of input values: " << theInputVars.size() << " != " << fNvars << std::endl; fStatusIsClean = false; } // validate input variables for (size_t ivar = 0; ivar < theInputVars.size(); ivar++) { if (theInputVars[ivar] != inputVars[ivar]) { std::cout << "Problem in class \"" << fClassName << "\": mismatch in input variable names" << std::endl << " for variable [" << ivar << "]: " << theInputVars[ivar].c_str() << " != " << inputVars[ivar] << std::endl; fStatusIsClean = false; } } // initialize min and max vectors (for normalisation) fVmin[0] = -1; fVmax[0] = 1; fVmin[1] = -1; fVmax[1] = 1; fVmin[2] = -1; fVmax[2] = 1; fVmin[3] = -1; fVmax[3] = 0.99999988079071; // initialize input variable types fType[0] = 'F'; fType[1] = 'F'; fType[2] = 'F'; fType[3] = 'F'; // initialize constants Initialize(); // initialize transformation InitTransform(); } // destructor virtual ~ReadMLPBNN() { Clear(); // method-specific } // the classifier response // "inputValues" is a vector of input values in the same order as the // variables given to the constructor double GetMvaValue( const std::vector& inputValues ) const override; private: // method-specific destructor void Clear(); // input variable transformation double fOff_1[3][4]; double fScal_1[3][4]; void InitTransform_1(); void Transform_1( std::vector & iv, int sigOrBgd ) const; void InitTransform(); void Transform( std::vector & iv, int sigOrBgd ) const; // common member variables const char* fClassName; const size_t fNvars; size_t GetNvar() const { return fNvars; } char GetType( int ivar ) const { return fType[ivar]; } // normalisation of input variables double fVmin[4]; double fVmax[4]; double NormVariable( double x, double xmin, double xmax ) const { // normalise to output range: [-1, 1] return 2*(x - xmin)/(xmax - xmin) - 1.0; } // type of input variable: 'F' or 'I' char fType[4]; // initialize internal variables void Initialize(); double GetMvaValue__( const std::vector& inputValues ) const; // private members (method specific) double ActivationFnc(double x) const; double OutputActivationFnc(double x) const; double fWeightMatrix0to1[10][5]; // weight matrix from layer 0 to 1 double fWeightMatrix1to2[1][10]; // weight matrix from layer 1 to 2 }; inline void ReadMLPBNN::Initialize() { // build network structure // weight matrix from layer 0 to 1 fWeightMatrix0to1[0][0] = 1.23868923136956; fWeightMatrix0to1[1][0] = 1.98860658225881; fWeightMatrix0to1[2][0] = 0.758104184750467; fWeightMatrix0to1[3][0] = 0.084299165838454; fWeightMatrix0to1[4][0] = -1.94648162535036; fWeightMatrix0to1[5][0] = -1.25794223547187; fWeightMatrix0to1[6][0] = -0.97011596216884; fWeightMatrix0to1[7][0] = 2.21602165727854; fWeightMatrix0to1[8][0] = -2.20299736255649; fWeightMatrix0to1[0][1] = 0.00389376933665004; fWeightMatrix0to1[1][1] = -1.40560909769445; fWeightMatrix0to1[2][1] = -0.503302789390002; fWeightMatrix0to1[3][1] = -0.761022766317438; fWeightMatrix0to1[4][1] = -0.31809321673524; fWeightMatrix0to1[5][1] = -1.08942972886825; fWeightMatrix0to1[6][1] = 0.452840901426247; fWeightMatrix0to1[7][1] = -0.0165791560414546; fWeightMatrix0to1[8][1] = 1.44137870099894; fWeightMatrix0to1[0][2] = 0.649451776467967; fWeightMatrix0to1[1][2] = 1.36682311992743; fWeightMatrix0to1[2][2] = -0.289521944271437; fWeightMatrix0to1[3][2] = -0.749980901255834; fWeightMatrix0to1[4][2] = -0.549286923179016; fWeightMatrix0to1[5][2] = 0.546987422955455; fWeightMatrix0to1[6][2] = -1.92626793483836; fWeightMatrix0to1[7][2] = -0.465378229875171; fWeightMatrix0to1[8][2] = 1.08701450981352; fWeightMatrix0to1[0][3] = -1.84259869174721; fWeightMatrix0to1[1][3] = -1.55775756901566; fWeightMatrix0to1[2][3] = 0.592406179139811; fWeightMatrix0to1[3][3] = 1.85545657971959; fWeightMatrix0to1[4][3] = 4.36388536504866; fWeightMatrix0to1[5][3] = 1.05521441872045; fWeightMatrix0to1[6][3] = -0.0847026518742384; fWeightMatrix0to1[7][3] = 0.276311023750612; fWeightMatrix0to1[8][3] = 0.768822088349441; fWeightMatrix0to1[0][4] = -0.0738761208228532; fWeightMatrix0to1[1][4] = 2.243739100749; fWeightMatrix0to1[2][4] = -0.982916751706231; fWeightMatrix0to1[3][4] = 0.639188052279329; fWeightMatrix0to1[4][4] = -0.704824209910524; fWeightMatrix0to1[5][4] = 0.0852736811831088; fWeightMatrix0to1[6][4] = 0.925862641875358; fWeightMatrix0to1[7][4] = 1.220557638785; fWeightMatrix0to1[8][4] = -0.175930237705895; // weight matrix from layer 1 to 2 fWeightMatrix1to2[0][0] = -2.43345650766201; fWeightMatrix1to2[0][1] = 0.662236010356895; fWeightMatrix1to2[0][2] = 0.0723309248759; fWeightMatrix1to2[0][3] = 1.10422862347865; fWeightMatrix1to2[0][4] = 5.02623091976506; fWeightMatrix1to2[0][5] = 2.32106210861871; fWeightMatrix1to2[0][6] = 1.97017798417512; fWeightMatrix1to2[0][7] = -1.18063267078848; fWeightMatrix1to2[0][8] = 0.91319899773434; fWeightMatrix1to2[0][9] = -1.21460311666692; } inline double ReadMLPBNN::GetMvaValue__( const std::vector& inputValues ) const { if (inputValues.size() != (unsigned int)4) { std::cout << "Input vector needs to be of size " << 4 << std::endl; return 0; } std::array fWeights1 {{}}; std::array fWeights2 {{}}; fWeights1.back() = 1.; // layer 0 to 1 for (int o=0; o<9; o++) { std::array buffer; // no need to initialise for (int i = 0; i<5 - 1; i++) { buffer[i] = fWeightMatrix0to1[o][i] * inputValues[i]; } // loop over i buffer.back() = fWeightMatrix0to1[o][4]; for (int i=0; i<5; i++) { fWeights1[o] += buffer[i]; } // loop over i } // loop over o for (int o=0; o<9; o++) { fWeights1[o] = ActivationFnc(fWeights1[o]); } // loop over o // layer 1 to 2 for (int o=0; o<1; o++) { std::array buffer; // no need to initialise for (int i=0; i<10; i++) { buffer[i] = fWeightMatrix1to2[o][i] * fWeights1[i]; } // loop over i for (int i=0; i<10; i++) { fWeights2[o] += buffer[i]; } // loop over i } // loop over o for (int o=0; o<1; o++) { fWeights2[o] = OutputActivationFnc(fWeights2[o]); } // loop over o return fWeights2[0]; } double ReadMLPBNN::ActivationFnc(double x) const { // hyperbolic tan return tanh(x); } double ReadMLPBNN::OutputActivationFnc(double x) const { // sigmoid return 1.0/(1.0+exp(-x)); } // Clean up inline void ReadMLPBNN::Clear() { } inline double ReadMLPBNN::GetMvaValue( const std::vector& inputValues ) const { // classifier response value double retval = 0; // classifier response, sanity check first if (!IsStatusClean()) { std::cout << "Problem in class \"" << fClassName << "\": cannot return classifier response" << " because status is dirty" << std::endl; } else { std::vector iV(inputValues); Transform( iV, -1 ); retval = GetMvaValue__( iV ); } return retval; } //_______________________________________________________________________ inline void ReadMLPBNN::InitTransform_1() { double fMin_1[3][4]; double fMax_1[3][4]; // Normalization transformation, initialisation fMin_1[0][0] = -5.16234207153; fMax_1[0][0] = 5.78214550018; fScal_1[0][0] = 2.0/(fMax_1[0][0]-fMin_1[0][0]); fOff_1[0][0] = fMin_1[0][0]*fScal_1[0][0]+1.; fMin_1[1][0] = -9.23118686676; fMax_1[1][0] = 7.07192516327; fScal_1[1][0] = 2.0/(fMax_1[1][0]-fMin_1[1][0]); fOff_1[1][0] = fMin_1[1][0]*fScal_1[1][0]+1.; fMin_1[2][0] = -9.23118686676; fMax_1[2][0] = 7.07192516327; fScal_1[2][0] = 2.0/(fMax_1[2][0]-fMin_1[2][0]); fOff_1[2][0] = fMin_1[2][0]*fScal_1[2][0]+1.; fMin_1[0][1] = -3.70671987534; fMax_1[0][1] = 4.02912044525; fScal_1[0][1] = 2.0/(fMax_1[0][1]-fMin_1[0][1]); fOff_1[0][1] = fMin_1[0][1]*fScal_1[0][1]+1.; fMin_1[1][1] = -3.45779681206; fMax_1[1][1] = 3.45797157288; fScal_1[1][1] = 2.0/(fMax_1[1][1]-fMin_1[1][1]); fOff_1[1][1] = fMin_1[1][1]*fScal_1[1][1]+1.; fMin_1[2][1] = -3.70671987534; fMax_1[2][1] = 4.02912044525; fScal_1[2][1] = 2.0/(fMax_1[2][1]-fMin_1[2][1]); fOff_1[2][1] = fMin_1[2][1]*fScal_1[2][1]+1.; fMin_1[0][2] = -3.18263268471; fMax_1[0][2] = 3.6047577858; fScal_1[0][2] = 2.0/(fMax_1[0][2]-fMin_1[0][2]); fOff_1[0][2] = fMin_1[0][2]*fScal_1[0][2]+1.; fMin_1[1][2] = -5.15695810318; fMax_1[1][2] = 4.15070819855; fScal_1[1][2] = 2.0/(fMax_1[1][2]-fMin_1[1][2]); fOff_1[1][2] = fMin_1[1][2]*fScal_1[1][2]+1.; fMin_1[2][2] = -5.15695810318; fMax_1[2][2] = 4.15070819855; fScal_1[2][2] = 2.0/(fMax_1[2][2]-fMin_1[2][2]); fOff_1[2][2] = fMin_1[2][2]*fScal_1[2][2]+1.; fMin_1[0][3] = -2.94924092293; fMax_1[0][3] = 3.84948801994; fScal_1[0][3] = 2.0/(fMax_1[0][3]-fMin_1[0][3]); fOff_1[0][3] = fMin_1[0][3]*fScal_1[0][3]+1.; fMin_1[1][3] = -6.31600189209; fMax_1[1][3] = 4.52105665207; fScal_1[1][3] = 2.0/(fMax_1[1][3]-fMin_1[1][3]); fOff_1[1][3] = fMin_1[1][3]*fScal_1[1][3]+1.; fMin_1[2][3] = -6.31600189209; fMax_1[2][3] = 4.52105665207; fScal_1[2][3] = 2.0/(fMax_1[2][3]-fMin_1[2][3]); fOff_1[2][3] = fMin_1[2][3]*fScal_1[2][3]+1.; } //_______________________________________________________________________ inline void ReadMLPBNN::Transform_1( std::vector& iv, int cls) const { // Normalization transformation if (cls < 0 || cls > 2) { if (2 > 1 ) cls = 2; else cls = 2; } const int nVar = 4; // get indices of used variables // define the indices of the variables which are transformed by this transformation static std::vector indicesGet; static std::vector indicesPut; if ( indicesGet.empty() ) { indicesGet.reserve(fNvars); indicesGet.push_back( 0); indicesGet.push_back( 1); indicesGet.push_back( 2); indicesGet.push_back( 3); } if ( indicesPut.empty() ) { indicesPut.reserve(fNvars); indicesPut.push_back( 0); indicesPut.push_back( 1); indicesPut.push_back( 2); indicesPut.push_back( 3); } static std::vector dv; dv.resize(nVar); for (int ivar=0; ivar& iv, int sigOrBgd ) const { Transform_1( iv, sigOrBgd ); }