import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
PRNG
Uniform distribution
I am pasting the code from vega-vis
export default function(seed) {
// Random numbers using a Linear Congruential Generator with seed value
// Uses glibc values from https://en.wikipedia.org/wiki/Linear_congruential_generator
return function() {
= (1103515245 * seed + 12345) % 2147483647;
seed return seed / 2147483647;
;
} }
def random_gen(seed, num):
= np.zeros(num)
out 0] = (1103515245 * seed + 12345) % 2147483647
out[for i in range(1, num):
= (1103515245 * out[i-1] + 12345) % 2147483647
out[i] return out/2147483647
0, 5000), density=True, alpha=0.5, label='Our implementation'); plt.hist(random_gen(
0, 5000), density=True, alpha=0.5, label='Our implementation');
plt.hist(random_gen(5000), density=True, alpha=0.4, label='Numpy implementation');
plt.hist(np.random.random( plt.legend()
Inverse transform sampling
Exponential distribution
Borrowing from Wikipedia.
The probability density function (pdf) of an exponential distribution is \[ f(x ; \lambda)=\left\{\begin{array}{ll} \lambda e^{-\lambda x} & x \geq 0 \\ 0 & x \leq 0 \end{array}\right. \]
The exponential distribution is sometimes parametrized in terms of the scale parameter \(\beta=1 / \lambda:\) \[ f(x ; \beta)=\left\{\begin{array}{ll} \frac{1}{\beta} e^{-x / \beta} & x \geq 0 \\ 0 & x<0 \end{array}\right. \]
The cumulative distribution function is given by \[ F(x ; \lambda)=\left\{\begin{array}{ll} 1-e^{-\lambda x} & x \geq 0 \\ 0 & x<0 \end{array}\right. \]
from scipy.stats import expon
= [expon(scale=s) for s in [1/1., 1/2., 1/3.]] rvs
= np.arange(0, 10, 0.1)
x for i, lambda_val in enumerate([1, 2, 3]):
=2, label=r'$\lambda=%s$' %lambda_val)
plt.plot(x, rvs[i].pdf(x), lw plt.legend()
For the purposes of this notebook, I will be looking only at the standard exponential or set the scale to 1.
Let us now view the CDF of the standard exponential.
= plt.subplots(nrows=2, sharex=True)
fig, ax 0].plot(x, expon().pdf(x), lw=2)
ax[0].set_title("PDF")
ax[1].set_title("CDF")
ax[1].plot(x, expon().cdf(x), lw=2,) ax[
= expon.rvs(size=1000) r
=True, bins=100)
plt.hist(r, normed=2) plt.plot(x, expon().pdf(x), lw
/home/nipunbatra-pc/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:1: MatplotlibDeprecationWarning:
The 'normed' kwarg was deprecated in Matplotlib 2.1 and will be removed in 3.1. Use 'density' instead.
"""Entry point for launching an IPython kernel.
Inverse of the CDF of exponential
The cumulative distribution function is given by \[ F(x ; \lambda)=\left\{\begin{array}{ll} 1-e^{-\lambda x} & x \geq 0 \\ 0 & x<0 \end{array}\right. \]
Let us consider only \(x \geq 0\).
Let \(u = F^{-1}\) be the inverse of the CDF of \(F\).
\[ u = 1-e^{-\lambda x} \\ 1- u = e^{-\lambda x} \\ \log(1-u) = -\lambda x\\ x = -\frac{\log(1-u)}{\lambda} \]
def inverse_transform(lambda_val, num_samples):
= np.random.random(num_samples)
u = -np.log(1-u)/lambda_val
x return x
1, 5000), bins=100, normed=True,label='Generated using our function');
plt.hist(inverse_transform(=4, label='Generated using scipy')
plt.plot(x, expon().pdf(x), lw plt.legend()
/home/nipunbatra-pc/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:1: MatplotlibDeprecationWarning:
The 'normed' kwarg was deprecated in Matplotlib 2.1 and will be removed in 3.1. Use 'density' instead.
"""Entry point for launching an IPython kernel.
Drawing samples from Laplace distribution
A random variable has a Laplace \((\mu, b)\) distribution if its probability density function is \[ f(x | \mu, b)=\frac{1}{2 b} \exp \left(-\frac{|x-\mu|}{b}\right) \]
\[F^{-1}(u)=\mu-b \operatorname{sgn}(u-0.5) \ln (1-2|u-0.5|)\]
def inverse_transform_laplace(b, mu, num_samples):
= np.random.random(num_samples)
u = mu-b*np.sign(u-0.5)*np.log(1-2*np.abs(u-0.5))
x return x
from scipy.stats import laplace
1, 0, 5000),bins=100, density=True, label='Generated using \nour function');
plt.hist(inverse_transform_laplace(= np.linspace(-10, 10, 100)
x_n =4, label='Generated from\n scipy')
plt.plot(x_n, laplace().pdf(x_n), lw plt.legend()