A MCMC implementation for a standard normal distribution¶
Target Distribution (Posterior)¶
In notebook, the goal is to generate samples from the standard normal distribution (a normal distribution centered around 0 with standard deviation of 1):
Since there is no data (I’m not conditioning on any observations for this simple example), the posterior is simply the target distribution , the standard normal density.
Likelihood¶
For the standard normal, when simulating from the distribution (not fitting to data), the likelihood term is just the value of the target density itself:
MCMC steps¶
Proposal Step:
Propose a new point from a normal distribution centered at the current :
This is a random walk Metropolis proposal: .
Acceptance Ratio:
Since the proposal distribution is symmetric, the terms cancel out in the general M-H acceptance ratio:
Plugging in the normal density:
Update Step:
Accept with probability . Otherwise, keep the current value.
import numpy as np
import matplotlib.pyplot as plt
from numba import njitdef MHSTDnormal(N, X0, sigmaSq):
x = np.empty(N)
x[0] = X0
for i in range(1, N):
xhat = np.random.normal(x[i-1], np.sqrt(sigmaSq))
accept_prob = np.exp(-0.5 * (xhat**2 - x[i-1]**2))
if np.random.uniform() <= accept_prob:
x[i] = xhat
else:
x[i] = x[i-1]
return xnormalSamples = MHSTDnormal(N = 10000, # number of iterations
X0 = 0.3, # starting value
sigmaSq = 10**1 # variance of the standard normal (sd = 1, var = 1^2)
)
plt.plot(normalSamples)
plt.title('Metropolis-Hastings samples from Standard Normal')
plt.xlabel('Iteration')
plt.ylabel('Sample Value')
plt.show()
plt.figure(figsize = (8,4))
count, bins, ignored = plt.hist(normalSamples, bins = 50, density = True, alpha = 0.6, color = "skyblue")
x = np.linspace(-4, 4, 1000)
plt.plot(x, 1/np.sqrt(2*np.pi) * np.exp(-x**2/2), 'r', lw=2, label='True Standard Normal')
plt.title('Posterior Distribution')
plt.xlabel('Sample Value')
plt.ylabel('Density')
plt.legend()
plt.show()
