How to use SpatialSablefishAssessment
Configuring and checking model inputs (data and parameters)
This package contains TMB models and summarizing and plotting functions for a spatial model used in sablefish research. Users are responsible for configuring the data
and parameter
structures that are passed to the TMB MakeADFun
function which compiles the model. The best place to look for what dimensions and names of expected elements for data
and parameter
it is best to look at an example or the source code for the model (see here). To view an example data run
load(system.file("testdata", "MockSablefishModel.RData",package="SpatialSablefishAssessment"))
names(data)
names(parameters)
region_key
Once you have built the data
and parameter
objects then you can check that the dimensions are consistent with the model by using,
validate_input_data_and_parameters(data, parameters)
This function will report a message telling you either success or if one of the objects dimensions are off, then you will need to fix this because it is likely if you pass this to the TMBs MakeADFun
it will crash your R session.
The following list are some useful utility functions contained in this package to visualize data inputs. All functions should be documented and queried using the usual R ?
method
plot_input_observations
plot_input_catches
plot_mean_weight
plot_age_length_matrix
Once you have checked the data
and parameter
objects you can build the TMB model following,
= TMB::MakeADFun(data = data,
my_model parameters = parameters,
DLL = "SpatialSablefishAssessment_TMBExports", silent = T)
During simulations I would sometimes encounter the following error
in getParameterOrder(data, parameters, new.env(), DLL = DLL) : NOT A VECTOR!`. Error
If you encounter this use the function ?convert_simdata_integers
.
Optimisation
= nlminb(start = my_model$par, objective = my_model$fn, gradient = my_model$gr, control = list(iter.max = 10000, eval.max = 10000))
mle_optim
# Try and improve the optimsation running the model for two additional Newton Raphson iterations
= tryCatch(expr =
try_improve for(i in 1:2) {
= as.numeric(my_model$gr(mle_optim$par))
g = optimHess(mle_spatial$par, fn = my_model$fn, gr = my_model$gr)
h $par = mle_spatial$par - solve(h,g)
mle_optim$objective = my_model$fn(mle_optim$par)
mle_optim
}error = function(e){e})
,
## should be NULL i.e., no error or warning otherwise suggests non-PD hessian matrix try_improve
Model Summary
Once you are satisfied that the model has converged at global minimum, then you can get the model to report model quantities
## get MLE quantities
= my_model$report(mle_optim$par)
mle_report
#########
## Plot interesting
## Model quantities i.e., recruitment SSBs model fits etc
#########
## movement assumption
plot_movement(mle_report, region_key = region_key)
# starting values
plot_movement(OM_report, region_key)
# plot selectivities
plot_selectivities(mle_report)
# starting values
plot_selectivities(OM_report)
## Regional SSBs
= plot_SSB(mle_report, region_key = region_key)
ssb_plt
ssb_plt## sum SSB over all regions
ggplot(ssb_plt$data %>% group_by(Year) %>% summarise(total_ssb = sum(SSB)), aes(x = Year, y = total_ssb)) +
geom_line(linewidth = 1.1) +
ylim(0,NA)
## plot F's
plot_fishing_mortalities(MLE_report = mle_report, region_key = region_key)
## plot fits to observations
# catch and index
plot_catch_fit(MLE_report = mle_report, region_key = region_key) + facet_wrap(label~Region, ncol = n_regions) + ylab("Catch (mt)")
plot_index_fit(MLE_report = mle_report, region_key = region_key)
# survey AFs
= c(1981, seq(from = 1985, to = 1993, by = 2), 1996:1999)
first_year_set plot_AF(MLE_report = mle_report, region_key = region_key, label = "srv_dom_ll", subset_years = first_year_set, sex = "male") +
ggtitle("Male survey AF") +
guides(shape = "none", linetype = "none") +
ylim(0,20)
plot_AF(MLE_report = mle_report, region_key = region_key, label = "srv_dom_ll", subset_years = first_year_set, sex = "female") +
ggtitle("Female survey AF") +
guides(shape = "none", linetype = "none")
# fishery LFs
# Fixed gear
plot_LF(MLE_report = mle_report, region_key = region_key, label = "fixed", subset_years = 1991:1999, sex = "male") +
ggtitle("Male fixed LF") +
guides(shape = "none", linetype = "none")
plot_LF(MLE_report = mle_report, region_key = region_key, label = "fixed", subset_years = 1991:1999, sex = "female") +
ggtitle("Female fixed LF") +
guides(shape = "none", linetype = "none")
# plot by tag releases event
= get_tag_recovery_obs_fitted_values(mle_report, region_key = region_key)
tag_fits_by_age_sex = tag_fits_by_age_sex %>% group_by(release_event, unique_recovery_id) %>% summarise(observed = sum(observed), predicted = sum(predicted), recovery_year = unique(recovery_year), recovery_region = unique(recovery_region), release_region = unique(release_region), release_year = unique(release_year))
tag_fits $resid = tag_fits$observed - tag_fits$predicted
tag_fits$stand_resid = tag_fits$resid / tag_fits$predicted
tag_fits$resid_sign = ifelse(tag_fits$resid < 0, "negative", "positive")
tag_fits= unique(tag_fits$release_event)
unique_release_events = ggplot(tag_fits %>% filter(release_event %in% unique_release_events[1:16]), aes(x = recovery_year, y = recovery_region)) +
gplt geom_point(aes(size = abs(stand_resid), col = resid_sign)) +
labs(x = "Recovery year", y = "Recovery region", size = "Pearson residuals") +
theme_bw() +
scale_size_area() +
facet_wrap(~release_event) +
scale_x_discrete(breaks = every_nth(n = 5))
MCMC inference
Previously ADMB had both frequentist and Bayesian inference available, given this package is embedded in TMB it can only do frequentist inference. However, it is very easy use the tmbstan
package allows TMB models to plug into the Stan back-end for MCMC inference. This will mean you will need to install this package following.
::install_github("kaskr/tmbstan/tmbstan") devtools
Once you have done MLE you can use the following R code to run MCMC and assess posteriors/convergence
library(tmbstan)
## Run a single chain in serial with defaults
<- tmbstan(my_model, chains=4)
fit
## Can also get ESS and Rhat from rstan::monitor
<- monitor(fit)
mon max(mon$Rhat)
min(mon$Tail_ESS)
## Other methods provided by 'rstan'
class(fit)
methods(class="stanfit")
## Pairs plot of the fixed effects
pairs(fit, pars=names(obj$par))
## Trace plot
traceplot(fit, pars=names(obj$par), inc_warmup=TRUE)
## Can extract marginal posteriors easily
<- as.matrix(fit)
post
hist(post[,'ln_mean_rec'])
## What if you want a posterior for derived quantities in the report? Just
## loop through each posterior sample (row) and call the report function
## which returns a list. The last column is the log-posterior density (lp__)
## and needs to be dropped
$report(post[1,-ncol(post)]) # sd0 is only element
obj<- rep(NA, len=nrow(post))
Bzero for(i in 1:nrow(post)){
<- obj$report(post[i,-ncol(post)])
r <- r$Bzero
Bzero[i]
}hist(Bzero)