Performing Global Sensitivity Analysis
JuliaSimModelOptimizer helps users to consider additional model exploration based on Global Sensitivity Analysis (GSA). This approach is helpful to further investigate how the model output reacts to variance in the model input. For example, we can analyse quantitatively how the variance in single input variables and how combinations of variances in several input variables affect output variables as shown in the figure below:
- Influence of first input variable,
- Influence of second input variable,
- Influence of third input variable,
- Influence of second and third input variable.
The GlobalSensitivity
package provides a large variety of algorithms via gsa(f, method)
. The function that is used to compuite the sensitivity can be based on simulate
, so that one can take advantage of already specified experiments. [1]
For example let's consider the predator prey model and perform GSA using the Morris method.
using JuliaSimModelOptimizer
using GlobalSensitivity
using Statistics
using OrdinaryDiffEq
using ModelingToolkit
import ModelingToolkit: D_nounits as D, t_nounits as t
using Plots
function lotka()
@variables x(t)=3.1 y(t)=1.5
@parameters α=1.3 β=0.9 γ=0.8 δ=1.8
eqs = [
D(x) ~ α * x - β * x * y,
D(y) ~ -δ * y + γ * x * y,
]
@named sys = ODESystem(eqs, t)
end
sys = complete(lotka())
tspan = (0.0, 10.0)
experiment = Experiment(nothing, sys;
tspan,
saveat = range(0, stop = 10, length = 200),
alg = Tsit5()
)
prob = InverseProblem(experiment,
[
sys.α => (1.0, 5.0),
sys.β => (1.0, 5.0),
sys.γ => (1.0, 5.0),
sys.δ => (1.0, 5.0),
])
function f(x)
sol = simulate(experiment, prob, x)
[mean(sol[:x]), maximum(sol[:y])]
end
lb = lowerbound(prob)
ub = upperbound(prob)
param_range = [[l, u] for (l, u) in zip(lb, ub)]
m = gsa(f, Morris(total_num_trajectory=1000, num_trajectory=150), param_range)
GlobalSensitivity.MorrisResult{Matrix{Float64}, Vector{Any}}([0.04951566290969013 -0.01220115453077349 -0.44472189657726197 0.36540103543789676; 0.5487957791504819 -1.6104931285173318 1.0248368147031335 -0.6031844003597436], [0.21055650033086332 0.031988069072590546 0.44472189657726197 0.36553578450302626; 0.5630474943877086 1.6115339213201272 1.0288224567371662 0.6188230799213801], [0.10377286812835068 0.003174334234495954 0.2653755824623717 0.09813138267403666; 0.33218722390629835 7.537702533526558 0.41599049718986364 0.34765570120407663], Any[[[0.33943303691356014, 0.2270717520098625], [-0.050334191633060556, 1.205564525787815], [-0.050334191633060556, 1.205564525787815], [-0.04189665701074952, 0.7301221058576726], [-0.0334947433751138, 0.507311565709515], [0.3345452228198708, 0.5476510445342382], [0.28192094228961867, 0.5512875897253251], [0.28192094228961867, 0.5512875897253251], [0.28192094228961867, 0.5512875897253251], [0.32751837514215326, 0.5556792481233288] … [-0.13157357558062258, 1.2297921641525118], [-0.11729277702857735, 0.9865617826079293], [-0.09295266647694683, 1.1020820364989063], [-0.06947162606631788, 1.2488221853357142], [-0.022042820311879898, 0.07966133198642093], [-0.022042820311879898, 0.07966133198642093], [-0.045163274389490846, 0.09868119330903102], [-0.09233282615920468, -0.16247952529332707], [-0.09661290519753715, 0.0816145589200659], [-0.09233282615920468, -0.16247952529332707]], [[-0.023806092533485604, -0.5227128358688066], [-0.023806092533485604, -0.5227128358688066], [-0.023806092533485604, -0.5227128358688066], [-0.04864662312287798, -0.5120242248279712], [-0.02112985995918171, -0.5224950280741764], [-0.0094017436403192, -1.6147784744086715], [0.5199310351922226, -16.065685646952076], [-0.11559621218268151, -9.900097109444804], [-0.0346914063328434, -0.3470744349853083], [-0.0346914063328434, -0.3470744349853083] … [-0.04073304477035712, -0.2918564369471379], [0.006705564795252984, -0.5745065399963295], [0.006178404015378268, -0.5841731687945201], [0.012021265151962173, -0.5479949869476402], [0.01405984569725632, -0.4942065851996085], [-0.04155120998457964, -2.163256925060628], [-0.00940049996066294, -0.20590717372061518], [-0.00940049996066294, -0.20590717372061518], [-0.009709891577593548, -0.28006074691790894], [0.006806018058996677, -0.21457236061756085]], [[-0.40582303980574824, 0.670178393442105], [-0.15279353641301946, 0.529237220434121], [-0.12871520658551353, 1.209540451208599], [-0.1203132929498778, 0.9867299110604414], [-0.1203132929498778, 0.9867299110604414], [-0.5366312577743506, 1.3223882846074417], [-0.18617940410013803, -0.07824670292101871], [-0.35809639615432315, 4.769152026385549], [-0.3258683663496734, 3.830405934358901], [-0.5099153554150643, 2.307843284319293] … [-0.3906816646227551, 1.8022664015576288], [-0.41130439432363447, 1.5002932507080835], [-0.415825407894303, 1.626671626953169], [-0.415825407894303, 1.626671626953169], [-0.13867201074509222, 1.5268025152451628], [-0.08196644380944437, 0.6804522929985151], [-0.07768636477111196, 0.4363582087851247], [-0.07768636477111196, 0.4363582087851247], [-0.07768636477111196, 0.4363582087851247], [-0.08196644380944437, 0.6804522929985151]], [[0.5859287245443613, -0.3549091323636249], [0.582388332622954, -0.3573275635288817], [0.5972884918860423, 0.8980166100811804], [0.5972884918860423, 0.8980166100811804], [0.7692054839402275, -3.9493821192253877], [0.22083795240685497, -1.2168193046718792], [0.22708653213328864, -0.8856920982568895], [0.3968243984778571, -0.18057610169708932], [0.3968243984778571, -0.18057610169708932], [0.41551403422326505, -0.26267411578469657] … [0.026236580713460484, -0.521550094952382], [0.019578400698170764, -0.5582860858494252], [0.051512332002798825, -0.3967190652151564], [0.2305910773788925, -0.6952777828897424], [0.23878481617740302, -0.8865034970729635], [0.25523243580509936, -0.6716959477620025], [0.095256820260196, -1.098222178193395], [0.38350519993370275, -0.4057196100891603], [0.3737950571924992, -0.43149787466702844], [0.03736514227404703, -0.5794551976066015]]])
We can plot the results using
scatter(m.means[1,:], m.variances[1,:], series_annotations=[:α,:β,:y,:δ], color=:gray)
and
scatter(m.means[2,:], m.variances[2,:], series_annotations=[:α,:β,:y,:δ], color=:gray)
For the Sobol method, we can similarly do:
m = gsa(f, Sobol(), param_range, samples=1000)
GlobalSensitivity.SobolResult{Matrix{Float64}, Nothing, Nothing, Nothing}([-0.0008389581111137501 -8.752702803115279e-5 0.5453489859004284 0.3542225683623781; 0.06407841546888673 0.5004449333190693 0.2356628015046419 0.06565860013591748], nothing, nothing, nothing, [0.00626573104376282 0.0034312794317180716 0.6315874448691761 0.4426611371958135; 0.13079977803485324 0.6194845380453204 0.2860119585836818 0.09457766010315302], nothing)
See the documentation for GlobalSensitivity for more details.
- 1Derived from https://docs.sciml.ai/GlobalSensitivity/stable/tutorials/parallelized_gsa/ from from https://github.com/SciML/SciMLDocs, MIT licensed, see repository for details.