1 Banana log-target density

The target density for \((x,y)\) is given by \[ p(x,y) \propto \exp\{-0.5[x^2+(y-bx^2]^2)\}. \]

# Banana log-density
logp = function(xx) {
  b = 2
  x = xx[1]
  y = xx[2]
  return(-0.5*(x^2+(y-b*x^2)^2))
}

N    = 200
x    = seq(-3,3,length=N)
y    = seq(-3,10,length=N)
post = matrix(0,N,N)
for (i in 1:N)
  for (j in 1:N)
    post[i,j] = logp(c(x[i],y[j]))

par(mfrow=c(1,1))
contour(x,y,exp(post),drawlabels=FALSE,xlab="x",ylab="y",main="Target distribution")

2 Metropolis-Hastings sampler

metropolis = function(logp,start=c(0,0),iter=niter,warmup=burnin,proposal_sd=0.4,seed=123){
  samples     = matrix(0,iter,2)
  samples[1,] = start
  logp_curr   = logp(start)
  
  for (i in 2:iter) {
    proposal    =  rnorm(2,samples[i-1,],proposal_sd)
    logp_prop   = logp(proposal)
    accept_prob = exp(logp_prop - logp_curr)
    
    if (runif(1) < accept_prob) {
      samples[i,] = proposal
      logp_curr   = logp_prop
    } else {
      samples[i,] = samples[i-1,]
    }
  }
  samples[(warmup+1):iter,]
}

seed = 31416
set.seed(seed)
niter  = 20000
burnin = 10000
M      = niter - burnin

mh_samples = metropolis(logp)

2.1 Trace plots and ACF plots

par(mfrow=c(2,2))
ts.plot(mh_samples[,1],xlab="Iterations",ylab="x",main="Metropolis-Hastings")
acf(mh_samples[,1],main="")
ts.plot(mh_samples[,2],xlab="Iterations",ylab="y")
acf(mh_samples[,2],main="")

2.2 Target draws

par(mfrow=c(1,1))
xrange = range(mh_samples[,1],x)
yrange = range(mh_samples[,2],y)
plot(mh_samples, pch=16, cex=0.3, main="Metropolis-Hastings",xlab="x",ylab="y",
     xlim=xrange,ylim=yrange)
contour(x,y,exp(post),add=TRUE,col=2,lwd=2)

2.3 Effective sample size

ESS.mh = c(M/sum(acf(mh_samples[,1],plot=FALSE)$acf^2),M/sum(acf(mh_samples[,2],plot=FALSE)$acf^2))
c(M,round(ESS.mh))
## [1] 10000   696   375

3 Hamiltonian Monte Carlo

library(rstan)
## Loading required package: StanHeaders
## 
## rstan version 2.32.7 (Stan version 2.32.2)
## For execution on a local, multicore CPU with excess RAM we recommend calling
## options(mc.cores = parallel::detectCores()).
## To avoid recompilation of unchanged Stan programs, we recommend calling
## rstan_options(auto_write = TRUE)
## For within-chain threading using `reduce_sum()` or `map_rect()` Stan functions,
## change `threads_per_chain` option:
## rstan_options(threads_per_chain = 1)
stan_code = "
data {
  int<lower=0> N;
}
parameters {
  real x;
  real y;
}
model {
  real b = 2;
  x ~ normal(0, 1);
  y ~ normal(b * x^2, 1);
}
"

3.1 Compiling and sampling

sm = stan_model(model_code = stan_code)

fit = sampling(sm,data=list(N=1),iter=niter,warmup=burnin,chains=1,seed=seed)
## 
## SAMPLING FOR MODEL 'anon_model' NOW (CHAIN 1).
## Chain 1: 
## Chain 1: Gradient evaluation took 5e-06 seconds
## Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0.05 seconds.
## Chain 1: Adjust your expectations accordingly!
## Chain 1: 
## Chain 1: 
## Chain 1: Iteration:     1 / 20000 [  0%]  (Warmup)
## Chain 1: Iteration:  2000 / 20000 [ 10%]  (Warmup)
## Chain 1: Iteration:  4000 / 20000 [ 20%]  (Warmup)
## Chain 1: Iteration:  6000 / 20000 [ 30%]  (Warmup)
## Chain 1: Iteration:  8000 / 20000 [ 40%]  (Warmup)
## Chain 1: Iteration: 10000 / 20000 [ 50%]  (Warmup)
## Chain 1: Iteration: 10001 / 20000 [ 50%]  (Sampling)
## Chain 1: Iteration: 12000 / 20000 [ 60%]  (Sampling)
## Chain 1: Iteration: 14000 / 20000 [ 70%]  (Sampling)
## Chain 1: Iteration: 16000 / 20000 [ 80%]  (Sampling)
## Chain 1: Iteration: 18000 / 20000 [ 90%]  (Sampling)
## Chain 1: Iteration: 20000 / 20000 [100%]  (Sampling)
## Chain 1: 
## Chain 1:  Elapsed Time: 0.059 seconds (Warm-up)
## Chain 1:                0.071 seconds (Sampling)
## Chain 1:                0.13 seconds (Total)
## Chain 1:
## Warning: There were 15 divergent transitions after warmup. See
## https://mc-stan.org/misc/warnings.html#divergent-transitions-after-warmup
## to find out why this is a problem and how to eliminate them.
## Warning: Examine the pairs() plot to diagnose sampling problems
posterior = as.data.frame(fit)

3.2 Trace plots and ACF plots

par(mfrow=c(2,2))
ts.plot(posterior$x,xlab="Iterations",ylab="x",main="Hamiltonian MC")
acf(posterior$x,main="")
ts.plot(posterior$y,xlab="Iterations",ylab="y")
acf(posterior$y,main="")

3.3 Target draws

par(mfrow=c(1,1))
plot(posterior$x, posterior$y, pch=16, cex=0.3,main="HMC (Stan)",xlab="x",ylab="y")
contour(x,y,exp(post),add=TRUE,col=2,lwd=2)

3.4 Effective sample size

ESS.hmc = c(M/sum(acf(posterior$x,plot=FALSE)$acf^2),M/sum(acf(posterior$y,plot=FALSE)$acf^2))
c(M,round(ESS.hmc))
## [1] 10000  2642  2500
LS0tCnRpdGxlOiAiQmFuYW5hLWxvZy10YXJnZXQgZGVuc2l0eSIKc3VidGl0bGU6ICJNZXRyb3BvbGlzLUhhc3RpbmdzIHZzIEhhbWlsdG9uaWFuIE1DIgphdXRob3I6ICJIZWRpYmVydCBGcmVpdGFzIExvcGVzIgpkYXRlOiAiMTEvMTEvMjAyNSIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6ICczJwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKCiMgQmFuYW5hIGxvZy10YXJnZXQgZGVuc2l0eQpUaGUgdGFyZ2V0IGRlbnNpdHkgZm9yICQoeCx5KSQgaXMgZ2l2ZW4gYnkKJCQKcCh4LHkpIFxwcm9wdG8gXGV4cFx7LTAuNVt4XjIrKHktYnheMl1eMilcfS4KJCQKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KIyBCYW5hbmEgbG9nLWRlbnNpdHkKbG9ncCA9IGZ1bmN0aW9uKHh4KSB7CiAgYiA9IDIKICB4ID0geHhbMV0KICB5ID0geHhbMl0KICByZXR1cm4oLTAuNSooeF4yKyh5LWIqeF4yKV4yKSkKfQoKTiAgICA9IDIwMAp4ICAgID0gc2VxKC0zLDMsbGVuZ3RoPU4pCnkgICAgPSBzZXEoLTMsMTAsbGVuZ3RoPU4pCnBvc3QgPSBtYXRyaXgoMCxOLE4pCmZvciAoaSBpbiAxOk4pCiAgZm9yIChqIGluIDE6TikKICAgIHBvc3RbaSxqXSA9IGxvZ3AoYyh4W2ldLHlbal0pKQoKcGFyKG1mcm93PWMoMSwxKSkKY29udG91cih4LHksZXhwKHBvc3QpLGRyYXdsYWJlbHM9RkFMU0UseGxhYj0ieCIseWxhYj0ieSIsbWFpbj0iVGFyZ2V0IGRpc3RyaWJ1dGlvbiIpCgpgYGAKCiMgTWV0cm9wb2xpcy1IYXN0aW5ncyBzYW1wbGVyCgpgYGB7cn0KbWV0cm9wb2xpcyA9IGZ1bmN0aW9uKGxvZ3Asc3RhcnQ9YygwLDApLGl0ZXI9bml0ZXIsd2FybXVwPWJ1cm5pbixwcm9wb3NhbF9zZD0wLjQsc2VlZD0xMjMpewogIHNhbXBsZXMgICAgID0gbWF0cml4KDAsaXRlciwyKQogIHNhbXBsZXNbMSxdID0gc3RhcnQKICBsb2dwX2N1cnIgICA9IGxvZ3Aoc3RhcnQpCiAgCiAgZm9yIChpIGluIDI6aXRlcikgewogICAgcHJvcG9zYWwgICAgPSAgcm5vcm0oMixzYW1wbGVzW2ktMSxdLHByb3Bvc2FsX3NkKQogICAgbG9ncF9wcm9wICAgPSBsb2dwKHByb3Bvc2FsKQogICAgYWNjZXB0X3Byb2IgPSBleHAobG9ncF9wcm9wIC0gbG9ncF9jdXJyKQogICAgCiAgICBpZiAocnVuaWYoMSkgPCBhY2NlcHRfcHJvYikgewogICAgICBzYW1wbGVzW2ksXSA9IHByb3Bvc2FsCiAgICAgIGxvZ3BfY3VyciAgID0gbG9ncF9wcm9wCiAgICB9IGVsc2UgewogICAgICBzYW1wbGVzW2ksXSA9IHNhbXBsZXNbaS0xLF0KICAgIH0KICB9CiAgc2FtcGxlc1sod2FybXVwKzEpOml0ZXIsXQp9CgpzZWVkID0gMzE0MTYKc2V0LnNlZWQoc2VlZCkKbml0ZXIgID0gMjAwMDAKYnVybmluID0gMTAwMDAKTSAgICAgID0gbml0ZXIgLSBidXJuaW4KCm1oX3NhbXBsZXMgPSBtZXRyb3BvbGlzKGxvZ3ApCmBgYAoKIyMgVHJhY2UgcGxvdHMgYW5kIEFDRiBwbG90cwoKYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9N30KcGFyKG1mcm93PWMoMiwyKSkKdHMucGxvdChtaF9zYW1wbGVzWywxXSx4bGFiPSJJdGVyYXRpb25zIix5bGFiPSJ4IixtYWluPSJNZXRyb3BvbGlzLUhhc3RpbmdzIikKYWNmKG1oX3NhbXBsZXNbLDFdLG1haW49IiIpCnRzLnBsb3QobWhfc2FtcGxlc1ssMl0seGxhYj0iSXRlcmF0aW9ucyIseWxhYj0ieSIpCmFjZihtaF9zYW1wbGVzWywyXSxtYWluPSIiKQpgYGAKCiMjIFRhcmdldCBkcmF3cwoKYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02fQpwYXIobWZyb3c9YygxLDEpKQp4cmFuZ2UgPSByYW5nZShtaF9zYW1wbGVzWywxXSx4KQp5cmFuZ2UgPSByYW5nZShtaF9zYW1wbGVzWywyXSx5KQpwbG90KG1oX3NhbXBsZXMsIHBjaD0xNiwgY2V4PTAuMywgbWFpbj0iTWV0cm9wb2xpcy1IYXN0aW5ncyIseGxhYj0ieCIseWxhYj0ieSIsCiAgICAgeGxpbT14cmFuZ2UseWxpbT15cmFuZ2UpCmNvbnRvdXIoeCx5LGV4cChwb3N0KSxhZGQ9VFJVRSxjb2w9Mixsd2Q9MikKYGBgCgojIyBFZmZlY3RpdmUgc2FtcGxlIHNpemUKYGBge3J9CkVTUy5taCA9IGMoTS9zdW0oYWNmKG1oX3NhbXBsZXNbLDFdLHBsb3Q9RkFMU0UpJGFjZl4yKSxNL3N1bShhY2YobWhfc2FtcGxlc1ssMl0scGxvdD1GQUxTRSkkYWNmXjIpKQpjKE0scm91bmQoRVNTLm1oKSkKYGBgCgoKIyBIYW1pbHRvbmlhbiBNb250ZSBDYXJsbwoKYGBge3J9CmxpYnJhcnkocnN0YW4pCnN0YW5fY29kZSA9ICIKZGF0YSB7CiAgaW50PGxvd2VyPTA+IE47Cn0KcGFyYW1ldGVycyB7CiAgcmVhbCB4OwogIHJlYWwgeTsKfQptb2RlbCB7CiAgcmVhbCBiID0gMjsKICB4IH4gbm9ybWFsKDAsIDEpOwogIHkgfiBub3JtYWwoYiAqIHheMiwgMSk7Cn0KIgpgYGAKCiMjIENvbXBpbGluZyBhbmQgc2FtcGxpbmcgCmBgYHtyfQpzbSA9IHN0YW5fbW9kZWwobW9kZWxfY29kZSA9IHN0YW5fY29kZSkKCmZpdCA9IHNhbXBsaW5nKHNtLGRhdGE9bGlzdChOPTEpLGl0ZXI9bml0ZXIsd2FybXVwPWJ1cm5pbixjaGFpbnM9MSxzZWVkPXNlZWQpCgpwb3N0ZXJpb3IgPSBhcy5kYXRhLmZyYW1lKGZpdCkKYGBgCgoKIyMgVHJhY2UgcGxvdHMgYW5kIEFDRiBwbG90cwoKYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9N30KcGFyKG1mcm93PWMoMiwyKSkKdHMucGxvdChwb3N0ZXJpb3IkeCx4bGFiPSJJdGVyYXRpb25zIix5bGFiPSJ4IixtYWluPSJIYW1pbHRvbmlhbiBNQyIpCmFjZihwb3N0ZXJpb3IkeCxtYWluPSIiKQp0cy5wbG90KHBvc3RlcmlvciR5LHhsYWI9Ikl0ZXJhdGlvbnMiLHlsYWI9InkiKQphY2YocG9zdGVyaW9yJHksbWFpbj0iIikKYGBgCgoKIyMgVGFyZ2V0IGRyYXdzCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTZ9CnBhcihtZnJvdz1jKDEsMSkpCnBsb3QocG9zdGVyaW9yJHgsIHBvc3RlcmlvciR5LCBwY2g9MTYsIGNleD0wLjMsbWFpbj0iSE1DIChTdGFuKSIseGxhYj0ieCIseWxhYj0ieSIpCmNvbnRvdXIoeCx5LGV4cChwb3N0KSxhZGQ9VFJVRSxjb2w9Mixsd2Q9MikKYGBgCgojIyBFZmZlY3RpdmUgc2FtcGxlIHNpemUKYGBge3J9CkVTUy5obWMgPSBjKE0vc3VtKGFjZihwb3N0ZXJpb3IkeCxwbG90PUZBTFNFKSRhY2ZeMiksTS9zdW0oYWNmKHBvc3RlcmlvciR5LHBsb3Q9RkFMU0UpJGFjZl4yKSkKYyhNLHJvdW5kKEVTUy5obWMpKQpgYGAKCg==