Gibbs sampling is a MCMC method to draw samples from a complex distribution (usually a posterior in Bayesian inference).
In this post I aim to show how to do Gibbs sampling using Edward, “a Python library for probabilistic modeling”. If you are new to Edward, you can install the package by following up these steps.
Let assume we have a multivariate normal random variable :
The following image show the 2d projection of pdf.
We can define the multivariate normal in Edward as follows:
mu = [3., 2.]
cov = [[1, -0.6], [-0.6, 1]]
scale = tf.cholesky(cov)
mvn = ed.models.MultivariateNormalTriL(loc=mu, scale_tril=scale)
For Gibbs sampling we need to
- Calculate the marginal pdf of each dimension, , .
- Initialize each random variable with random values, and
- Draw sample and
- Repeat 3, times
- Keep for where is total number of samples and is burning samples.
In Edward, we can define the marginal distribution as follows:
x0 = tf.placeholder(shape=[], dtype=tf.float32)
x1 = tf.placeholder(shape=[], dtype=tf.float32)
normal0_given1 = ed.models.Normal(loc=mu[0]+cov[0][1]/cov[1][1]*(x1-mu[1]), scale=cov[1][1]-cov[0][1]**2/cov[0][0])
normal1_given0 = ed.models.Normal(loc=mu[1]+cov[1][0]/cov[0][0]*(x0-mu[0]), scale=cov[0][0]-cov[1][0]**2/cov[1][1])
In above code x0
and x1
are two place holders for samples of and from previous iteration.
Now its time to implement #4 and #5:
N = 5000
with sess:
x1_sample = 0
data_sampled = [[0, 0]] * N
for i in range(N):
x0_sample = sess.run(normal0_given1.sample(1), {x1: x1_sample})[0] # x0 ~ P(X0| X1=x1)
x1_sample = sess.run(normal1_given0.sample(1), {x0: x0_sample})[0] # x1 ~ P(X1| X0=x0)
data_sampled[i] = [x0_sample, x1_sample]
data_sample
above contains the
plt.hist2d([x[0] for x in data_sampled], [x[1] for x in data_sampled], bins=100)
plt.show()
Here we go. Edward helped us to write Gibbs sampling with less than 10 line of codes. The whole code can be found on github.