Title: | Checkpoint MCMC Sampling with 'Stan' |
---|---|
Description: | Fit Bayesian models in Stan <doi: 10.18637/jss.v076.i01> with checkpointing, that is, the ability to stop the MCMC sampler at will, and then pick right back up where the MCMC sampler left off. Custom 'Stan' models can be fitted, or the popular package 'brms' <doi: 10.18637/jss.v080.i01> can be used to generate the 'Stan' code. This package is fully compatible with the R packages 'brms', 'posterior', 'cmdstanr', and 'bayesplot'. |
Authors: | Vencislav Popov [aut, cre, cph], Donald Williams [aut], Tyler Matta [aut], NWEA [cph] |
Maintainer: | Vencislav Popov <[email protected]> |
License: | Apache License 2.0 | file LICENSE |
Version: | 0.2.0 |
Built: | 2024-10-25 05:18:48 UTC |
Source: | https://github.com/venpopov/chkptstanr |
Fit Bayesian generalized (non-)linear multivariate multilevel models using brms with checkpointing.
chkpt_brms( formula, data, iter_adaptation = 150, iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 100, parallel_chains = 4, threads_per = 1, chkpt_progress = TRUE, control = NULL, seed = 1, stop_after = NULL, reset = FALSE, path, ... )
chkpt_brms( formula, data, iter_adaptation = 150, iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 100, parallel_chains = 4, threads_per = 1, chkpt_progress = TRUE, control = NULL, seed = 1, stop_after = NULL, reset = FALSE, path, ... )
formula |
An object of class |
data |
An object of class |
iter_adaptation |
(positive integer) The number of iterations in the initial warmup, which are used for the adaptation of the step size and inverse mass matrix. This is equivalent to the traditional warmup stage. Checkpointing will begin only after this stage is complete. |
iter_warmup |
(positive integer) The number of warmup iterations to run per chain after the adaptation stage (defaults to 1000). During this stage the step size and inverse mass matrix are fixed to the values found during the adaptation stage. There is no further adaptation performed. |
iter_sampling |
(positive integer) The number of post-warmup iterations to run per chain (defaults to 1000). |
iter_per_chkpt |
(positive integer). The number of iterations per
checkpoint. Note that |
parallel_chains |
(positive integer) The maximum number of MCMC
chains to run in parallel. If parallel_chains is not specified then the
default is to look for the option |
threads_per |
(positive integer) Number of threads to use in
within-chain parallelization (defaults to |
chkpt_progress |
logical. Should the |
control |
A named list of parameters to control the sampler's behavior.
It defaults to NULL so all the default values are used. For a comprehensive
overview see |
seed |
(positive integer). The seed for random number generation to make results reproducible. |
stop_after |
(positive integer). The number of iterations to sample
before stopping. If |
reset |
logical. Should the checkpointing be reset? If |
path |
Character string. The path to the folder, that is used for saving the checkpoints (see Details). You can provide either a relative path to the current working directory or a full path. You no longer need to create the folder, as this is done automatically. |
... |
Any additional arguments passed to |
An object of class brmsfit
A folder specified by path
is created with four subfolders:
cmd_output: The cmdstanr output_files (one for each checkpoint and chain).
cp_info: Mass matrix, step size, and initial values for next checkpoint (last iteration from previous checkpoint).
cp_samples: Samples from the posterior distribution (post warmup)
stan_model: Complied Stan model
## Not run: library(brms) library(cmdstanr) # "random" intercept fit1 <- chkpt_brms( bf( formula = count ~ zAge + zBase * Trt + (1 | patient), family = poisson() ), data = epilepsy, , iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 250, path = "chkpt_folder_fit1" ) # brmsfit output fit1 # remove "random" intercept (for model comparison) fit2 <- chkpt_brms( bf( formula = count ~ zAge + zBase * Trt, family = poisson() ), data = epilepsy, , iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 250, path = "chkpt_folder_fit2" ) # brmsfit output fit2 # compare models loo(fit1, fit2) # priors bprior <- prior(constant(1), class = "b") + prior(constant(2), class = "b", coef = "zBase") + prior(constant(0.5), class = "sd") # fit model fit3 <- chkpt_brms( bf( formula = count ~ zAge + zBase + (1 | patient), family = poisson() ), data = epilepsy, path = "chkpt_folder_fit3", prior = bprior, iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 250, ) # check priors prior_summary(fit3) ## End(Not run)
## Not run: library(brms) library(cmdstanr) # "random" intercept fit1 <- chkpt_brms( bf( formula = count ~ zAge + zBase * Trt + (1 | patient), family = poisson() ), data = epilepsy, , iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 250, path = "chkpt_folder_fit1" ) # brmsfit output fit1 # remove "random" intercept (for model comparison) fit2 <- chkpt_brms( bf( formula = count ~ zAge + zBase * Trt, family = poisson() ), data = epilepsy, , iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 250, path = "chkpt_folder_fit2" ) # brmsfit output fit2 # compare models loo(fit1, fit2) # priors bprior <- prior(constant(1), class = "b") + prior(constant(2), class = "b", coef = "zBase") + prior(constant(0.5), class = "sd") # fit model fit3 <- chkpt_brms( bf( formula = count ~ zAge + zBase + (1 | patient), family = poisson() ), data = epilepsy, path = "chkpt_folder_fit3", prior = bprior, iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 250, ) # check priors prior_summary(fit3) ## End(Not run)
Deterimine the number of checkpoints for the warmup and sampling, given the desired number of iterations for each and the iterations per checkpoint.
chkpt_setup(iter_sampling, iter_warmup, iter_per_chkpt)
chkpt_setup(iter_sampling, iter_warmup, iter_per_chkpt)
iter_sampling |
(positive integer) The number of post-warmup iterations to run per chain. Note: in the CmdStan User's Guide this is referred to as num_samples. |
iter_warmup |
(positive integer) The number of warmup iterations to run per chain. Note: in the CmdStan User's Guide this is referred to as num_warmup. |
iter_per_chkpt |
(positive integer) The number of iterations per check point. |
A list with the following:
warmup_chkpts
: Number of warmup checkpoints
sample_chkpts
: Number of sampling checkpoints
total_chkpts
: Total number of checkpoints
(warmup_chkpts + sample_chkpts)
iter_per_chkpt
: Iterations per checkpoint
chkpt_setup <- chkpt_setup( iter_sampling = 5000, iter_warmup = 2000, iter_per_chkpt = 10 ) chkpt_setup
chkpt_setup <- chkpt_setup( iter_sampling = 5000, iter_warmup = 2000, iter_per_chkpt = 10 ) chkpt_setup
Fit Bayesian models using Stan with checkpointing.
chkpt_stan( model_code, data, iter_adaptation = 150, iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 100, parallel_chains = 4, threads_per = 1, chkpt_progress = TRUE, control = NULL, seed = 1, stop_after = NULL, reset = FALSE, path, ... )
chkpt_stan( model_code, data, iter_adaptation = 150, iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 100, parallel_chains = 4, threads_per = 1, chkpt_progress = TRUE, control = NULL, seed = 1, stop_after = NULL, reset = FALSE, path, ... )
model_code |
Character string corresponding to the Stan model. |
data |
A named list of R objects (like for RStan). Further details can
be found in |
iter_adaptation |
(positive integer) The number of iterations in the initial warmup, which are used for the adaptation of the step size and inverse mass matrix. This is equivalent to the traditional warmup stage. Checkpointing will begin only after this stage is complete. |
iter_warmup |
(positive integer) The number of warmup iterations to run per chain (defaults to 1000). |
iter_sampling |
(positive integer) The number of post-warmup iterations to run per chain (defaults to 1000). |
iter_per_chkpt |
(positive integer). The number of iterations per
checkpoint. Note that |
parallel_chains |
(positive integer) The maximum number of MCMC
chains to run in parallel. If parallel_chains is not specified then the
default is to look for the option |
threads_per |
(positive integer) Number of threads to use in
within-chain parallelization (defaults to |
chkpt_progress |
logical. Should the |
control |
A named list of parameters to control the sampler's behavior.
It defaults to NULL so all the default values are used. For a comprehensive
overview see |
seed |
(positive integer). The seed for random number generation to make results reproducible. |
stop_after |
(positive integer). The number of iterations to sample
before stopping. If |
reset |
logical. Should the checkpointing be reset? If |
path |
Character string. The path to the folder, that is used for saving the checkpoints (see Details). You can provide either a relative path to the current working directory or a full path. You no longer need to create the folder, as this is done automatically. |
... |
Currently ignored. |
An objet of class chkpt_stan
## Not run: stan_code <- make_stancode( bf( formula = count ~ zAge + zBase * Trt + (1 | patient), family = poisson() ), data = epilepsy ) stan_data <- make_standata( bf( formula = count ~ zAge + zBase * Trt + (1 | patient), family = poisson() ), data = epilepsy ) # "random" intercept fit1 <- chkpt_stan( model_code = stan_code, data = stan_data, iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 250, path = "chkpt_folder_fit1" ) draws <- combine_chkpt_draws(object = fit1) posterior::summarise_draws(draws) # eight schools example stan_code <- " data { int<lower=0> n; real y[n]; real<lower=0> sigma[n]; } parameters { real mu; real<lower=0> tau; vector[n] eta; } transformed parameters { vector[n] theta; theta = mu + tau * eta; } model { target += normal_lpdf(eta | 0, 1); target += normal_lpdf(y | theta, sigma); } " stan_data <- schools.data <- list( n = 8, y = c(28, 8, -3, 7, -1, 1, 18, 12), sigma = c(15, 10, 16, 11, 9, 11, 10, 18) ) fit2 <- chkpt_stan( model_code = stan_code, data = stan_data, iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 250, path = "chkpt_folder_fit2" ) draws <- combine_chkpt_draws(object = fit2) posterior::summarise_draws(draws) ## End(Not run)
## Not run: stan_code <- make_stancode( bf( formula = count ~ zAge + zBase * Trt + (1 | patient), family = poisson() ), data = epilepsy ) stan_data <- make_standata( bf( formula = count ~ zAge + zBase * Trt + (1 | patient), family = poisson() ), data = epilepsy ) # "random" intercept fit1 <- chkpt_stan( model_code = stan_code, data = stan_data, iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 250, path = "chkpt_folder_fit1" ) draws <- combine_chkpt_draws(object = fit1) posterior::summarise_draws(draws) # eight schools example stan_code <- " data { int<lower=0> n; real y[n]; real<lower=0> sigma[n]; } parameters { real mu; real<lower=0> tau; vector[n] eta; } transformed parameters { vector[n] theta; theta = mu + tau * eta; } model { target += normal_lpdf(eta | 0, 1); target += normal_lpdf(y | theta, sigma); } " stan_data <- schools.data <- list( n = 8, y = c(28, 8, -3, 7, -1, 1, 18, 12), sigma = c(15, 10, 16, 11, 9, 11, 10, 18) ) fit2 <- chkpt_stan( model_code = stan_code, data = stan_data, iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 250, path = "chkpt_folder_fit2" ) draws <- combine_chkpt_draws(object = fit2) posterior::summarise_draws(draws) ## End(Not run)
Combine Checkpoint Draws
combine_chkpt_draws(object, ...)
combine_chkpt_draws(object, ...)
object |
An object of class |
... |
Currently ignored. |
An object of class draws_array
.
## Not run: path <- create_folder(folder_name = "chkpt_folder_fit1") stan_code <- " data { int<lower=0> n; real y[n]; real<lower=0> sigma[n]; } parameters { real mu; real<lower=0> tau; vector[n] eta; } transformed parameters { vector[n] theta; theta = mu + tau * eta; } model { target += normal_lpdf(eta | 0, 1); target += normal_lpdf(y | theta, sigma); } " stan_data <- schools.data <- list( n = 8, y = c(28, 8, -3, 7, -1, 1, 18, 12), sigma = c(15, 10, 16, 11, 9, 11, 10, 18) ) fit2 <- chkpt_stan(model_code = stan_code, data = stan_data, iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 250, path = path) draws <- combine_chkpt_draws(object = fit2) draws ## End(Not run)
## Not run: path <- create_folder(folder_name = "chkpt_folder_fit1") stan_code <- " data { int<lower=0> n; real y[n]; real<lower=0> sigma[n]; } parameters { real mu; real<lower=0> tau; vector[n] eta; } transformed parameters { vector[n] theta; theta = mu + tau * eta; } model { target += normal_lpdf(eta | 0, 1); target += normal_lpdf(y | theta, sigma); } " stan_data <- schools.data <- list( n = 8, y = c(28, 8, -3, 7, -1, 1, 18, 12), sigma = c(15, 10, 16, 11, 9, 11, 10, 18) ) fit2 <- chkpt_stan(model_code = stan_code, data = stan_data, iter_warmup = 1000, iter_sampling = 1000, iter_per_chkpt = 250, path = path) draws <- combine_chkpt_draws(object = fit2) draws ## End(Not run)
create_folder() is deprected. Provide a path directly in chkpt_brms()', or chkpt_stan() instead and a folder will be created automatically.'
create_folder(folder_name = "cp_folder", path = NULL)
create_folder(folder_name = "cp_folder", path = NULL)
folder_name |
Character string. Desired name for the 'parent' folder
(defaults to |
path |
Character string, when specified. Defaults to |
the path to the main parent folder containing the four subfolders.
This path should be used as the path
argument in
chkpt_brms
. If return_relative = TRUE
, the relative
path to the current working directory is returned. If path
is
specified or return_relative = FALSE
, the full path is returned.
Create the folder for checkingpointing, which will 'house'
additional folders for the .stan
model, checkpointing information,
and draws from the posterior distribution.
This creates a directory with four folders:
cmd_output: The cmdstanr output_files (one for each checkpoint and chain).
cp_info: Mass matrix, step size, and initial values for next checkpoint (last iteration from previous checkpoint).
cp_samples: Samples from the posterior distribution (post warmup)
stan_model: Complied Stan model
# create initial folder path <- create_folder(folder_name = 'cp_folder') path unlink('cp_folder', recursive = TRUE) # remove folder # remove folder unlink('cp_folder', recursive = TRUE) identical(dir(path), character(0)) # repeat - no warning path <- create_folder(folder_name = 'cp_folder') # repeat - warning, but folders are kept path <- create_folder(folder_name = 'cp_folder') identical(dir(path), c('cmd_output', 'cp_info', 'cp_samples', 'stan_model')) unlink('cp_folder', recursive = TRUE) # specify nested folder path <- create_folder(folder_name = 'nested_folder/cp_folder') path unlink('nested_folder', recursive = TRUE) # remove folder
# create initial folder path <- create_folder(folder_name = 'cp_folder') path unlink('cp_folder', recursive = TRUE) # remove folder # remove folder unlink('cp_folder', recursive = TRUE) identical(dir(path), character(0)) # repeat - no warning path <- create_folder(folder_name = 'cp_folder') # repeat - warning, but folders are kept path <- create_folder(folder_name = 'cp_folder') identical(dir(path), c('cmd_output', 'cp_info', 'cp_samples', 'stan_model')) unlink('cp_folder', recursive = TRUE) # specify nested folder path <- create_folder(folder_name = 'nested_folder/cp_folder') path unlink('nested_folder', recursive = TRUE) # remove folder
CmdStanMCMC
ObjectsA convenience function for extracting the draws from a
CmdStanMCMC
object.
extract_chkpt_draws(object, phase)
extract_chkpt_draws(object, phase)
object |
An object of class |
phase |
Character string. Which phase during checkpointing?
The options included |
A 3-D draws_array
object
(iteration x chain x variable).
This can be used to extract the draws in general by setting
phase = "sample"
which then only includes the post-warmup
draws.
## Not run: library(cmdstanr) # eight schools example fit_schools_ncp_mcmc <- cmdstanr_example("schools_ncp") drws <- extract_chkpt_draws(object = fit_schools_ncp_mcmc, phase = "sample") # compare to cmdstanr all.equal(drws, fit_schools_ncp_mcmc$draws()) ## End(Not run)
## Not run: library(cmdstanr) # eight schools example fit_schools_ncp_mcmc <- cmdstanr_example("schools_ncp") drws <- extract_chkpt_draws(object = fit_schools_ncp_mcmc, phase = "sample") # compare to cmdstanr all.equal(drws, fit_schools_ncp_mcmc$draws()) ## End(Not run)
Extract the inverse metric and step size adaption from
CmdStanMCMC
objects.
extract_hmc_info(object)
extract_hmc_info(object)
object |
An object of class |
A list including
inv_metric
: Inverse metric for each chain
(with matrix = FALSE
).
step_size_adapt
: Step size adaptation for each chain.
This is primarily used internally.
## Not run: library(cmdstanr) fit_schools_ncp_mcmc <- cmdstanr_example("schools_ncp") extract_hmc_info(fit_schools_ncp_mcmc) ## End(Not run)
## Not run: library(cmdstanr) fit_schools_ncp_mcmc <- cmdstanr_example("schools_ncp") extract_hmc_info(fit_schools_ncp_mcmc) ## End(Not run)
Extract Stan State
extract_stan_state(object, phase)
extract_stan_state(object, phase)
object |
An object of class |
phase |
Character string indicating the current phase.
Options include |
A list containing the inverse metric, step size, and last MCMC draw (to be used as the initial value for the next checkpoint)
## Not run: library(cmdstanr) # eight schools example fit_schools_ncp_mcmc <- cmdstanr_example("schools_ncp") extract_stan_state(fit_schools_ncp_mcmc, "sample") ## End(Not run)
## Not run: library(cmdstanr) # eight schools example fit_schools_ncp_mcmc <- cmdstanr_example("schools_ncp") extract_stan_state(fit_schools_ncp_mcmc, "sample") ## End(Not run)
brmsfit
ObjectThis is primarily used internally, wherein the output files of
multiple cmdstanr fits are combined into a single brmsfit
object.
object is converted into a brmsfit
object.
make_brmsfit(formula, data, path, ...)
make_brmsfit(formula, data, path, ...)
formula |
A |
data |
A data frame used to generate the checkpoints |
path |
Character string. The path to the folder, that is used for saving the checkpoints. |
... |
Additional arguments to be passed to |
An object of class brmsfit
This is primarily an internal function that constructs a brmsfit
object.
chkpt_brms
ObjectsPrint chkpt_brms
Objects
## S3 method for class 'chkpt_brms' print(x, ...)
## S3 method for class 'chkpt_brms' print(x, ...)
x |
Object of class |
... |
Currently ignored |
No return value, and used to print the chkpt_brms
object.
This function mainly avoids printing out a list,
and it is only used when brmsfit = "FALSE"
in chkpt_brms
.
Typically, after fitting, the posterior draws should be summarized with
combine_chkpt_draws
(assuming brmsfit = "FALSE"
).
chkpt_setup
ObjectPrint chkpt_setup
Object
## S3 method for class 'chkpt_setup' print(x, ...)
## S3 method for class 'chkpt_setup' print(x, ...)
x |
An object of class |
... |
Currently ignored. |
No return value, and used to print the chkpt_setup
object.
chkpt_setup <- chkpt_setup( iter_sampling = 5000, iter_warmup = 2000, iter_per_chkpt = 10 ) chkpt_setup
chkpt_setup <- chkpt_setup( iter_sampling = 5000, iter_warmup = 2000, iter_per_chkpt = 10 ) chkpt_setup
Deletes all checkpoint files and folders under path except for stan_model/model.stan and stan_model/model.exe. This allows you to restart the sampling from 0 without recompiling the model.
reset_checkpoints(path, reset = TRUE, recompile = FALSE)
reset_checkpoints(path, reset = TRUE, recompile = FALSE)
path |
(character) The path to the checkpoint folder. |
reset |
(logical) If TRUE, only the checkpoint folders are deleted |
recompile |
(logical) If TRUE, the entire folder is deleted allowing for
a fresh start. If both |