Gibbs sampling algorithm from scratch using R programming language
Gibbs sampling algorithm from scratch using R programming language
from scratch
Psychiatrist
https://www.linkedin.com/in/mehdihamedi/
Gibbs sampling algorithm is one type of Markov Chain Monte Carlo
methods to approximate posterior distribution, when direct sampling is
difficult or not possible.
Bayes theorem
P ( θ | y )=( P ( y | θ ) × P ( θ ) ) / P ( y ) (1)
The regularity that all samples for xj are conditioned on the current
sample (i.e.,i+1) for all variables x1,..., xj−1, and on the previous sample
(i.e., i) for all variables xj+1,..., xk, should be immediately apparent.
We first set up our bivariate structure by specifying the means (μ) and
standard deviations (σ) of two normal distributions, their correlation (ρ),
and their variance-covariance matrix (Σ).
#gibbs sampler
require(mvtnorm)
require(MASS)
𝜎𝑥
𝑥 𝑖+1 ~ 𝑓(𝑥|𝑦 𝑖 ) = 𝑁 (𝜇𝑥 + 𝜌 ( ) (𝑦 (𝑖) − 𝜇𝑦 ), √𝜎𝑥2 (1 − 𝜌2 ))
𝜎𝑦
𝜎𝑦
𝑦 𝑖+1 ~ 𝑓(𝑦|𝑥 𝑖+1 ) = 𝑁 (𝜇𝑦 + 𝜌 ( ) (𝑥 (𝑖+1) − 𝜇𝑥 ), √𝜎𝑦2 (1 − 𝜌2 ))
𝜎𝑥
𝜎𝑥 (𝑖)
𝑥 𝑖+1 ~ 𝑓(𝑥|𝑦 𝑖 ) = 𝑁 (𝜌 ( ) 𝑦 , √𝜎𝑥2 (1 − 𝜌2 ))
𝜎𝑦
𝜎𝑦 (𝑖+1)
𝑦 𝑖+1
~ 𝑓(𝑦|𝑥 𝑖+1
) = 𝑁 (𝜌 ( ) 𝑥 , √𝜎𝑦2 (1 − 𝜌2 ))
𝜎𝑥
#gibbs sampling
sxt1mr <- sqrt(sigx^2*(1-rho^2))
syt1mr <- sqrt(sigy^2*(1-rho^2))
rxy <- rho*(sigx/sigy)
ryx <- rho*(sigy/sigx)
xsamp <- ysamp <- rep(0,nsamples)
xsamp[1] <- -2
ysamp[1] <- 2
for (i in c(1:(nsamples-1))) {
xsamp[i+1] <- rnorm(1, mean=rxy*ysamp[i], sd=sxt1mr)
ysamp[i+1] <- rnorm(1, mean=ryx*xsamp[i+1], sd=syt1mr)
}
Then, the last few lines of code plots the last 500 sampled x−y pairs. We
discarded the first 500 as the usual burnin, although to illustrate the path
of the sampler from the starting value, we also plot and identify by
number the first five samples. Then check the mean, standard deviation,
and correlation of the samples:
points(xsamp[-c(1:500)],ysamp[-c(1:500)],pch=21,bg="red")
for (j in c(1:5)){
points(xsamp[j],ysamp[j]-.005,pch=21,cex=3.5,bg="white")
text(xsamp[j],ysamp[j],as.character(j))
}
cor.test(xsamp,ysamp)
sd(xsamp)
sd(ysamp)
bivn<-rmvnorm(1000,rep(0,2),sigma)
#some checks
apply(bivn,2,mean)
apply(bivn,2,sd)
cor.test(bivn[,1],bivn[,2])
And the checks:
> cor.test(xsamp,ysamp)
> sd(xsamp)
[1] 1.028386
> sd(ysamp)
[1] 0.5167615
>
> bivn<-rmvnorm(1000,rep(0,2),sigma)
> #some checks
> apply(bivn,2,mean)
[1] -0.003818762 0.006641190
> apply(bivn,2,sd)
[1] 1.0365947 0.4919069
> cor.test(bivn[,1],bivn[,2])
Now all integrated codes are illustrated below for your convenience:
#gibbs sampler
require(mvtnorm)
require(MASS)
#gibbs sampling
sxt1mr <- sqrt(sigx^2*(1-rho^2))
syt1mr <- sqrt(sigy^2*(1-rho^2))
rxy <- rho*(sigx/sigy)
ryx <- rho*(sigy/sigx)
xsamp <- ysamp <- rep(0,nsamples)
xsamp[1] <- -2
ysamp[1] <- 2
for (i in c(1:(nsamples-1))) {
xsamp[i+1] <- rnorm(1, mean=rxy*ysamp[i], sd=sxt1mr)
ysamp[i+1] <- rnorm(1, mean=ryx*xsamp[i+1], sd=syt1mr)
}
points(xsamp[-c(1:500)],ysamp[-c(1:500)],pch=21,bg="red")
for (j in c(1:5)){
points(xsamp[j],ysamp[j]-.005,pch=21,cex=3.5,bg="white")
text(xsamp[j],ysamp[j],as.character(j))
}
cor.test(xsamp,ysamp)
sd(xsamp)
sd(ysamp)
bivn<-rmvnorm(1000,rep(0,2),sigma)
#some checks
apply(bivn,2,mean)
apply(bivn,2,sd)
cor.test(bivn[,1],bivn[,2])
Source: