Morris method

The Morris method is a so-called one-at-a-time (OAT) screening method that is known to achieve a good trade-off between accuracy and efficiency, and can serve to identify the few important factors in models with many factors. The method is based on calculating for each input a number of incremental ratios, called Elementary Effects (EE), from which basic statistics are computed to derive sensitivity information [40].

For each input \(X_{k}\), the elementary effect is computed as:

\[EE_{k} = \frac{Y(X_{1}, ..., X_{k}+\Delta, ..., X_{d})-Y(X_{1}, ..., X_{k}, ..., X_{d})}{\Delta}\]

where \(\Delta\) is chosen so that \(X_{k}+\Delta\) is still in the allowable domain for every dimension k.

The key idea of the original Morris method (current implementation) is to initiate trajectories from various “nominal” points \(X\) randomly selected over the grid and then gradually advancing one \(\Delta\) at a time between each model evaluation (one at a time OAT design), along a different dimension of the parameter space selected randomly (see an example of 5 trajectories in a 2D space on the left plot of the figure below). For \(r\) trajectories (usually set \(r\) between 5 and 50), the number of simulations required is \(r (d+1)\).

The following sensitivity indices are computed from the elementary effects:

\[\mu_{k}^{\star} = \frac{1}{r} \sum_{i=1}^{r} \vert EE_{k}^{r} \vert\]
\[\sigma_{k} = \sqrt{ \frac{1}{r} \sum_{i=1}^{r} \left( EE_{k}^{r} - \mu_{k} \right)^{2}}\]

These indices allow differentiation between three groups of inputs (see example in the right plot on the figure below):

  • Parameters with non-influential effects, i.e., the parameters that have relatively small values of both \(\mu_{k}^{\star}\) and \(\sigma_{k}\).

  • Parameters with linear and/or additive effects, i.e., the parameters that have a relatively large value of \(\mu_{k}^{\star}\) and relatively small value of \(\sigma_{k}\) (the magnitude of the effect \(\mu_{k}^{\star}\) is consistently large, regardless of the other parameter values, i.e., no interaction).

  • Parameters with nonlinear and/or interaction effects, i.e., the parameters that have a relatively small value of \(\mu_{k}^{\star}\) and a relatively large value of \(\sigma_{k}\) (large value of \(\sigma_{k}\) indicates that the effect can be large or small depending on the other values of parameters at which the model is evaluated, indicates potential interaction between parameters).

../_images/morris_indices.png

Morris Class

The MorrisSensitivity class is imported using the following command:

>>> from UQpy.sensitivity.MorrisSensitivity import MorrisSensitivity

Methods

class MorrisSensitivity(runmodel_object, distributions, n_levels, delta=None, random_state=None, n_trajectories=None, maximize_dispersion=False)[source]

Compute sensitivity indices based on the Morris screening method.

Parameters:
  • runmodel_object (RunModel) – The computational model. It should be of type RunModel. The output QoI can be a scalar or vector of length ny, then the sensitivity indices of all ny outputs are computed independently.

  • distributions (Union[JointIndependent, list, tuple]) – List of Distribution objects corresponding to each random variable, or JointIndependent object (multivariate RV with independent marginals).

  • n_levels (int) – Number of levels that define the grid over the hypercube where evaluation points are sampled. Must be an integer \(\ge 3\).

  • delta (Union[float, int, None]) – Size of the jump between two consecutive evaluation points, must be a multiple of delta should be in {1/(n_levels-1), ..., 1-1/(n_levels-1)}. Default: \(delta=\frac{levels\_number}{2 * (levels\_number-1)}\) if n_levels is even, \(delta=0.5\) if n_levels is odd.

  • random_state (Union[None, int, RandomState]) – Random seed used to initialize the pseudo-random number generator. Default is None.

  • n_trajectories (Optional[int]) – Number of random trajectories, usually chosen between \(5\) and \(10\). The number of model evaluations is n_trajectories * (d+1). If None, the Morris object is created but not run (see run() method)

  • maximize_dispersion (bool) –

    If True, generate a large number of design trajectories and keep the ones that maximize dispersion between all trajectories, allows for a better coverage of the input space.

    Default False.

run(n_trajectories)[source]

Run the Morris indices evaluation.

The code first sample trajectories in the unit hypercube and transform them to the physical space (see method sample_trajectories()), then runs the forward model to compute the elementary effects, and finally computes the sensitivity indices.

Parameters:

n_trajectories (int) – Number of random trajectories. Usually chosen between \(5\) and \(10\). The number of model evaluations is n_trajectories * (d+1).

sample_trajectories(n_trajectories, maximize_dispersion=False)[source]

Create the trajectories, first in the unit hypercube then transform them in the physical space.

Parameters:
  • n_trajectories (int) – Number of random trajectories. Usually chosen between \(5\) and \(10\). The number of model evaluations is n_trajectories * (d+1).

  • maximize_dispersion (bool) – If True, generate a large number of design trajectories and keep the ones that maximize dispersion between all trajectories, allows for a better coverage of the input space. Default False.

Attributes

MorrisSensitivity.trajectories_unit_hypercube: ndarray

Trajectories in the unit hypercube, numpy.ndarray of shape (n_trajectories, d+1, d)

MorrisSensitivity.trajectories_physical_space: ndarray

Trajectories in the physical space, numpy.ndarray of shape (n_trajectories, d+1, d)

MorrisSensitivity.elementary_effects: ndarray

Elementary effects \(EE_{k}\), numpy.ndarray of shape (n_trajectories, d, ny).

MorrisSensitivity.mustar_indices: ndarray

First Morris sensitivity index \(\mu_{k}^{\star}\), numpy.ndarray of shape (d, ny)

MorrisSensitivity.sigma_indices: ndarray

Second Morris sensitivity index \(\sigma_{k}\), numpy.ndarray of shape (d, ny)

Examples

Note

Subclassing the Morris class. The user can subclass the Morris class to implement algorithms with better sampling of the trajectories for instance. In order to do so, the user can simply overwrite the sample_trajectories() method, which should take as inputs the number of trajectories trajectories_number and any other user-defined input (transferred from the run() method as kwargs).