Example 2.8#

In what follows, we will implement rejection methods for sampling continuous distributions.

Let us implement here Example 2.8 of lecture notes.

First let us describe the Beta density.

import numpy as np
import matplotlib.pyplot as plt

def beta_pdf(x, alpha, beta):
    return (x**(alpha-1) * (1-x)**(beta-1) * np.math.gamma(alpha+beta) /
            (np.math.gamma(alpha) * np.math.gamma(beta)))

Now we are ready to implement the rejection method as shown in Example 2.8.

Example 2.8. We aim at sampling from \(p(x) = \text{Beta}(x;\alpha,\beta)\) with \(\alpha = \beta = 2\). We will do this in a way that will demonstrate the Fundamental Theorem of Simulation. As noted in the example, we know that \(p^\star = 1.5\) in this case, which is the maximum of this density. In order to draw samples under the curve \(p(x)\), we will first sample uniformly in the “box” \((X', U') \sim \text{Unif}([0,1] \times [0, p^\star])\) and accept/reject samples if \(U' \leq p(X')\). Note that this sampler is just for demonstration as the rejection samplers.

alpha = 2
beta = 2
p_star = 1.5

rng = np.random.default_rng(5)

xx = np.linspace(0, 1, 1000)

n = 5000

fig, axs = plt.subplots(1, 2, figsize=(10, 4))

# for demonstration purposes, we do this in a for loop
# this can be done all at once

acc_samples = np.array([])
acc_u = np.array([])
# note that we do not have to store uniform samples
# this is again for demonstration of the FTS.

for i in range(n):
    x = rng.uniform(0, 1)
    u = rng.uniform(0, p_star)

    if u <= beta_pdf(x, alpha, beta):
        acc_u = np.append(acc_u, u)
        acc_samples = np.append(acc_samples, x)

axs[0].plot(xx, beta_pdf(xx, alpha, beta), color='k', linewidth=2)
axs[0].add_patch(plt.Rectangle((0, 0), 1, p_star, color=[0.8, 0, 0], fill=False, lw=2))
axs[0].scatter(acc_samples, acc_u, color=[0.8, 0, 0], s=12)
axs[0].set_xlim(0, 1)
axs[0].set_ylim(0, 2.1)
axs[1].cla()
axs[1].plot(xx, beta_pdf(xx, alpha, beta), color=[0.8, 0, 0], linewidth=2)
axs[1].hist(acc_samples, bins=100, density=True, color='k')
axs[1].set_xlim(0, 1)
plt.show()
<ipython-input-1-069f25697792>:5: DeprecationWarning: `np.math` is a deprecated alias for the standard library `math` module (Deprecated Numpy 1.25). Replace usages of `np.math` with `math`
  return (x**(alpha-1) * (1-x)**(beta-1) * np.math.gamma(alpha+beta) /
<ipython-input-1-069f25697792>:6: DeprecationWarning: `np.math` is a deprecated alias for the standard library `math` module (Deprecated Numpy 1.25). Replace usages of `np.math` with `math`
  (np.math.gamma(alpha) * np.math.gamma(beta)))
../_images/147d5afb22b3a390e8ac81dd77819c1a15a4309ce8d870774f6c7e3593f5bb27.png

One can see the samples on the left that are uniformly distributed. On the right, the histogram of the accepted samples is shown (only accepted \(x\) values which are acc_samples in the code). Animating this process is too costly in a notebook but is provided in the course.