This is a joint blog post with Andrew ElHabr.

In probabilistic sensitivity analysis (PSA), model parameters are repeatedly sampled from the joint parameter space to generate a set of model runs, also known as PSA iterations.

The choice of probability distribution for a given parameter depends on the parameter’s range. If the parameter is constrained between 0 and 1, the beta distribution is commonly used, otherwise the normal or gamma distributions are a good choice.

Typically, for each parameter, we will have a base case value (\(B\)), a lower value (\(L\)), and an upper value (\(U\)). One common approach to designing a probability distribution is to assume \(B\) is the median, and \(L\) and \(U\) are the 2.5th and 97.5th percentiles, i.e., the bounds of the 95% confidence interval.

This tutorial will explain how to parameterize the normal, beta, and gamma distributions under the above assumption.

Normal distribution

If \(L\) and \(U\) are equidistant from \(B\) and a symmetrical distribution is desired, then the normal distribution is ideal. Recall from high school statistics, that (1) the mean of the normal distribution is equal to its median; and (2) 1.96 standard deviations above and below the mean delineate the 95% confidence interval. Therefore, the distribution we need is:

\[{\rm Normal}\bigg(B,\ \frac{B-L}{1.96}\bigg).\]

Beta distribution

There is no analytical way to do this so we have to resort to some kind of calibration approach. Here is an example using simulated annealing in R:

 library(GenSA)
 
 # Quantile targets
 target <- c(L, B, U)
 
 # MSE between estimated quantiles and target quantiles
 score <- function(params) {
   est <- qbeta(c(0.025, 0.5, 0.975), shape1 = params[1], shape2 = params[2])
   return(sum((est - target)^2))
 }

 # Upper and lower bounds for shape1 and shape2
 lower <- c(1, 1)
 upper <- c(200, 200)

 # Setting the random seed is good practice
 set.seed(1)
 
 # Run calibration
 opt <- GenSA(par = mapply(runif, 1, lower, upper),
             fn = score,
             lower = lower,
             upper = upper)

Gamma distribution

Same as the beta distribution, we have to use calibration. Simply replace the previous score function with:

 score <- function(params) {
   est <- qgamma(c(0.025, 0.5, 0.975), shape = params[1], scale = params[2])
   return(sum((est - target)^2))
 }

Validation

The final step is to check that the fitted distribution looks reasonable (make a plot!) and its quantiles do indeed match up with \(B\), \(L\), and \(U\).