The samplr package

Lucas Castillo

University of Warwick

C. Stella Qian

University of Warwick

Adam N. Sanborn

University of Warwick

Overview of the package

The samplr package is an R package available on CRAN. With it, you can:

  • use MCMC algorithms
  • use the Autocorrelated Bayesian Sampler model (Zhu et al., 2024)
  • calculate some useful statistics that help with model inference.

Documentation

The package documentation lives at https://lucas-castillo.github.io/samplr/

Prerequisites

install.packages("samplr")
library(samplr)

Metropolis Hastings

sampler_mh(
  start = 1,
  distr_name = "norm",
  distr_params = c(0, 1),
  sigma_prop = .1,
  iterations = 1e4
)

Documentation

You can access function documentation by prepending a function with ?, i.e. ?sampler_mh

Sampling from Metropolis Hastings

  1. Use sampler_mh() to generate samples from a Normal distribution \(\mu=3; \sigma^2=5\)
  2. Same as above, but with a large proposal width (\(\sigma^2_{prop} = 10\)). How does the acceptance rate change?
  3. Use sampler_mh() to generate samples from a Beta distribution \(\alpha = 4, \beta = 4\)

Quick Start

Use the 2.samplr.R file for a quick implementation.

Sampling from Metropolis Hastings (my solutions #1)

Use sampler_mh() to generate samples from a Normal distribution \(\mu=3; \sigma^2=5\)

sampler_mh(
  start = 0, 
  distr_name = "norm", 
  distr_params = c(3, sqrt(5))
)

Sampling from Metropolis Hastings (my solutions #2)

Same as above, but with a large proposal width (\(\sigma^2_{prop} = 10\)). How does the acceptance rate change?

set.seed(1)
sampler_mh(
  start = 0, 
  distr_name = "norm", 
  distr_params = c(3, sqrt(5)), 
  sigma_prop = 1
)$`Acceptance Ratio`
[1] 0.8631476
set.seed(1)
sampler_mh(
  start = 0, 
  distr_name = "norm", 
  distr_params = c(3, sqrt(5)), 
  sigma_prop = 10
)$`Acceptance Ratio`
[1] 0.5845552

Sampling from Metropolis Hastings (my solutions #2)

Sampling from Metropolis Hastings (my solutions #2)

\(\sigma^2_{prop} = .01\) after 1000 iterations

\(\sigma^2_{prop} = 100\) after 1000 iterations

Note

For a Gaussian, the ideal acceptance rate is .234

Clarifying sigma..

Warning

Notice that:

  • distr_params for distr_name = "norm" uses sd
  • the proposal width is given as variance
sampler_mh(
  start = 0, 
  distr_name = "norm",
  distr_params = c(0, 2), 
  sigma_prop = 4
)

⬆️ Equal proposal width and target width

Sampling from Metropolis Hastings (my solutions #3)

Use sampler_mh() to generate samples from a Beta distribution \(\alpha = 4, \beta = 4\)

sampler_mh(
  start = 0, 
  distr_name = "beta", 
  distr_params = c(4,4)
)

Further Reading

From samples to responses – Anchoring

Lieder et al. (2018) use MCMC to provide an explanation of anchoring as resource-rational allocation of resources.

The anchoring effect

Strack & Mussweiler (1997)

How tall is the Cathedral in Cologne?

  • One group (high anchor):
    1. Is the cathedral taller than 320m?
    2. How tall is the cathedral?
  • Another group (low anchor):
    1. Is the cathedral taller than 60m?
    2. How tall is the cathedral?

Mean answers: \(\bar x_{high} = 273;\bar x_{low} = 89\)

Lieder et al. (2018)

  • This is because people adjust the anchor in an MCMC way
  • Sampling takes effort so after some time they stop (as extra sampling is more costly than estimate improvement)

From samples to responses – Anchoring

Target distribution

  • The true height of the cathedral is 157m
  • Probably very uncertain \(\rightarrow \mathcal N (\mu=157, \sigma=30)\)
  • Let’s fix sigma_prop = 20
  • Start point is either start=320 or start=60
  • Mean answers: \(\bar x_{high} = 273;\bar x_{low} = 89\)

Replicating the effect

  • Make the last sample the response
  • How many samples are needed to replicate the effect in both groups?
  • How do the sd of the target and the proposal variance influence the result?
  • Is there a situation where response=last sample might not make much sense?

From samples to responses – Anchoring (my solution)

set.seed(1)
starts <- c(60, 320)

target_sd <- 30
proposal_variance <- 20
n.max <- 200 # maximum number of samples we're going to test

# Initialise vector
responses <- c()

# Loop over starting points
for (start in starts){
  # loop over possible n values
  for (n in 1:n.max){
    samples <- sampler_mh(
      start = start, 
      distr_name = "norm", 
      distr_params = c(157, target_sd), 
      sigma_prop = proposal_variance, 
      iterations = n
    )$Samples[n] # choose the nth sample
    
    # add samples to vector
    responses <- c(responses, samples)
  }
}

Is there a situation where response=last sample might not make much sense?

  • When starting point influence disappears, mean of samples is a better estimate (burn-in).

Other MCMC algorithms in the package

Sampling Functions

Qualitative Features

3 qualitative features

Their inclusion or exclusion makes 8 algorithms in total (\(2^3\)).

Qualitative Features:

  • Multiple Chains
  • Gradient-based proposals
  • Autocorrelated proposals

In the next slides…

  • Overview of the features
  • Why they might be useful

For technical detail

  • See appendix of Castillo et al. (2025)
  • See package reference

Multiple Chains

The basic idea

Have more than one chain running at the same time (Geyer, 1991)

First chain (cold chain) exactly like MH

Other chains have higher temperature (more likely to accept)

Sometimes chains swap positions (if the colder of the two is “happy” with the new place)

End: only consider cold chain. (in the package, take the first slice: samples[,,1])

Gradient-based proposals

The basic idea

Don’t make “blind” proposals, but base them on the gradient of the target density (Neal, 2011)

This increases acceptance rate without being stuck in a location.

Achieved by simulating a physical system with random momentum in each iteration. (simulate \(L\) steps of size [precision] \(\epsilon\))

Autocorrelated proposals

In MH,

  • \(\theta^{t'} = \theta^{t-1} + n; n \sim \mathcal N (0, \sigma)\)

In Gradient-based proposals:

  • \(\rho \sim \mathcal N (0, 1)\)

This can lead to random-walk behaviour which is inefficient sometimes

Instead, recycle the previous jump to get a sense of trajectory.

Qualitative Features

Algorithm samplr function M. Chains Gradients Autoc. Proposals
Metropolis Hastings (MH) (Hastings, 1970) sampler_mh()
Metropolis-coupled MCMC (MC\(^3\)) (Geyer, 1991) sampler_mc3()
Hamiltonian Monte Carlo (HMC) (Neal, 2011) sampler_hmc()
RECMH* sampler_mh(alpha=)
MCHMC sampler_mchmc()
RECMC3* sampler_mc3(alpha=)
RECHMC (Horowitz, 1991) sampler_rec()
MCREC sampler_mcrec()

* Use these algorithms by setting the alpha parameter to a value other than 0 in the sampler_mh() and sampler_mc3() functions respectively.

Note

These names appear in the Glossary

Practice

Consider the distribution

names <- rep("norm", 2)
parameters <- list(c(-2, .25), c(2, .25))
weights <- rep(.5, 2)

Choose an algorithm other than MH and draw samples from the distribution.

My answer

sampler_*(
  start = -2, 
  distr_name = names, 
  distr_params = parameters, 
  weights = weights
)
# Metropolis Hastings
sampler_mh(
  start = -2, 
  distr_name = names, 
  distr_params = parameters, 
  weights = weights,
  sigma_prop = .5
)$Samples[,1]
# MC3
sampler_mc3(
  start = -2, 
  distr_name = names, 
  distr_params = parameters, 
  weights = weights,
  sigma_prop = .5, 
  nChains = 6
)$Samples[,,1] # first slice
# HMC
sampler_hmc(
  start = -2, 
  distr_name = names, 
  distr_params = parameters, 
  weights = weights,
  epsilon = .1,  
  L = 10 
)$Samples[,1]
# REC
sampler_rec(
  start = -2, 
  distr_name = names, 
  distr_params = parameters, 
  weights = weights,
  epsilon = .1,  
  L = 10, 
  alpha = .4 
)$Samples[,1]
# MCREC
sampler_mcrec(
  start = -2, 
  distr_name = names, 
  distr_params = parameters, 
  weights = weights,
  nChains = 6, 
  epsilon = .1,  
  L = 10, 
  alpha = .4 
)$Samples[,,1] # first slice

References

Castillo, L., Li, Y.-X., & Sanborn, A. N. (2025). The samplr package: A tool for modeling human cognition with sampling algorithms. https://doi.org/10.31234/osf.io/ax8hm_v2
Geyer, C. J. (1991). Markov Chain Monte Carlo Maximum Likelihood. Proc. 23rd Symposium on the Interface Interface Foundation, Fairfax Station, 1991, 156–163.
Hastings, W. K. (1970). Monte Carlo sampling methods using Markov chains and their applications. Biometrika, 57(1), 97–109. https://doi.org/10.1093/biomet/57.1.97
Horowitz, A. M. (1991). A Generalized Guided Monte Carlo Algorithm. Physics Letters B, 268(2), 247–252. https://doi.org/10.1016/0370-2693(91)90812-5
Lieder, F., Griffiths, T. L., M. Huys, Q. J., & Goodman, N. D. (2018). The anchoring bias reflects rational use of cognitive resources. Psychonomic Bulletin & Review, 25(1), 322–349. https://doi.org/10.3758/s13423-017-1286-8
Neal, R. M. (2011). MCMC Using Hamiltonian Dynamics. In S. Brooks, A. Gelman, G. Jones, & X.-L. Meng (Eds.), Handbook of Markov Chain Monte Carlo (1st ed., pp. 113–162). Chapman and Hall/CRC. https://doi.org/10.1201/b10905
Strack, F., & Mussweiler, T. (1997). Explaining the enigmatic anchoring effect: Mechanisms of selective accessibility. Journal of Personality and Social Psychology, 73(3), 437–446. https://doi.org/10.1037/0022-3514.73.3.437
Zhu, J.-Q., Sundh, J., Spicer, J., Chater, N., & Sanborn, A. N. (2024). The autocorrelated Bayesian sampler: A rational process for probability judgments, estimates, confidence intervals, choices, confidence judgments, and response times. Psychological Review, 131(2), 456–493. https://doi.org/10.1037/rev0000427