Jitter analyses are commonly implemented in Stock Synthesis to ensure
a model has reached global convergence. Jitter involves changing the
parameter start values by a small increment and rerunning the model to
see if that adjustment causes the model to converge at a lower
likelihood. This can be useful for distinguishing if a model reached a
local minimum or a global minimum. The number of jitter iterations
should be anywhere between 50-100 to ensure a good spread of start
values. If any of those runs has a lower likelihood than your current
model, parameter start values should be adjusted to use those from the
run with a lower likelihood. You can do this by adjusting the values in
the control.ss file to match those in the
ss.par_#_of_the_lower_likelihood_run. We provide the steps for running
jitter analysis using r4ss::jitter()
below.
Model inputs
To run a Stock Synthesis model, four input files are required:
starter.ss, forecast.ss, control.ss, and data.ss. The input files for
the example model can be found within the ss3diags
package
and accessed as shown below. Also, if you do not have the
r4ss
package installed, you will need to install it for
this tutorial.
install_github("r4ss/r4ss")
library(r4ss)
files_path <- system.file("extdata", package = "ss3diags")
dir_jitter <- file.path(tempdir(check = TRUE), "jitter")
dir.create(dir_jitter, showWarnings = FALSE, recursive = TRUE)
list.files(files_path)
#> [1] "control.ss" "data.ss" "forecast.ss" "starter.ss"
file.copy(from = list.files(files_path, full.names = TRUE), to = dir_jitter)
#> [1] TRUE TRUE TRUE TRUE
You will need to make sure you have the SS
executable file either in your path or in the directory you are
running the retrospective from (in this case dir_jitter
).
An easy way to get the latest release of stock synthesis is to use the
r4ss
function get_ss3_exe()
.
r4ss::get_ss3_exe(dir = dir_jitter, version = "v3.30.21")
#> The stock synthesis executable for Linux v3.30.21 was downloaded to: /tmp/RtmpnGOaCR/jitter/ss3
We will run the model in dir_jitter
first to produce the
necessary output files. It is recommended to do jitter runs in a
subdirectory of your model run. This will keep all of the output files
separate from other diagnostic tests you may run.
r4ss::run(dir = dir_jitter, exe = "ss3", verbose = FALSE)
#> [1] "ran model" "ran model" "ran model" "ran model" "ran model"
Jitter
For this example, we will run 50 jitters. The jitter()
function automates the entire process so you only need to give it a few
arguments and it will run and produce the total likelihoods for each
run. Full documentation of the jitter()
function can be
found at the r4ss
website.
Njitter <- 50
jit.likes <- r4ss::jitter(
dir = dir_jitter,
Njitter = Njitter,
init_values_src = 1,
jitter_fraction = 0.1,
exe = "ss3",
printlikes = FALSE,
verbose = FALSE
)
To analyze the output of all 50 runs, use
r4ss::SSgetoutput()
and r4ss::SSsummarize()
as
shown below.
jit_mods <- SSgetoutput(
keyvec = 0:Njitter, # 0 to include reference run (Report0.sso)
getcomp = FALSE,
dirvec = dir_jitter,
getcovar = FALSE,
verbose = FALSE
)
jit_summary <- SSsummarize(jit_mods, verbose = FALSE)
Some key sections you may want to check and compare across models are, likelihoods, derived quantities, and estimated parameters.
head(jit_summary$likelihoods)
#> replist0 replist1 replist2 replist3 replist4 replist5
#> 1 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02
#> 2 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10
#> 3 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01
#> 4 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00
#> 5 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02
#> 6 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02
#> replist6 replist7 replist8 replist9 replist10 replist11
#> 1 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02
#> 2 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10
#> 3 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01
#> 4 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00
#> 5 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02
#> 6 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02
#> replist12 replist13 replist14 replist15 replist16 replist17
#> 1 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02
#> 2 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10
#> 3 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01
#> 4 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00
#> 5 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02
#> 6 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02
#> replist18 replist19 replist20 replist21 replist22 replist23
#> 1 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02
#> 2 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10
#> 3 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01
#> 4 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00
#> 5 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02
#> 6 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02
#> replist24 replist25 replist26 replist27 replist28 replist29
#> 1 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02
#> 2 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10
#> 3 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01
#> 4 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00
#> 5 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02
#> 6 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02
#> replist30 replist31 replist32 replist33 replist34 replist35
#> 1 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02
#> 2 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10
#> 3 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01
#> 4 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00
#> 5 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02
#> 6 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02
#> replist36 replist37 replist38 replist39 replist40 replist41
#> 1 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02
#> 2 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10
#> 3 1.74853e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01
#> 4 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00
#> 5 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02
#> 6 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02
#> replist42 replist43 replist44 replist45 replist46 replist47
#> 1 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02 7.54302e+02
#> 2 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10 1.33479e-10
#> 3 1.74853e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01 1.74852e-01
#> 4 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00 -7.11813e+00
#> 5 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02 3.66756e+02
#> 6 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02 2.31845e+02
#> replist48 replist49 replist50 Label
#> 1 7.54302e+02 7.54302e+02 7.54302e+02 TOTAL
#> 2 1.33479e-10 1.33479e-10 1.33479e-10 Catch
#> 3 1.74852e-01 1.74852e-01 1.74852e-01 Equil_catch
#> 4 -7.11813e+00 -7.11813e+00 -7.11813e+00 Survey
#> 5 3.66756e+02 3.66756e+02 3.66756e+02 Length_comp
#> 6 2.31845e+02 2.31845e+02 2.31845e+02 Age_comp
head(jit_summary$quants)
#> replist0 replist1 replist2 replist3 replist4 replist5 replist6 replist7
#> 1 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8
#> 2 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 3 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 4 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1
#> 5 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1
#> 6 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5
#> replist8 replist9 replist10 replist11 replist12 replist13 replist14 replist15
#> 1 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8
#> 2 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 3 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 4 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1
#> 5 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1
#> 6 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5
#> replist16 replist17 replist18 replist19 replist20 replist21 replist22
#> 1 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8
#> 2 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 3 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 4 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1
#> 5 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1
#> 6 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5
#> replist23 replist24 replist25 replist26 replist27 replist28 replist29
#> 1 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8
#> 2 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 3 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 4 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1
#> 5 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1
#> 6 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5
#> replist30 replist31 replist32 replist33 replist34 replist35 replist36
#> 1 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8
#> 2 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 3 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 4 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1
#> 5 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1
#> 6 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5
#> replist37 replist38 replist39 replist40 replist41 replist42 replist43
#> 1 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8
#> 2 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 3 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 4 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1
#> 5 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1
#> 6 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5
#> replist44 replist45 replist46 replist47 replist48 replist49 replist50
#> 1 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8 54773.8
#> 2 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 3 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4 26071.4
#> 4 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1 24096.1
#> 5 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1 22126.1
#> 6 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5 20143.5
#> Label Yr
#> 1 SSB_Virgin NA
#> 2 SSB_Initial NA
#> 3 SSB_2011 2011
#> 4 SSB_2012 2012
#> 5 SSB_2013 2013
#> 6 SSB_2014 2014
head(jit_summary$pars)
#> replist0 replist1 replist2 replist3 replist4 replist5 replist6
#> 1 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 2 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000
#> 3 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200
#> 4 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165
#> 5 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 6 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> replist7 replist8 replist9 replist10 replist11 replist12 replist13
#> 1 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 2 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000
#> 3 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200
#> 4 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165
#> 5 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 6 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> replist14 replist15 replist16 replist17 replist18 replist19 replist20
#> 1 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 2 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000
#> 3 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200
#> 4 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165
#> 5 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 6 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> replist21 replist22 replist23 replist24 replist25 replist26 replist27
#> 1 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 2 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000
#> 3 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200
#> 4 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165
#> 5 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 6 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> replist28 replist29 replist30 replist31 replist32 replist33 replist34
#> 1 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 2 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000
#> 3 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200
#> 4 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165
#> 5 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 6 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> replist35 replist36 replist37 replist38 replist39 replist40 replist41
#> 1 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 2 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000
#> 3 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200
#> 4 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165
#> 5 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 6 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> replist42 replist43 replist44 replist45 replist46 replist47 replist48
#> 1 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 2 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000 22.769000
#> 3 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200 71.807200
#> 4 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165 0.142165
#> 5 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> 6 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000 0.100000
#> replist49 replist50 Label Yr recdev
#> 1 0.100000 0.100000 NatM_uniform_Fem_GP_1 NA FALSE
#> 2 22.769000 22.769000 L_at_Amin_Fem_GP_1 NA FALSE
#> 3 71.807200 71.807200 L_at_Amax_Fem_GP_1 NA FALSE
#> 4 0.142165 0.142165 VonBert_K_Fem_GP_1 NA FALSE
#> 5 0.100000 0.100000 CV_young_Fem_GP_1 NA FALSE
#> 6 0.100000 0.100000 CV_old_Fem_GP_1 NA FALSE
You may also want to check that the models converged. To do this you can check the maximum gradients to make sure they are all small (< 0.0001). You can also compare the estimated spawning biomass, if they are extreme values (+2x or <0.5x the base spawning biomass) this suggests the model didn’t converge.
# Maximum gradient
converged_grad <- which(jit_summary$maxgrad < 0.0001)
converged_ssb <- jit_summary$SpawnBio %>%
mutate(across(c(1:(Njitter + 1)),
.fns = ~ . / replist0
)) %>% # for each column, divide SSB by SSB from the reference run (replist)
select(-Label) %>%
pivot_longer(col = c(1:(Njitter + 1)), names_to = "jitter", values_to = "SSB") %>%
pivot_wider(names_from = Yr, values_from = SSB) %>%
mutate(rownumber = seq(1, nrow(.))) %>%
tibble::column_to_rownames("jitter") %>%
filter_at(vars(1:(ncol(.) - 1)), all_vars((.) < 2 & (.) > 0.5)) %>% # keep only rows where SSB is a reasonable value
select(rownumber) %>%
pull(rownumber)
converged_mods <- intersect(converged_grad, converged_ssb) # getting which models are in both groups
converged_jitters <- jit_mods[converged_grad]
converged_sum <- SSsummarize(converged_jitters, verbose = FALSE)
Visualizing Output
To compare the likelihoods of all runs, we plot them as shown below.
There are no built in functions (as of writing this vignette) in
r4ss
or ss3diags
to generate a likelihood
plot, therefore we provide code in the tidyverse syntax (using
ggplot2
) to visualize the results.
converged_sum$likelihoods %>%
filter(str_detect(Label, "TOTAL")) %>%
select(-Label) %>%
pivot_longer(cols = everything(), names_to = "jitter", values_to = "likelihood") %>%
separate(jitter, into = c("replist", "jitter"), sep = "(?<=[A-Za-z])(?=[0-9])") %>%
mutate(jitter = as.numeric(jitter)) %>%
ggplot(aes(x = jitter, y = likelihood)) +
geom_point(size = 3) +
geom_hline(aes(yintercept = likelihood[1]), color = "red") +
theme_classic() +
labs(
y = "Total Likelihood",
x = "Jitter runs at a converged solution"
)
The figure plots the total likelihood from each jitter run and the
red line indicates the total likelihood value from the reference run. If
there are any runs with points below the red line, use the converged
parameter values from the run with the lowest likelihood value as
starting values in your base model. We can also use
r4ss::SSplotComparisons()
to compare the spawning biomass
trajectories between jitter runs to see the impact of different
parameter values on the estimated quantities.
SSplotComparisons(converged_sum,
subplots = 2,
ylimAdj = 1,
new = FALSE
)
#> showing uncertainty for all models
#> subplot 2: spawning biomass with uncertainty intervals