---
# System prepended metadata

title: Bayesian Software Standards
tags: [statistical-software]

---

---
title: Bayesian Software Standards
tags: statistical-software
robots: noindex, nofollow
---


<!-- Edit the .Rmd not the .md file -->

## Bayesian and Monte Carlo Software

Bayesian and Monte Carlo software centres on quantitative estimation of
components of [Baye’s
theorem](https://en.wikipedia.org/wiki/Bayes%27_theorem), particularly
on estimation or application of prior and/or posterior probability
distributions. The procedures implemented to estimate the properties of
such distributions are commonly based on random sampling procedures,
hence referred to as “*Monte Carlo*” routines in reference to the random
yet quantifiable nature of casino games. The scope of this category also
includes algorithms which focus on sampling routines only, such as
Markov-Chain Monte Carlo (MCMC) procedures, independent of application
in Bayesian analyses.

The term “model” is understood with reference here to Bayesian software
to refer to an encoded description of how parameters specifying aspects
of one or more prior distributions are transformed into (properties of)
one or more posterior distributions.

Some examples of Bayesian and Monte Carlo software include:

1.  The [`bayestestR`
    package](https://joss.theoj.org/papers/10.21105/joss.01541) which
    “provides tools to describe … posterior distributions”
2.  The [`ArviZ`
    package](https://joss.theoj.org/papers/10.21105/joss.01143) python
    package for exploratory analyses of Bayesian models, particularly
    posterior distributions.
3.  The [`GammaGompertzCR`
    package](https://joss.theoj.org/papers/10.21105/joss.00216), which
    features explicit diagnostics of MCMC convergence statistics.
4.  The [`BayesianNetwork`
    package](https://joss.theoj.org/papers/10.21105/joss.00425), which
    is in many ways a wrapper package primarily serving a `shiny` app,
    and is also accordingly a package in the EDA category.
5.  The [`fmcmc`
    package](https://joss.theoj.org/papers/10.21105/joss.01427), which
    is a “classic” MCMC package which directly provides its own
    implementation, and generates its own convergence statistics.
6.  The [`rsimsum`
    package](https://joss.theoj.org/papers/10.21105/joss.00739) which
    “summarise\[s\] results from Monte Carlo simulation studies”. Many
    of the statistics generated by this package are useful for assessing
    and comparing Bayesian and Monte Carlo software in general. (See
    also the [`MCMCvis`
    package](https://joss.theoj.org/papers/10.21105/joss.00640), with
    more of a focus on visualisation.)
7.  The [`walkr`
    package](https://joss.theoj.org/papers/10.21105/joss.00061) for
    “MCMC Sampling from Non-Negative Convex Polytopes”. This package is
    also indicative of the difficulties of deriving generally applicable
    assessments of software in this category, because MCMC *sampling*
    relies on fundamentally different inputs and outputs than many other
    MCMC routines.

Click on the following link to view a demonstration [Application of
Bayesian and Monte Carlo
Standards](https://hackmd.io/zVWTAl9ZQeCcj_bvMGcmMQ).

Bayesian and Monte Carlo Software (hereafter referred to for simplicity
as “Bayesian Software”) is presumed to perform one or more of the
following steps:

1.  Document how to specify inputs including:
    -   1.1 Data
    -   1.2 Parameters determining prior distributions
    -   1.3 Parameters determining the computational processes
2.  Accept and validate all of forms of input
3.  Apply data transformation and pre-processing steps
4.  Apply one or more analytic algorithms, generally sampling algorithms
    used to generate estimates of posterior distributions
5.  Return the result of that algorithmic application
6.  Offer additional functionality such as printing or summarising
    return results

This chapter details standards for each of these steps, each prefixed
with “BS”.

### 1 Documentation of Inputs

Prior to actual standards for documentation of inputs, we note one
terminological standard for Bayesian software which uses the term
“hyperparameter”:

-   **BS1.0** *Bayesian software which uses the term “hyperparameter”
    should explicitly clarify the meaning of that term in the context of
    that software.*

This standard reflects the dual facts that this term is frequently used
in Bayesian software, yet has no unambiguous definition or
interpretation. The term “hyperparameter” is also used in other
statistical contexts in ways that are often distinctly different from
its common use in Bayesian analyses. Examples of the kinds of
clarifications required to adhere to this standard include,

> Hyperparameters refer here to parameters determining the form of prior
> distributions that conditionally depend on other parameters.

Such a clarification would then require further explicit distinction
between “parameters” and “hyperparameters”. The remainder of these
standards does not refer to “hyperparameters”, rather attempts to make
explicit distinctions between different kinds of parameters, such as
distributional or algorithmic control parameters. Beyond this standard,
Bayesian Software should provide the following documentation of how to
specify inputs:

-   **BS1.1** *Descriptions of how to enter data, both in textual form
    and via code examples. Both of these should consider the simplest
    cases of single objects representing independent and dependent data,
    and potentially more complicated cases of multiple independent data
    inputs.*
-   **BS1.2** *Description of how to specify prior distributions, both
    in textual form describing the general principles of specifying
    prior distributions, along with more applied descriptions and
    examples, within:*
    -   **B31.2a** *The main package `README`, either as textual
        description or example code*
    -   **B31.2b** *At least one package vignette, both as general and
        applied textual descriptions, and example code*
    -   **B31.2c** *Function-level documentation, preferably with code
        included in examples*
-   **BS1.3** *Description of all parameters which control the
    computational process (typically those determining aspects such as
    numbers and lengths of sampling processes, seeds used to start them,
    thinning parameters determining post-hoc sampling from simulated
    values, and convergence criteria). In particular:*
    -   **BS1.3a** *Bayesian Software should document, both in text and
        examples, how to use the output of previous simulations as
        starting points of subsequent simulations.*
    -   **BS1.3b** *Where applicable, Bayesian software should document,
        both in text and examples, how to use different sampling
        algorithms for a given model.*
-   **BS1.4** *For Bayesian Software which implements or otherwise
    enables convergence checkers, documentation should explicitly
    describe and provide examples of use with and without convergence
    checkers.*
-   **BS1.5** *For Bayesian Software which implements or otherwise
    enables multiple convergence checkers, differences between these
    should be explicitly tested.*

### 2 Input Data Structures and Validation

This section contains standards primarily intended to ensure that input
data, including model specifications, are validated prior to passing
through to the main computational algorithms.

#### 2.1 Input Data

Bayesian Software is commonly designed to accept generic one- or
two-dimensional forms such as vector, matrix, or `data.frame` objects,
for which the following standard applies.

-   **BS2.1** *Bayesian Software should implement pre-processing
    routines to ensure all input data is dimensionally commensurate, for
    example by ensuring commensurate lengths of vectors or numbers of
    rows of tabular inputs.*
    -   **BS2.1a** *The effects of such routines should be tested.*

#### 2.2 Prior Distributions, Model Specifications, and Distributional Parameters

The second set of standards in this section concern specification of
prior distributions, model structures, or other equivalent ways of
specifying hypothesised relationships among input data structures. R
already has a diverse range of Bayesian Software with distinct
approaches to this task, commonly either through specifying a model as a
character vector representing an R function, or an external file either
as R code, or encoded according to some alternative system (such as for
[`rstan`](https://mc-stan.org/rstan/)).

Bayesian Software should:

-   **BS2.2** *Ensure that all appropriate validation and pre-processing
    of distributional parameters are implemented as distinct
    pre-processing steps prior to submitting to analytic routines, and
    especially prior to submitting to multiple parallel computational
    chains.*
-   **BS2.3** *Ensure that lengths of vectors of distributional
    parameters are checked, with no excess values silently discarded
    (unless such output is explicitly suppressed, as detailed below).*
-   **BS2.4** *Ensure that lengths of vectors of distributional
    parameters are commensurate with expected model input (see example
    immediately below)*
-   **BS2.5** *Where possible, implement pre-processing checks to
    validate appropriateness of numeric values submitted for
    distributional parameters; for example, by ensuring that
    distributional parameters defining second-order moments such as
    distributional variance or shape parameters, or any parameters which
    are logarithmically transformed, are non-negative.*

The following example demonstrates how standards like the above
(BS2.4-2.5) might be addressed. Consider the following function which
defines a log-likelihood estimator for a linear regression, controlled
via a vector of three distributional parameters, `p`:

``` r
ll <- function (x, y, p) dnorm (y - (p[1] + x * p[2]), sd = p[3], log = TRUE)
```

Pre-processing stages should be used to determine:

1.  That the dimensions of the input data, `x` and `y`, are commensurate
    (BS2.1); non-commensurate inputs should error by default.
2.  The length of the vector `p` (BS2.3)

The latter task is not necessarily straightforward, because the
definition of the function, `ll()`, will itself generally be part of the
input to an actual Bayesian Software function. This functional input
thus needs to be examined to determine expected lengths of
hyperparameter vectors. The following code illustrates one way to
achieve this, relying on utilities for parsing function calls in R,
primarily through the
[`getParseData`](https://stat.ethz.ch/R-manual/R-devel/library/utils/html/getParseData.html)
function from the `utils` package. The parse data for a function can be
extracted with the following line:

``` r
x <- getParseData (parse (text = deparse (ll)))
```

The object `x` is a `data.frame` of every R token (such as an
expression, symbol, or operator) parsed from the function `ll`. The
following section illustrates how this data can be used to determine the
expected lengths of vector inputs to the function, `ll()`.

<details>
<summary>
click to see details
</summary>
<p>

Input arguments used to define parameter vectors in any R software are
accessed through R’s standard vector access syntax of `vec[i]`, for some
element `i` of a vector `vec`. The parse data for such begins with the
`SYMBOL` of `vec`, the `[`, a `NUM_CONST` for the value of `i`, and a
closing `]`. The following code can be used to extract elements of the
parse data which match this pattern, and ultimately to extract the
various values of `i` used to access members of `vec`.

``` r
vector_length <- function (x, i) {
    xn <- x [which (x$token %in% c ("SYMBOL", "NUM_CONST", "'['", "']'")), ]
    # split resultant data.frame at first "SYMBOL" entry
    xn <- split (xn, cumsum (xn$token == "SYMBOL"))
    # reduce to only those matching the above pattern
    xn <- xn [which (vapply (xn, function (j)
                             j$text [1] == i & nrow (j) > 3,
                             logical (1)))]
    ret <- NA_integer_ # default return value
    if (length (xn) > 0) {
        # get all values of NUM_CONST as integers
        n <- vapply (xn, function (j)
                         as.integer (j$text [j$token == "NUM_CONST"] [1]),
                         integer (1), USE.NAMES = FALSE)
        # and return max of these
        ret <- max (n)
    }
    return (ret)
}
```

That function can then be used to determine the length of any inputs
which are used as hyperparameter vectors:

``` r
ll <- function (p, x, y) dnorm (y - (p[1] + x * p[2]), sd = p[3], log = TRUE)
p <- parse (text = deparse (ll))
x <- utils::getParseData (p)

# extract the names of the parameters:
params <- unique (x$text [x$token == "SYMBOL"])
lens <- vapply (params, function (i) vector_length (x, i), integer (1))
lens
#>  y  p  x 
#> NA  3 NA
```

And the vector `p` is used as a hyperparameter vector containing three
parameters. Any initial value vectors can then be examined to ensure
that they have this same length.

------------------------------------------------------------------------

</p>
</details>

<br>

Not all Bayesian Software is designed to accept model inputs expressed
as R code. The [`rstan` package](https://github.com/stan-dev/rstan), for
example, implements its own model specification language, and only
allows distributional parameters to be named, and not addressed by
index. While this largely avoids problems of mismatched lengths of
parameter vectors, the software (at v2.21.1) does not ensure the
existence of named parameters prior to starting the computational
chains. This ultimately results in each chain generating an error when a
model specification refers to a non-existent or undefined distributional
parameter. Such controls should be part of a single pre-processing
stage, and so should only generate a single error.

#### 2.3 Computational Parameters

Computational parameters are considered here distinct from
distributional parameters, and commonly passed to Bayesian functions to
directly control computational processes. They typically include
parameters controlling lengths of runs, lengths of burn-in periods,
numbers of parallel computations, other parameters controlling how
samples are to be generated, or convergence criteria. All Computational
Parameters should be checked for general “sanity” prior to calling
primary computational algorithms. The standards for such sanity checks
include that Bayesian Software should:

-   **BS2.6** *Check that values for computational parameters lie within
    plausible ranges.*

While admittedly not always possible to define, plausible ranges may be
as simple as ensuring values are greater than zero. Where possible,
checks should nevertheless ensure appropriate responses to extremely
large values, for example by issuing diagnostic messages about likely
long computational times. The following two sub-sections consider
particular cases of computational parameters.

#### 2.4 Parameters Controlling Start Values

Bayesian software generally relies on sequential random sampling
procedures, with each sequence uniquely determined by (among other
aspects) the value at which it is started. Given that, Bayesian software
should:

-   **BS2.7** *Enable starting values to be explicitly controlled via
    one or more input parameters, including multiple values for software
    which implements or enables multiple computational “chains.”*
-   **BS2.8** *Enable results of previous runs to be used as starting
    points for subsequent runs.*

Bayesian Software which implements or enables multiple computational
chains should:

-   **BS2.9** *Ensure each chain is started with a different seed by
    default.*
-   **BS2.10** *Issue diagnostic messages when identical seeds are
    passed to distinct computational chains.*
-   **BS2.12** *Software which accepts starting values as a vector
    should provide the parameter with a plural name: for example,
    “starting\_values” and not “starting\_value”.*

To avoid potential confusion between separate parameters to control
random seeds and starting values, we recommended a single “starting
values” rather than “seeds” argument, with appropriate translation of
these parameters into seeds where necessary.

#### 2.5 Output Verbosity

All Bayesian Software should implement computational parameters to
control output verbosity. Bayesian computations are often
time-consuming, and often performed as batch computations. The following
standards should be adhered to in regard to output verbosity:

-   **BS2.13** *Bayesian Software should implement at least one
    parameter controlling the verbosity of output, defaulting to verbose
    output of all appropriate messages, warnings, errors, and progress
    indicators.*
-   **BS2.14** *Bayesian Software should enable suppression of messages
    and progress indicators, while retaining verbosity of warnings and
    errors. This should be tested.*
-   **BS2.15** *Bayesian Software should enable suppression of warnings
    where appropriate. This should be tested.*
-   **BS2.16** *Bayesian Software should explicitly enable errors to be
    caught, and appropriately processed either through conversion to
    warnings, or otherwise captured in return values. This should be
    tested.*

### 3 Pre-processing and Data Transformation

#### 3.1 Missing Values

In additional to the *General Standards* for missing values
(**G2.13**–**2.16**), and in particular **G2.13**, Bayesian Software
should:

-   **BS3.0** *Explicitly document assumptions made in regard to missing
    values; for example that data is assumed to contain no missing
    (`NA`, `Inf`) values, and that such values, or entire rows including
    any such values, will be automatically removed from input data.*

#### 3.2 Perfect Collinearity

Where appropriate, Bayesian Software should:

-   **BS3.1** *Implement pre-processing routines to diagnose perfect
    collinearity, and provide appropriate diagnostic messages or
    warnings*
-   **BS3.2** *Provide distinct routines for processing perfectly
    collinear data, potentially bypassing sampling algorithms*

An appropriate test for **BS3.2** would confirm that `system.time()` or
equivalent timing expressions for perfectly collinear data should be
*less* than equivalent routines called with non-collinear data.
Alternatively, a test could ensure that perfectly collinear data passed
to a function with a stopping criteria generated no results, while
specifying a fixed number of iterations may generate results.

### 4 Analytic Algorithms

As mentioned, analytic algorithms for Bayesian Software are commonly
algorithms to simulate posterior distributions, and to draw samples from
those simulations. Numerous extant R packages implement and offer
sampling algorithms, and not all Bayesian Software will internally
implement sampling algorithms. The following standards apply to packages
which do implement internal sampling algorithms:

-   **BS4.0** *Packages should document sampling algorithms (generally
    via literary citation, or reference to other software)*
-   **BS4.1** *Packages should provide explicit comparisons with
    external samplers which demonstrate intended advantage of
    implementation (generally via tests, vignettes, or both).*

Regardless of whether or not Bayesian Software implements internal
sampling algorithms, it should:

-   **BS4.2** *Implement at least one means to validate posterior
    estimates.*

An example of posterior validation is the [Simulation Based
Calibration](https://arxiv.org/abs/1804.06788) approach implemented in
the [`rstan`](https://mc-stan.org/rstan) function
[`sbc`](https://mc-stan.org/rstan/reference/sbc.html)). (Note also that
the [`BayesValidate`
package](https://cran.r-project.org/package=BayesValidate) has not been
updated for almost 15 years, so should not be directly used, although
ideas from that package may be adapted for validation purposes.) Beyond
this, where possible or applicable, Bayesian Software should:

-   **BS4.3** *Implement or otherwise offer at least one type of
    convergence checker, and provide a documented reference for that
    implementation.*
-   **BS4.3** *Enable computations to be stopped on convergence
    (although not necessarily by default).*
-   **BS4.5** *Ensure that appropriate mechanisms are provided for
    models which do not converge.*

This is often achieved by having default behaviour to stop after
specified numbers of iterations regardless of convergence.

-   **BS4.6** *Implement tests to confirm that results with convergence
    checker are statistically equivalent to results from equivalent
    fixed number of samples without convergence checking.*
-   **BS4.7** *Where convergence checkers are themselves parametrised,
    the effects of such parameters should also be tested. For threshold
    parameters, for example, lower values should result in longer
    sequence lengths.*

### 5 Return Values

Unlike software in many other categories, Bayesian Software should
generally return several kinds of distinct data, both the raw data
derived from statistical algorithms, and associated metadata. Such
distinct and generally disparate forms of data will be generally best
combined into a single object through implementing a defined class
structure, although other options are possible, including (re-)using
extant class structures (see the CRAN Task view on [Bayesian
Inference](https://cran.r-project.org/web/views/Bayesian.html) for
reference to other packages and class systems). Regardless of the
precise form of return object, and whether or not defined class
structures are used or implemented, the following standards apply:

-   **BS5.0** *Return values should include starting value(s) or
    seed(s), including values for each sequence where multiple sequences
    are included*
-   **BS5.1** *Return values should include appropriate metadata on
    types (or classes) and dimensions of input data*

The latter standard may also include returning a unique hash computed
from the input data, to enable results to be uniquely associated with
that input data. With regard to the input function, or alternative means
of specifying prior distributions:

-   **BS5.2** *Bayesian Software should either return the input function
    or prior distributional specification in the return object; or
    enable direct access to such via additional functions which accept
    the return object as single argument.*

Where convergence checkers are implemented or provided:

-   **BS5.3** *Bayesian Software should return convergence statistics or
    equivalent*
-   **BS5.4** *Where multiple checkers are enabled, Bayesian Software
    should return details of convergence checker used*
-   **BS5.5** *Appropriate diagnostic statistics to indicate absence of
    convergence should either be returned or immediately able to be
    accessed.*

### 6 Additional Functionality

With regard to additional methods implemented for, or dispatched on,
return objects:

-   **BS6.0** *Software should implement a default `print` method for
    return objects*
-   **BS6.1** *Software should implement a default `plot` method for
    return objects*
-   **BS6.2** *Software should provide and document straightforward
    abilities to plot sequences of posterior samples, with burn-in
    periods clearly distinguished*
-   **BS6.3** *Software should provide and document straightforward
    abilities to plot posterior distributional estimates*

Beyond these points:

-   **BS6.4** *Software may provide `summary` methods for return
    objects*
-   **BS6.5** *Software may provide abilities to plot both sequences of
    posterior samples and distributional estimates together in single
    graphic*

### 7 Tests

#### 7.1 Parameter Recovery Tests

Bayesian software should implement the following parameter recovery
tests:

-   **BS7.0** *Software should demonstrate and confirm recovery of
    parametric estimates of a prior distribution*
-   **BS7.1** *Software should demonstrate and confirm recovery of a
    prior distribution in the absence of any additional data or
    information*
-   **BS7.2** *Software should demonstrate and confirm recovery of a
    expected posterior distribution given a specified prior and some
    input data*

#### 7.2 Algorithmic Scaling Tests

-   **BS7.3** *Bayesian software should include tests which demonstrate
    and confirm the scaling of algorithmic efficiency with sizes of
    input data.*

An example of adhering to this standard would be documentation or tests
which demonstrate or confirm that computation times increase
approximately logarithmically with increasing sizes of input data.

#### 7.3 Scaling of Input to Output Data

-   **BS7.4** *Bayesian software should implement tests which confirm
    that predicted or fitted values are on (approximately) the same
    scale as input values.*
    -   **BS7.4a** *The implications of any assumptions on scales on
        input objects should be explicitly tested in this context; for
        example that the scales of inputs which do not have means of
        zero will not be able to be recovered.*
