// Class: ReadMLP // Automatically generated by MethodBase::MakeClass // /* configuration options ===================================================== #GEN -*-*-*-*-*-*-*-*-*-*-*- general info -*-*-*-*-*-*-*-*-*-*-*- Method : MLP::MLP TMVA Release : 4.2.1 [262657] ROOT Release : 6.41/01 [403713] Creator : root Date : Tue May 19 20:08:53 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: 4000 Analysis type : [Classification] #OPT -*-*-*-*-*-*-*-*-*-*-*-*- options -*-*-*-*-*-*-*-*-*-*-*-*- # Set by User: NCycles: "1000" [Number of training cycles] HiddenLayers: "N+5,5" [Specification of hidden layer architecture] NeuronType: "tanh" [Neuron activation function type] EstimatorType: "MSE" [MSE (Mean Square Estimator) for Gaussian Likelihood or CE(Cross-Entropy) for Bernoulli Likelihood] V: "False" [Verbose output (short form of "VerbosityLevel" below - overrides the latter one)] H: "False" [Print method-specific help message] TestRate: "5" [Test for overtraining performed at each #th epochs] # Default: RandomSeed: "1" [Random seed for initial synapse weights (0 means unique seed for each run; default value '1')] NeuronInputType: "sum" [Neuron input function type] VerbosityLevel: "Default" [Verbosity level] VarTransform: "None" [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)"] 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)] TrainingMethod: "BP" [Train with Back-Propagation (BP), BFGS Algorithm (BFGS), or Genetic Algorithm (GA - slower and worse)] 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)] UseRegulator: "False" [Use regulator to avoid over-training] 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 var1 var1 var1 'F' [-4.05916023254,3.26447582245] var2 var2 var2 Variable 2 'F' [-3.68905711174,3.78774046898] var3 var3 var3 Variable 3 units 'F' [-3.6296145916,3.91998791695] var4 var4 var4 Variable 4 units 'F' [-4.84856987,4.3625254631] NSpec 0 ============================================================================ */ #include #include #include #include #include #ifndef IClassifierReader__def #define IClassifierReader__def class IClassifierReader { public: // constructor IClassifierReader() : fStatusIsClean( true ) {} virtual ~IClassifierReader() {} // return classifier response virtual std::vector GetMulticlassValues( const std::vector& inputValues ) const = 0; // returns classifier status bool IsStatusClean() const { return fStatusIsClean; } protected: bool fStatusIsClean; }; #endif class ReadMLP : public IClassifierReader { public: // constructor ReadMLP( std::vector& theInputVars ) : IClassifierReader(), fClassName( "ReadMLP" ), fNvars( 4 ) { // the training input variables const char* inputVars[] = { "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] = 0; fVmax[0] = 0; fVmin[1] = 0; fVmax[1] = 0; fVmin[2] = 0; fVmax[2] = 0; fVmin[3] = 0; fVmax[3] = 0; // initialize input variable types fType[0] = 'F'; fType[1] = 'F'; fType[2] = 'F'; fType[3] = 'F'; // initialize constants Initialize(); } // destructor virtual ~ReadMLP() { Clear(); // method-specific } // the classifier response // "inputValues" is a vector of input values in the same order as the // variables given to the constructor std::vector GetMulticlassValues( const std::vector& inputValues ) const override; private: // method-specific destructor void Clear(); // 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(); std::vector GetMulticlassValues__( 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[6][10]; // weight matrix from layer 1 to 2 double fWeightMatrix2to3[4][6]; // weight matrix from layer 2 to 3 }; inline void ReadMLP::Initialize() { // build network structure // weight matrix from layer 0 to 1 fWeightMatrix0to1[0][0] = 2.04587196239276; fWeightMatrix0to1[1][0] = 1.7184552569469; fWeightMatrix0to1[2][0] = 0.293516801945702; fWeightMatrix0to1[3][0] = 0.299905309446156; fWeightMatrix0to1[4][0] = -2.08055527765318; fWeightMatrix0to1[5][0] = -3.53270980852752; fWeightMatrix0to1[6][0] = -0.205002184993538; fWeightMatrix0to1[7][0] = 0.902233419327913; fWeightMatrix0to1[8][0] = -0.401386711694818; fWeightMatrix0to1[0][1] = -0.402641296947939; fWeightMatrix0to1[1][1] = 1.22156743373212; fWeightMatrix0to1[2][1] = 0.271253032982175; fWeightMatrix0to1[3][1] = -1.70274506310016; fWeightMatrix0to1[4][1] = -1.59224030893546; fWeightMatrix0to1[5][1] = 0.587008249856246; fWeightMatrix0to1[6][1] = -0.362140320493828; fWeightMatrix0to1[7][1] = -0.499628836972127; fWeightMatrix0to1[8][1] = 3.58334943574684; fWeightMatrix0to1[0][2] = 0.944305711713039; fWeightMatrix0to1[1][2] = 0.658601185810607; fWeightMatrix0to1[2][2] = -1.19120482669963; fWeightMatrix0to1[3][2] = -0.429170556377554; fWeightMatrix0to1[4][2] = -0.919374675971291; fWeightMatrix0to1[5][2] = -0.136230528087468; fWeightMatrix0to1[6][2] = -1.53616163432236; fWeightMatrix0to1[7][2] = 0.105405855269459; fWeightMatrix0to1[8][2] = -0.291862968331516; fWeightMatrix0to1[0][3] = -3.0483209050555; fWeightMatrix0to1[1][3] = -2.89942635067549; fWeightMatrix0to1[2][3] = 0.124298345709395; fWeightMatrix0to1[3][3] = 3.19007177877009; fWeightMatrix0to1[4][3] = 3.55587275728083; fWeightMatrix0to1[5][3] = 0.192524965044861; fWeightMatrix0to1[6][3] = 1.20682884606561; fWeightMatrix0to1[7][3] = 0.642406217170102; fWeightMatrix0to1[8][3] = 0.125639905845052; fWeightMatrix0to1[0][4] = -1.60675486916398; fWeightMatrix0to1[1][4] = 1.95689895800082; fWeightMatrix0to1[2][4] = -1.47171296244331; fWeightMatrix0to1[3][4] = -0.187124018155066; fWeightMatrix0to1[4][4] = 2.0626878642301; fWeightMatrix0to1[5][4] = 2.61598908248355; fWeightMatrix0to1[6][4] = 1.21466987126719; fWeightMatrix0to1[7][4] = -0.568344112759897; fWeightMatrix0to1[8][4] = -3.23034696337304; // weight matrix from layer 1 to 2 fWeightMatrix1to2[0][0] = -0.248438727134338; fWeightMatrix1to2[1][0] = 0.969621731607441; fWeightMatrix1to2[2][0] = 0.113348760525155; fWeightMatrix1to2[3][0] = 0.511889799449209; fWeightMatrix1to2[4][0] = -0.203581280563983; fWeightMatrix1to2[0][1] = 0.107789952450882; fWeightMatrix1to2[1][1] = -0.968919093567054; fWeightMatrix1to2[2][1] = 0.420868391155964; fWeightMatrix1to2[3][1] = 1.16089638755745; fWeightMatrix1to2[4][1] = -1.75455588239395; fWeightMatrix1to2[0][2] = -0.87691013636618; fWeightMatrix1to2[1][2] = 0.909324017987598; fWeightMatrix1to2[2][2] = -0.565968834909648; fWeightMatrix1to2[3][2] = -0.184426757071435; fWeightMatrix1to2[4][2] = -0.108250022926436; fWeightMatrix1to2[0][3] = -0.344016303090561; fWeightMatrix1to2[1][3] = -1.29034278088035; fWeightMatrix1to2[2][3] = 0.122790953748625; fWeightMatrix1to2[3][3] = 0.479176750651281; fWeightMatrix1to2[4][3] = 0.472408893207853; fWeightMatrix1to2[0][4] = 0.0512308201115492; fWeightMatrix1to2[1][4] = -1.55755396070629; fWeightMatrix1to2[2][4] = -0.587222208120465; fWeightMatrix1to2[3][4] = -0.132099876065672; fWeightMatrix1to2[4][4] = 3.08948618510028; fWeightMatrix1to2[0][5] = -0.364680674980976; fWeightMatrix1to2[1][5] = -1.40210136765035; fWeightMatrix1to2[2][5] = 0.0340530236600099; fWeightMatrix1to2[3][5] = 3.96933309690439; fWeightMatrix1to2[4][5] = 0.0529201079577534; fWeightMatrix1to2[0][6] = -0.3000117349709; fWeightMatrix1to2[1][6] = -1.2789980183701; fWeightMatrix1to2[2][6] = -0.695014857348084; fWeightMatrix1to2[3][6] = 0.831423777698454; fWeightMatrix1to2[4][6] = -0.0850448850880283; fWeightMatrix1to2[0][7] = 0.465535906155072; fWeightMatrix1to2[1][7] = -1.98064520432565; fWeightMatrix1to2[2][7] = -0.456006394132539; fWeightMatrix1to2[3][7] = -0.169053472516111; fWeightMatrix1to2[4][7] = -0.592389189284173; fWeightMatrix1to2[0][8] = 0.389825288951952; fWeightMatrix1to2[1][8] = -0.479084197498184; fWeightMatrix1to2[2][8] = -0.443853758947049; fWeightMatrix1to2[3][8] = -3.92067440556955; fWeightMatrix1to2[4][8] = 0.00150309561898216; fWeightMatrix1to2[0][9] = -0.637245382109332; fWeightMatrix1to2[1][9] = -3.03803439399876; fWeightMatrix1to2[2][9] = -0.518147136066482; fWeightMatrix1to2[3][9] = -2.87353063749408; fWeightMatrix1to2[4][9] = -1.82253581899056; // weight matrix from layer 2 to 3 fWeightMatrix2to3[0][0] = 1.31936433339808; fWeightMatrix2to3[1][0] = -0.087452524073475; fWeightMatrix2to3[2][0] = 1.0718861210472; fWeightMatrix2to3[3][0] = -4.54113970127371; fWeightMatrix2to3[0][1] = -1.77363882568221; fWeightMatrix2to3[1][1] = -3.26706638308021; fWeightMatrix2to3[2][1] = -0.621775684607036; fWeightMatrix2to3[3][1] = 2.88898040243586; fWeightMatrix2to3[0][2] = -1.55565700764996; fWeightMatrix2to3[1][2] = -1.31568684239611; fWeightMatrix2to3[2][2] = 2.56811260346992; fWeightMatrix2to3[3][2] = 1.52116917799443; fWeightMatrix2to3[0][3] = 1.4788104052447; fWeightMatrix2to3[1][3] = 1.42052296877079; fWeightMatrix2to3[2][3] = 1.0141212441653; fWeightMatrix2to3[3][3] = -6.20043486064954; fWeightMatrix2to3[0][4] = 2.84714637647587; fWeightMatrix2to3[1][4] = -1.60032554918188; fWeightMatrix2to3[2][4] = -1.95535516282736; fWeightMatrix2to3[3][4] = 0.311320438796763; fWeightMatrix2to3[0][5] = 0.614772476001639; fWeightMatrix2to3[1][5] = -1.06567251259994; fWeightMatrix2to3[2][5] = 0.359269953903194; fWeightMatrix2to3[3][5] = 2.11794423882523; } inline double ReadMLP::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 {{}}; std::array fWeights3 {{}}; fWeights1.back() = 1.; fWeights2.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<5; 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<5; o++) { fWeights2[o] = ActivationFnc(fWeights2[o]); } // loop over o // layer 2 to 3 for (int o=0; o<4; o++) { std::array buffer; // no need to initialise for (int i=0; i<6; i++) { buffer[i] = fWeightMatrix2to3[o][i] * fWeights2[i]; } // loop over i for (int i=0; i<6; i++) { fWeights3[o] += buffer[i]; } // loop over i } // loop over o for (int o=0; o<4; o++) { fWeights3[o] = OutputActivationFnc(fWeights3[o]); } // loop over o return fWeights3[0]; } double ReadMLP::ActivationFnc(double x) const { // hyperbolic tan return tanh(x); } double ReadMLP::OutputActivationFnc(double x) const { // identity return x; } // Clean up inline void ReadMLP::Clear() { } inline std::vector ReadMLP::GetMulticlassValues( const std::vector& inputValues ) const { // classifier response value std::vector retval; // classifier response, sanity check first if (!IsStatusClean()) { std::cout << "Problem in class \"" << fClassName << "\": cannot return classifier response" << " because status is dirty" << std::endl; } else { retval = GetMulticlassValues__( inputValues ); } return retval; }