## 3 Materials and Methods
### Neural Network Modeling  
This section describes the use of biologically inspired optimization algorithms for training MLP neural networks. An MLP neural network architecture consists of an input layer, an output layer, and one or more hidden layers, and each of these layers contains a certain number of neurons. Adjacent layers of the MLP are fully connected, and each connection between two neurons has an associated weight. The values of weights and biases are adjusted in a supervised manner using an optimization algorithm. Since we are normalizing the data set in the range [\(-\)0.9, 0.9], we choose the hyperbolic tangent activation function (1) for each neuron:  
\[tanh(x)=\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}} \tag{1}\]  
Figure 1: Illustration of the main steps of our approach. We use the notation [_ni-nh1_-... -_no_] to describe the architecture of an MLP, where _ni_ represents the number of neurons in the input layer, _nh1_ represents the number of neurons in the first hidden layer (the number of neurons of this layer is illustrated in bold), and _no_ represents the number of neurons in the output layer. For example, the notation [7-**5-**2**] describes an MLP with seven inputs, five neurons in the hidden layer, and two outputs. In this paper, we use different algorithms to optimize the architecture, weights, and biases of MLP neural networks to obtain networks with the best prediction performance on the MMA data set. A population-based algorithm uses a set of candidate solutions (i.e., individuals) that evolve through an iterative process. Individuals in the population are created or modified using different operators specific to the algorithm. In our case, a solution represents a neural network, and a population is equivalent to a set of neural networks. An individual's objective function is evaluated using the root mean square error (RMSE) (2) of the MLP on the training or testing data set. Therefore, minimizing the RMSE value is the primary goal of the algorithm:  
\[RMSE=\sqrt{\frac{1}{ns\cdot no}\cdot\sum_{i=0}^{ns}\sum_{j=0}^{no}\bigl{(}d_{ ij}-y_{ij}\bigr{)}^{2}} \tag{2}\]  
where _ns_ is the number of samples in the training or testing data set, _no_ is the number of outputs of the MLP, _dij_ is the desired MLP _j_th output at _i_th training or testing sample, and _yij_ is the actual MLP _j_th output at _i_th training or testing sample. A coding and decoding step is required in training MLP neural networks with such algorithms. The coding step consists of extracting information from an MLP structure and organizing it into a specific representation compatible with a candidate solution used by an algorithm. In this paper, we code the solution as a fixed-length one-dimensional array of real values. A general case of an MLP structure and its associated coded solution is illustrated in Figure 2.  
The locations in the solution array illustrated in Figure 2 are described as follows:  
* _nl_: the number of hidden layers of the neural network. This number can be different from one network to another and is an integer value in the range [_nlmin_, _nlmax_];
* _nh1_: the number of neurons in the first hidden layer. _nh1_ is an integer value in the range [_nh1 min_, _nh1 max_];
* _nh2_: the number of neurons in the second hidden layer. _nh2_ is an integer value in the range [_nh2 min_, _nh2 max_]. This location is only used when _nl_ = 2;  
Figure 2: A general structure of an MLP and its associated coded solution. * \(w_{i\text{-}h1}\): the weight values associated with the connections between the neurons of the input layer (\(i\)) and the neurons of the first hidden layer (\(h1\)). These locations always exist in the solution array because all networks we use have at least one hidden layer;
* \(w_{h1\text{-}h2}\): the weight values associated with the connections between the neurons of the first hidden layer (\(h1\)) and the neurons of the second hidden layer (\(h2\)).