# 1. Accept/reject for target=Normal and proposal: G=2-sided exponential. # Explaining the underlying principle par(mfrow=c(2,1)) z <- seq(-5,5,0.01) f <- dnorm(z) # target density g <- 0.5*exp(-abs(z)) # proposal density acc <- sqrt(pi*0.5)*exp(-0.5) # acceptance probability = 1/M plot(z,g,type="l",ylab="density",main= "normal and 2-sided exponential density") abline(h=0) lines(z,f,col=3) lines(z,acc*f,col=2) # f/M plot(z,acc*f/g,type="l",ylab="f(x)/(g(x)M)",main= "acceptance probabilities") # Implementing par(mfrow=c(2,1)) x <- (1-2*(runif(10000) < 0.5))*log(runif(10000)) # Sample from G qqnorm(x) # G has heavier tails than F a <- exp(-0.5*(abs(x)-1)^2) # vector of acceptance probabilities y <- x[runif(10000) r.target(x[i,],x[i-1,],...)) { x[i,] <- x[i-1,] nrej <- nrej+1 } } list(sample=x,nrej=nrej,prop=y) } r.post <- function(x1,x2,xi,ka2,gam,lam,n,xb,xs) { ## Purpose: Computing ratio of posteriori densities at x1 and x2 ## for an i.i.d. normal model ## ---------------------------------------------------------------------- ## Arguments: x=(mu,log(sigma)) = Parameters of the normal distribution ## xi,ka2,gam,lam = Parameters of the prior ## n=number of data, xb=sample mean, xs=sample variance ## ---------------------------------------------------------------------- ## Author: Hans-Ruedi Kuensch, Date: 24 Jan 2004, 17:25 quot <- 0.5*((x2[1]-xi)^2-(x1[1]-xi)^2)/ka2 + (2*gam+n)*(x2[2]-x1[2]) + (lam+0.5*n*(xs+(x2[1]-xb)^2))*exp(-2*x2[2]) - (lam+0.5*n*(xs+(x1[1]-xb)^2))*exp(-2*x1[2]) exp(quot) } # Few iterations (with log scale for sigma) to explain the idea f.post.contour(xi,ka2,gam,lam,n,xb,xs) points(xb,sqrt(xs),pch=15,col=2) title(main="log posterior density") metrop <- f.metrop(x0=c(xb,0.5*log(xs)),sigma=c(0.2,0.1),nrep=21, r.target=r.post,xi,ka2,gam,lam,n,xb,xs) # vary values of sigma to see how it influences the results sample <- metrop$sample sample[,2] <- exp(sample[,2]) prop <- metrop$prop prop[,2] <- exp(prop[,2]) points(prop[,1],prop[,2],col=3) # proposed points in green points(sample[,1],sample[,2],col=2) #accepted points in red arrows(sample[-21,1],sample[-21,2],prop[,1],prop[,2],length=0.1,col=4) #Result of many iterations f.post.contour(xi,ka2,gam,lam,n,xb,xs) points(xb,sqrt(xs),pch=15,col=2) title(main="log posterior density") metrop <- f.metrop(x0=c(xb,0.5*log(xs)),sigma=c(0.6,0.3),nrep=5000, r.target=r.post,xi,ka2,gam,lam,n,xb,xs) metrop$nrej # number of rejections param <- metrop$sample points(param[,1]+0.04*(runif(5000)-0.5), exp(param[,2])+0.04*(runif(5000)-0.5),cex=0.5) # overlapping points made visible by jittering par(mfrow=c(2,1)) plot(param[1:500,1],type="l",xlab="iteration",ylab="mu") #trace plots (time series of each component) plot(param[1:500,2],type="l",xlab="iteration",ylab="sigma") acf(param[,1],lag.max=100) #Autocorrelations acf(param[,2],lag.max=100) par(mfrow=c(1,1)) # 5. Metropolis for a Gaussian mixture f.contour.mixture <- function(p,mu,scale) { ## Purpose: Plotting the density of a mixture of 2 bivariate normals ## The first normal is the standard normal. ## ------------------------------------------------------------------------- ## Arguments: p = mixture weight, mu=location of second normal, ## scale = scale of second normal (scalar) ## ------------------------------------------------------------------------- ## Author: Hans-Ruedi Kuensch, Date: 22 Jan 2002, 22:07 x <- seq(-2.5,4,length=32) z <- p*exp(-0.5*outer(x^2,x^2,FUN="+"))+ (1-p)*exp(-0.5*outer((x-mu[1])^2,(x-mu[2])^2,FUN="+")/scale^2) contour(x,x,z,nlevels=20)} r.mixture <- function(x1,x2,p,mu,scale) { ## Purpose: Computing the ratio of a mixture density at two places x1, x2 ## ------------------------------------------------------------------------- ## Arguments: p, mu scale as in the previous function ## ------------------------------------------------------------------------- ## Author: Hans-Ruedi Kuensch, Date: 22 Jan 2002, 21:25 r <- p*exp(-0.5*sum(x1^2)) + (1-p)*exp(-0.5*sum((x1-mu)^2)/scale^2) r <- r/(p*exp(-0.5*sum(x2^2)) + (1-p)*exp(-0.5*sum((x2-mu)^2)/scale^2)) r } mu <- c(3,3) scale <- 0.5 #target density and generated sample par(mfrow=c(1,1)) f.contour.mixture(0.7,mu,scale) erg <- f.metrop(x0=c(0,0),sigma=c(1,1),5000,r.mixture,0.7,mu,scale) # vary argument sigma! erg$nrej # number of rejected proposals x <- erg$sample points(x[,1],x[,2]) # trace plots and autocorrelations par(mfrow=c(2,1)) plot(x[1:500,1],type="l") plot(x[1:500,2],type="l") acf(x[,1],lag.max=100) acf(x[,2],lag.max=100) par(mfrow=c(1,1))