Nothing
#' @title calcprior return the sum of a vector of constant values as priors
#'
#' @description calcprior is used to include a prior probability into
#' Bayesian calculations. calcprior is a template for generating
#' such priors. The default given here is to return a constant
#' small number for the prior probability, it needs to sum to 1.0
#' across the replicates returned by do_MCMC. If non-uniform priors
#' are required write a different function and in do_MCMC point
#' priorcalc at it. Whatever function you define needs to have the
#' same input parameters as this calcprior, i.e. the parameters
#' and N. If something else if required then do_MCMC will need
#' modification in the two places where priorcalc is used. Alternatively,
#' the ellipsis, ..., might be used.
#'
#' @param pars the parameters of the model being examined by the MCMC
#' @param N the number of replicate parameter vectors to be returned from
#' do_MCMC, remember to include the burn-in replicates
#'
#' @return the sum of a vector of small constant values to act as priors.
#' @export
#'
#' @examples
#' param <- log(c(0.4,9400,3400,0.05))
#' calcprior(pars=param,N=20000) # should give -39.61395
calcprior <- function(pars,N) { # return log(1/N) for all values entered.
return(sum(rep(log(1/N),length(pars))))
}
#' @title do_MCMC conducts an MCMC using Gibbs within Metropolis
#'
#' @description do_MCMC conducts a Gibbs within Metropolis algorithm. One
#' can define the number of chains, the burnin before candidate
#' parameter vectors and associated probabilities are stored, the total
#' number of candidate vectors to keep and the step or thinning rate
#' between accepting a result into the Markov Chain. One needs to
#' input three functions: 1) 'infunk' to calculate the likelihoods,
#' 2) 'calcpred' used within 'infunk' to calculate the predicted values
#' used to compare with the observed (found in 'obsdat'), and
#' 3) 'priorcalc' used to calculate the prior probabilities of the
#' various parameters in each trial. (N + burnin) * thinstep iterations
#' are made in total although only N are stored. The jumping
#' function uses random normal deviates (mean=0, sd=1) to combine with
#' each parameter value (after multiplication by the specific scaling
#' factor held in the scales argument). Determination of suitable scaling
#' values is generally done empirically, perhaps by trialing a small number
#' of iterations to begin with. Multiple chains would be usual and
#' the thinstep would be larger eg. 128, 256, or 512, but it would
#' take 8, 16, or 32 times longer, depending on the number of parameters,
#' these numbers are for four parameters only. The scales are usually
#' empirically set to obtain an acceptance rate between 20 - 40%.
#' It is also usual to run numerous diagnostic plots on the outputs
#' to ensure convergence onto the final stationary distribution. There
#' are three main loops: 1) total number of iterations (N + burnin)*
#' thinstep, used by priorcalc, 2) thinstep/(number of parameters)
#' so that at least all parameters are stepped through at least once
#' (thinstep = np) before any combinations are considered for
#' acceptance, this means that the true thinning rate is thinstep/np,
#' and 3) the number of parameters loop, that steps through the np
#' parameters varying each one, one at a time.
#'
#' @param chains the number of independent MCMC chains produced
#' @param burnin the number of steps made before candidate parameter
#' vectors begin to be kept.
#' @param N the total number of posterior parameter vectors retained
#' @param thinstep the number of interations before a vector is kept; must
#' be divisible by the number of parameters
#' @param inpar the initial parameter values (usually log-transformed)
#' @param infunk the function used to calculate the negative log-likelihood
#' @param calcpred the function used by infunk to calculate the predicted
#' values for comparison with obsdat; defaults to simpspm.
#' @param calcdat the data used by calcpred to calculate the predicted
#' values
#' @param obsdat the observed data (on the same scale as the predicted, ie
#' usually log-transformed), against with the predicted values are compared.
#' @param priorcalc a function used to calculate the prior probability for
#' each of the parameters in each trial parameter vector.
#' @param scales The re-scaling factors for each parameter to convert the
#' normal random deviates into +/- values on a scale that leads to
#' acceptance rates of between 20 and 40percent.
#' @param ... needed by the simpspm function = calcpred
#'
#' @return a list of the result chains, the acceptance and rejection rates
#' @export
#'
#' @examples
#' data(abdat); fish <- as.matrix(abdat) # to increase speed
#' param <- log(c(0.4,9400,3400,0.05))
#' N <- 500 # usually very, very many more 10s of 1000s
#' result <- do_MCMC(chains=1,burnin=20,N=N,thinstep=8,inpar=param,
#' infunk=negLL,calcpred=simpspm,calcdat=fish,
#' obsdat=log(fish[,"cpue"]),priorcalc=calcprior,
#' scales=c(0.06,0.05,0.06,0.42))
#' # a thinstep of 8 is whofully inadequate, see the runs in the plots
#' cat("Acceptance Rate = ",result[[2]],"\n")
#' cat("Failure Rate = ",result[[3]],"\n")
#' oldpar <- par(no.readonly=TRUE)
#' #plotprep(width=6,height=5,newdev=FALSE)
#' out <- result[[1]][[1]] # get the list containing the matrix
#' pairs(out[,1:4],col=rgb(1,0,0,1/5)) # adjust the 1/5 to suit N
#'
#' parset(plots=c(1,2)) # Note the serial correlation in each trace
#' plot1(1:N,out[,1],ylab="r",xlab="Replicate",defpar=FALSE)
#' plot1(1:N,out[,2],ylab="K",xlab="Replicate",defpar=FALSE)
#' par(oldpar)
do_MCMC <- function(chains,burnin,N,thinstep,inpar,infunk,calcpred,
calcdat,obsdat,priorcalc,scales,...) {
totN <- N + burnin # total number of replicate steps
result <- vector("list",chains) # to store all results
for (ch in 1:chains) { # ch=1
param <- inpar # initiate the chain from here to next for loop
np <- length(param) # Number of parameters
if (ch > 1) param <- param + (rnorm(np) * scales) #change start pt
if ((thinstep %% np) != 0) # thinstep must be divisible by np
stop("Thinning step must be a multiple of number of parameters")
stepnp <- thinstep/np
posterior <- matrix(0,nrow=totN,ncol=(np+1))
colnames(posterior) <- c("r","K","Binit","sigma","Post")
arate <- numeric(np) # to store acceptance rate
func0 <- exp(-infunk(param,calcpred,indat=calcdat,obsdat,...)
+ priorcalc(np,totN)) #back transform log-likelihoods
posterior[1,] <- c(exp(param),func0) # start the chain
for (iter in 2:totN) { # Generate the Markov Chain
randinc <- matrix(rnorm(thinstep,mean=0,sd=1),nrow=stepnp,ncol=np)
for (i in 1:np) randinc[,i] <- randinc[,i] * scales[i]
for (st in 1:stepnp) {
uniform <- runif(np)
for (i in 1:np) { # loop through parameters
oldpar <- param[i] # incrementing them one a at time
param[i] <- param[i] + randinc[st,i]
func1 <- exp(-infunk(param,calcpred,indat=calcdat,obsdat,...)
+ priorcalc(np,totN))
if (func1/func0 > uniform[i]) { # Accept
func0 = func1
arate[i] = arate[i] + 1
} else { # Reject
param[i] <- oldpar
}
} # end of parameter loop
} # end of thinstep loop
posterior[iter,] <- c(exp(param),func0)
} # end of Markov Chain generation; now remove burn-in and rescale
posterior <- posterior[(burnin+1):totN,] # to a post probability
posterior[,"Post"] <- posterior[,"Post"]/sum(posterior[,"Post"])
result[[ch]] <- posterior
} # end of chains loop
P_arate=arate/((N+burnin-1)*thinstep/np)
return(list(result=result,arate=P_arate,frate=1-P_arate))
} # end of do_MCMC
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.