This file is meant to present the possibilities of the function
runMCMC_btadjust
in the runMCMCbtadjust
package when using Bayesian models written with the Nimble
language, and the capabilities of the packages
nimble
, nimbleHMC
and nimbleAPT
in terms of MCMC samplers. The aim of the
runMCMC_btadjust
function is to run a Markov Chain Monte
Carlo (MCMC) for a specified Bayesian model while adapting automatically
the burn-in and thinning parameters to meet pre-specified targets in
terms of MCMC convergence and number of effective values of MCMC outputs
- where the term “number of effective values” for the MCMC outputs
refers to sample size adjusted for autocorrelation. This is done in only
one call to the function that repeatedly calls the MCMC until criteria
for convergence and number of effective values are met. This allows to
obtain a MCMC output that is out of the transient phase of the MCMC
(convergence) and that contains a pre-specified number of nearly
independent draws from the posterior distribution (number of effective
values).
This function has four main advantages: (i) it saves the analyst’s
programming time since he/she does not have to repeatedly diagnose and
re-run MCMCs until desired levels of convergence and number of effective
values are reached; (ii) it allows a minimal, normalized quality control
of MCMC outputs by allowing to meet pre-specified levels in terms of
convergence and number of quasi-independent values; (iii) it may save
computer’s time when compared to cases where we have to restart the MCMC
from the beginning if it has not converged or reached the specified
number of effective values (as e.g. with runMCMC
function
in NIMBLE
); and (iv) it can be applied with different MCMC
R languages, with a stronger integration with NIMBLE
.
We will here restrict our attention on the
NIMBLE
language and show a first axis of strong integration
with NIMBLE
. Indeed, the last versions of the
package nimble
provide a still improved flexibility
for the user, especially in terms of MCMC samplers since
nimble
allows the user to choose the MCMC sampler parameter
by parameter, which is one of its great strength. We will demonstrate
the way we can use these possibilities on a very simple, yet problematic
statistical model. The simulated data we wish to model correspond to a
simple linear model with a strongly uncentered explanatory variable - a
situation which is known to pose problems with classical MCMCs due top
strong correlation of the Intercept and slope parameters.
We will analyse these data with the same likelihood function than the one used to generate the data and rather non-informative priors, and with data and initial values that of course include the explanatory variable and its associated slope.
library(runMCMCbtadjust)
library(nimble)
library(parallel)
library(coda)
ModelData <-list(y = y)
ModelConsts <- list(x=x, nobs = length(y))
ModelCode<-nimbleCode(
{
# Priors
Intercept ~ dnorm(0,sd=100)
Slope ~ dnorm(0,sd=100)
population.sd ~ dunif(0,100)
# Normal distribution parameterized by precision = 1/variance in Nimble
population.variance <- population.sd * population.sd
precision <- 1 / population.variance
# Likelihood
for(i in 1:nobs){
meany[i]<-Intercept+Slope*x[i]
y[i] ~ dnorm(meany[i], precision)
}
})
ModelInits <- function()
{list (Intercept = rnorm(1,0,1), Slope = rnorm(1,0,1), population.sd = runif(1, 1, 30))}
### put here to pass CRAN tests: https://stackoverflow.com/questions/41307178/error-processing-vignette-failed-with-diagnostics-4-simultaneous-processes-spa
options(mc.cores=2)
### adapted the number of chains for the same reason
Nchains <- 2
set.seed(1)
Inits<-lapply(1:Nchains,function(x){ModelInits()})
#specifying the names of parameters to analyse and save:
params <- c("Intercept", "Slope", "population.sd")
We now fit this model with the runMCMC_btadjust
function. As we infer there will be some convergence issues we restrict
the duration of the fit to two minutes (or 120 seconds with parameter
time.max
). We will keep this restriction for all the
attempts we will make in this vignette. This is a source of non
reproducibility of results since the result depends on the
speed of the computer - so that the reader should not be too surprised
if he/she finds other results than those commented hereafter. In this
specific case we also turn to FALSE print.thinmult
as it
would otherwise imply the printing of a much too long output.
out.mcmc.base<-runMCMC_btadjust(code=ModelCode, constants = ModelConsts, data = ModelData, MCMC_language="Nimble",
Nchains=Nchains, params=params, inits=Inits,
niter.min=1000, niter.max=Inf,
nburnin.min=100, nburnin.max=Inf,
thin.min=1, thin.max=Inf,
conv.max=1.05, neff.min=1000,
control=list(neff.method="Coda", time.max=120, print.diagnostics=FALSE,print.thinmult=FALSE),
control.MCMC=list(parallelize=TRUE, n.adapt=1000))
#> [1] "control$seed is NULL. Replaced by 1"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Convergence and trying to reach end of MCMC at the end of next cycle"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "Number of planned new iterations non-positive: end of MCMC cycles"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Main MCMC sampling finished."
#> [1] "###################################################################################"
#> Warning in system.time({: The MCMC did not converge
#> Warning in system.time({: The expected effective sample size was not reached
#> [1] "###################################################################################"
#> [1] "MCMC has NOT reached the required level of convergence."
#> [1] "###################################################################################"
#> [1] "MCMC has NOT reached the required level of effective values."
#> [1] "###################################################################################"
The model finally did not converge and did not reach its required level of number of effective values.
We now use the built-in findMCMC_strong_corrs
function
to identify where the model has problems in terms of
autocorrelation.
knitr::kable(findMCMC_strong_corrs(out.mcmc.base),align="r",caption=paste0("Pairs of parameters that are strongly correlated"))
dimnames(Table)[[1]][Temp[, 1]] | dimnames(Table)[[1]][Temp[, 2]] | Table[Temp] |
---|---|---|
Slope | Intercept | -0.999862 |
Intercept | Slope | -0.999862 |
As expected, there is a very strong negative correlation between
Intercept
and Slope
- this case was indeed
built for this.
We will therefore now try to fit the same model but with a sampler
that allows parameters Intercept and Slope to be correlated. Indeed, so
far, by default, Nimble used independent samplers for each of the
parameters. We will now use a “RW_block” (Random walk block) sampler for
Intercept
and Slope
to be updated together
with a correlated update. This will be done through the component
confModel.expression.toadd
added in the parameter
control.MCMC
of the runMCMC_btadjust
function.
As its name suggests, it will be an expression to add in the step of
model configuration for NIMBLE
- with the
NIMBLE
function configureMCMC
. The syntax is
given below:
sampler.expression.toadd<-expression(
{ConfModel[[i]]$removeSamplers(c("Intercept","Slope"))
ConfModel[[i]]$addSampler(target = c("Intercept","Slope"),type = "RW_block")} )
out.mcmc.RWblock<-runMCMC_btadjust(code=ModelCode, constants = ModelConsts, data = ModelData, MCMC_language="Nimble",
Nchains=Nchains, params=params, inits=Inits,
niter.min=1000, niter.max=Inf,
nburnin.min=100, nburnin.max=Inf,
thin.min=1, thin.max=Inf,
conv.max=1.05, neff.min=1000,
control=list(neff.method="Coda", time.max=120, print.diagnostics=FALSE),
control.MCMC=list(confModel.expression.toadd=sampler.expression.toadd, parallelize=TRUE, n.adapt=1000))
#> [1] "control$seed is NULL. Replaced by 1"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "Number of planned new iterations non-positive: end of MCMC cycles"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Main MCMC sampling finished."
#> [1] "###################################################################################"
#> Warning in system.time({: The MCMC did not converge
#> Warning in system.time({: The expected effective sample size was not reached
#> [1] "###################################################################################"
#> [1] "MCMC has NOT reached the required level of convergence."
#> [1] "###################################################################################"
#> [1] "MCMC has NOT reached the required level of effective values."
#> [1] "###################################################################################"
In this case, we even do not reach convergence. This is confirmed by the traceplot of the Slope parameter (not shown here due to problems with CRAN; you can run the code in the FALSE condition below to see it).
Indeed, the two trajectories are completely separate showing a complete lack of convergence. Such is also the case for the Intercept parameter, but not for poluation.sd. This means that the Random Walk block sampler did even worse than the original samplers. This is very likely due to a note/warning issued by Nimble but which we did not see due to the parallelization, that we can read without it. It reads:
Assigning an RW_block sampler to nodes with very different scales can result in low MCMC efficiency. If all nodes assigned to RW_block are not on a similar scale, we recommend providing an informed value for the "propCov" control list argument, or using the AFSS sampler instead.
We will actually try the second alternative: use the AF slice sampler: this is done in what follows:
sampler.expression.toadd<-expression(
{ConfModel[[i]]$removeSamplers(c("Intercept","Slope"))
ConfModel[[i]]$addSampler(target = c("Intercept","Slope"),type = "AF_slice")} )
out.mcmc.AFslice<-runMCMC_btadjust(code=ModelCode, constants = ModelConsts, data = ModelData, MCMC_language="Nimble",
Nchains=Nchains, params=params, inits=Inits,
niter.min=1000, niter.max=Inf,
nburnin.min=100, nburnin.max=Inf,
thin.min=1, thin.max=Inf,
conv.max=1.05, neff.min=1000,
control=list(neff.method="Coda", time.max=120, print.diagnostics=FALSE),
control.MCMC=list(confModel.expression.toadd=sampler.expression.toadd, parallelize=TRUE, n.adapt=1000))
#> [1] "control$seed is NULL. Replaced by 1"
#> [1] "###################################################################################"
#> [1] "Raw multiplier of thin: 9.497"
#> [1] "###################################################################################"
#> [1] "Testing multiplier of thin: 9 :"
#> [1] "Testing multiplier of thin: 8 :"
#> [1] "Testing multiplier of thin: 7 :"
#> [1] "Testing multiplier of thin: 6 :"
#> [1] "Testing multiplier of thin: 5 :"
#> [1] "Retained multiplier of thin: 5 :"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Convergence and trying to reach end of MCMC at the end of next cycle"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Main MCMC sampling finished."
#> [1] "###################################################################################"
#> [1] "Final max raw multiplier of thin: 1.325"
#> [1] "###################################################################################"
#> [1] "Retained final multiplier of thin: 1"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "MCMC has reached the required level of convergence."
#> [1] "###################################################################################"
#> [1] "MCMC has reached the required level of effective values."
#> [1] "###################################################################################"
This now works very fine with both convergence and reaching the required number of effective values. The estimates are also fine with the true parameters we know, since the true values are within the credibility intervals:
summary(out.mcmc.AFslice)
#>
#> Iterations = 104:5659
#> Thinning interval = 5
#> Number of chains = 2
#> Sample size per chain = 1112
#>
#> 1. Empirical mean and standard deviation for each variable,
#> plus standard error of the mean:
#>
#> Mean SD Naive SE Time-series SE
#> Intercept -0.07618 3.26137 0.0691565 0.0727508
#> Slope 1.00090 0.03260 0.0006912 0.0007272
#> population.sd 1.02866 0.02331 0.0004943 0.0005692
#>
#> 2. Quantiles for each variable:
#>
#> 2.5% 25% 50% 75% 97.5%
#> Intercept -6.3407 -2.1744 -0.2191 2.113 6.514
#> Slope 0.9349 0.9792 1.0025 1.022 1.063
#> population.sd 0.9844 1.0131 1.0277 1.045 1.076
In line with the above, I have recently shifted my practice of block sampling to AF_slice sampler which in my experience behaves nicely in such cases of correlated parameters.
We will in the sequel try two other possibilities provided by Nimble.
The first one is to use an Hamiltonian sampler - similar in principle to
the one provided by STAN
- which is a priori well suited to
such badly behaving cases. This will require rather numerous steps to do
so. First, this will require the loading of the new
nimbleHMC
library as well as modifications of
nimbleOptions
in the component
parallelizeInitExpr
of parameter control.MCMC
;
this is done in what follows in the variable
newParallelizeInitExpr
. Second, we need to refer to the HMC
sampler in the confModel.expression.toadd
component. Third,
we need to turn to TRUE the buildDerivs
component of
parameter control.MCMC
. This actually means that the log
posterior density should be derivable relative to all the parameters to
use this sampler - or at least relative to the parameters on which this
sampler is applied. This is what we now perform:
newParallelizeInitExpr<-expression({
library(nimble)
library(nimbleHMC)
nimbleOptions(MCMCusePredictiveDependenciesInCalculations = TRUE)
nimbleOptions(MCMCorderPosteriorPredictiveSamplersLast = FALSE)
nimbleOptions(enableDerivs = TRUE)
})
sampler.expression.toadd<-expression(
{ConfModel[[i]]$removeSamplers(c("Intercept","Slope"))
nimbleHMC::addHMC(ConfModel[[i]], target=c("Intercept","Slope"))
} )
out.mcmc.HMC<-runMCMC_btadjust(code=ModelCode, constants = ModelConsts, data = ModelData, MCMC_language="Nimble",
Nchains=Nchains, params=params, inits=Inits,
niter.min=1000, niter.max=Inf,
nburnin.min=100, nburnin.max=Inf,
thin.min=1, thin.max=Inf,
conv.max=1.05, neff.min=1000,
control=list(neff.method="Coda", time.max=120, print.diagnostics=FALSE),
control.MCMC=list(confModel.expression.toadd=sampler.expression.toadd, parallelizeInitExpr= newParallelizeInitExpr,buildDerivs=TRUE, parallelize=TRUE, n.adapt=1000))
#> [1] "control$seed is NULL. Replaced by 1"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "Number of planned new iterations non-positive: end of MCMC cycles"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Main MCMC sampling finished."
#> [1] "###################################################################################"
#> Warning in system.time({: The MCMC did not converge
#> Warning in system.time({: The expected effective sample size was not reached
#> [1] "###################################################################################"
#> [1] "MCMC has NOT reached the required level of convergence."
#> [1] "###################################################################################"
#> [1] "MCMC has NOT reached the required level of effective values."
#> [1] "###################################################################################"
With these adaptations, within two minutes, the Hamiltonian Monte Carlo sampler does not go very far; it does not converge and does not reach the required number of effective values. This is due to a longer time per iteration and a longer time of MCMC preparation than with other samplers. The associated summary is given below:
summary(out.mcmc.HMC)
#>
#> Iterations = 100:999
#> Thinning interval = 1
#> Number of chains = 2
#> Sample size per chain = 900
#>
#> 1. Empirical mean and standard deviation for each variable,
#> plus standard error of the mean:
#>
#> Mean SD Naive SE Time-series SE
#> Intercept 0.2880 3.51863 0.0829349 0.252204
#> Slope 0.9973 0.03518 0.0008291 0.002522
#> population.sd 1.0270 0.02326 0.0005482 0.001527
#>
#> 2. Quantiles for each variable:
#>
#> 2.5% 25% 50% 75% 97.5%
#> Intercept -5.9043 -2.0825 0.1268 2.537 7.136
#> Slope 0.9286 0.9748 0.9989 1.021 1.059
#> population.sd 0.9830 1.0143 1.0253 1.043 1.072
effectiveSize(out.mcmc.HMC)
#> Intercept Slope population.sd
#> 200.3512 200.0932 243.8469
Our final try in terms of Nimble samplers will be the Adaptive
Parallel Tempering (Miasojedow et al.
(2013)) provided by the nimbleAPT
library. This is
also a type of sampler that can help adapt tricky situations, especially
multiple local maxima (or near-maxima) of the log posterior density.
This is however unsure turning to APT by itself will be able to treat
the correlation issue we have to deal with. The code to turn to APT is
rather simple - and here we do not have to change the sampler as it is
already included in the component APT=TRUE
of
control.MCMC
. An important characteristic of
nimbleAPT
is that samplers for all parameters should be
within the APT family: it is not possible at present to mix APT and
non-APT samplers for different parameters - we initially wished to
remove the APT sampler from parameter population.sd
and
replace it by the traditional random walk one to be more comparable to
the ones above which also kept the random walk sampler for
population.sd
but this turned out to be impossible.
out.mcmc.APT<-runMCMC_btadjust(code=ModelCode, constants = ModelConsts, data = ModelData, MCMC_language="Nimble",
Nchains=Nchains, params=params, inits=Inits,
niter.min=1000, niter.max=Inf,
nburnin.min=100, nburnin.max=Inf,
thin.min=1, thin.max=Inf,
conv.max=1.05, neff.min=1000,
control=list(neff.method="Coda", time.max=120, print.diagnostics=FALSE),
control.MCMC=list(APT=TRUE, parallelize=TRUE, n.adapt=1000))
#> [1] "control$seed is NULL. Replaced by 1"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "Number of planned new iterations non-positive: end of MCMC cycles"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Main MCMC sampling finished."
#> [1] "###################################################################################"
#> Warning in system.time({: The MCMC did not converge
#> Warning in system.time({: The expected effective sample size was not reached
#> [1] "###################################################################################"
#> [1] "MCMC has NOT reached the required level of convergence."
#> [1] "###################################################################################"
#> [1] "MCMC has NOT reached the required level of effective values."
#> [1] "###################################################################################"
This model did not converge nor allow us to reach the required number of effective values. The traceplot of the Slope parameter indeed indicates a difficulty of convergence, which is however less extreme that in the case of the above (untempered) RW block sampler (not shown here due to problems with CRAN; you can run the code in the FALSE condition below to see it).
By default, when turning APT
to TRUE
,
runMCMC_btadjust
puts a tempered random walk sampler -
called sampler_RW_tempered
- on each of the model’s
parameters. Staying in the realm of APT, we try an additional tempered
sampler provided by the nimbleAPT
library, the tempered
block sampler - called sampler_RW_block_tempered
- instead
of the independent random walk samplers, still through the parameter
confModel.expression.toadd
:
sampler.expression.toadd<-expression(
{ConfModel[[i]]$removeSamplers(c("Intercept","Slope"))
ConfModel[[i]]$addSampler(target = c("Intercept","Slope"),type = "sampler_RW_block_tempered",control=list(temperPriors=FALSE))
})
out.mcmc.blockAPT<-runMCMC_btadjust(code=ModelCode, constants = ModelConsts, data = ModelData, MCMC_language="Nimble",
Nchains=Nchains, params=params, inits=Inits,
niter.min=1000, niter.max=Inf,
nburnin.min=100, nburnin.max=Inf,
thin.min=1, thin.max=Inf,
conv.max=1.05, neff.min=1000,
control=list(neff.method="Coda", time.max=120, print.diagnostics=FALSE),
control.MCMC=list(confModel.expression.toadd=sampler.expression.toadd, APT=TRUE, parallelize=TRUE, n.adapt=1000))
#> [1] "control$seed is NULL. Replaced by 1"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Non convergence"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Raw multiplier of thin: 49.388"
#> [1] "###################################################################################"
#> [1] "Testing multiplier of thin: 49 :"
#> [1] "Retained multiplier of thin: 49 :"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Convergence and trying to reach end of MCMC at the end of next cycle"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Raw multiplier of thin: 2.43"
#> [1] "###################################################################################"
#> [1] "Testing multiplier of thin: 2 :"
#> [1] "Retained multiplier of thin: 2 :"
#> [1] "###################################################################################"
#> [1] "Case of niter update: Convergence and trying to reach end of MCMC at the end of next cycle"
#> [1] "###################################################################################"
#> [1] "Number of planned new iterations non-positive: end of MCMC cycles"
#> [1] "###################################################################################"
#> [1] "###################################################################################"
#> [1] "Main MCMC sampling finished."
#> [1] "###################################################################################"
#> [1] "Final max raw multiplier of thin: 2.43"
#> [1] "###################################################################################"
#> [1] "Testing final multiplier of thin: 2 :"
#> [1] "Retained final multiplier of thin: 1"
#> [1] "###################################################################################"
#> Warning in system.time({: The expected effective sample size was not reached
#> [1] "###################################################################################"
#> [1] "MCMC has reached the required level of convergence."
#> [1] "###################################################################################"
#> [1] "MCMC has NOT reached the required level of effective values."
#> [1] "###################################################################################"
This one converges but does not allow to reach a sufficient number of effective values. The associated summary is given below:
summary(out.mcmc.blockAPT)
#>
#> Iterations = 3268:18115
#> Thinning interval = 49
#> Number of chains = 2
#> Sample size per chain = 304
#>
#> 1. Empirical mean and standard deviation for each variable,
#> plus standard error of the mean:
#>
#> Mean SD Naive SE Time-series SE
#> Intercept -0.1127 3.52162 0.142820 0.2580538
#> Slope 1.0013 0.03521 0.001428 0.0025798
#> population.sd 1.0290 0.02310 0.000937 0.0009378
#>
#> 2. Quantiles for each variable:
#>
#> 2.5% 25% 50% 75% 97.5%
#> Intercept -6.8666 -2.4423 -0.4271 2.231 6.716
#> Slope 0.9331 0.9778 1.0046 1.025 1.069
#> population.sd 0.9828 1.0125 1.0293 1.045 1.071
effectiveSize(out.mcmc.blockAPT)
#> Intercept Slope population.sd
#> 250.4521 250.1634 608.0000
Summaries are fine in this case in the sense that the true parameters are within the credibility intervals.
Let us now compare the different above models in terms of their rapidly analyzed performances (convergence, reaching the number of effective values, duration…).
default | RW.block | Slice.block | HMC | APT | APT.block | |
---|---|---|---|---|---|---|
converged | 0.000e+00 | 0.000e+00 | 1.000e+00 | 0.000e+00 | 0.000e+00 | 1.000e+00 |
neffs.reached | 0.000e+00 | 0.000e+00 | 1.000e+00 | 0.000e+00 | 0.000e+00 | 0.000e+00 |
final.Nchains | 2.000e+00 | 2.000e+00 | 2.000e+00 | 2.000e+00 | 2.000e+00 | 2.000e+00 |
burnin | 1.000e+02 | 1.000e+02 | 1.040e+02 | 1.000e+02 | 1.000e+02 | 3.268e+03 |
thin | 5.600e+01 | 3.800e+01 | 5.000e+00 | 1.000e+00 | 1.700e+01 | 4.900e+01 |
niter.tot | 2.212e+04 | 3.879e+04 | 5.662e+03 | 1.000e+03 | 1.715e+04 | 1.813e+04 |
Nvalues | 4.080e+02 | 2.038e+03 | 2.224e+03 | 1.800e+03 | 2.008e+03 | 6.080e+02 |
neff.min | 6.232e+00 | 1.191e+01 | 1.679e+03 | 2.001e+02 | 1.019e+02 | 2.502e+02 |
neff.median | 6.280e+00 | 3.025e+01 | 2.009e+03 | 2.004e+02 | 1.019e+02 | 2.505e+02 |
duration | 1.441e+02 | 1.504e+02 | 8.736e+01 | 1.424e+02 | 1.415e+02 | 1.383e+02 |
duration.MCMC.preparation | 3.716e+01 | 3.610e+01 | 4.661e+01 | 7.238e+01 | 3.175e+01 | 4.089e+01 |
duration.MCMC.transient | 1.223e+01 | 1.062e+01 | 1.265e+00 | 2.778e+01 | 3.166e+01 | 5.052e+00 |
duration.MCMC.asymptotic | 0.000e+00 | 0.000e+00 | 6.368e+00 | 0.000e+00 | 0.000e+00 | 1.758e+01 |
We notice that 2 methods reached convergence - the block slice sampler and the block APT sampler - but only one reached the required number of effective values: the block slice sampler. On the whole it therefore appears that block slice sampling clearly performs best on this case. The block APT sampler comes second since it converged and reached final numbers of effective values that were far greater than the default setting. The Hamiltonian was stopped soon in terms of number of iterations but its number of effective values was rather promising.
We have here shown how to use the capabilities of
runMCMC_btadjust()
in terms of coupling with
NIMBLE
for changing and controlling MCMC samplers. This is
something that I have found very powerful in various contexts, with also
the possibility to write your own samplers. There are other samplers
provided by Nimble that the user may find useful (cf. Nimble user guide,
Nimble web site: https://r-nimble.org/ and Nimble users mailing list).
This is a real strength of NIMBLE
that
runMCMC_btadjust()
permits to use quite easily.
I wished to thank David Pleydell for help on the package
nimbleAPT
and the NIMBLE
users mailing
list.
The initial development of this package (up to version 1.1.1) was performed within the GAMBAS project funded by the French Agence Nationale pour la Recherche (ANR-18-CE02-0025) (cf. https://gambas.cirad.fr/).