Expectations and Densities¶
CDF and PDF¶
- In the last lecture, we introduced the ECDF $\hat{F}(x)$ and the CDF $F(x)$, and showed that $\mathbb{E}[\hat{F}(x)]=F(x)$
- For a given function to be a distribution function it must be non-decreasing, go to 0 as $x \rightarrow -\infty$, and go to 1 as $x \rightarrow \infty$
CDF TO PMF¶
- Let's put $X$ on a grid $\{x_1, x_2, ..., x_J\}$, where the space between $x_j$ and $x_{j+1}$ is $h$
- Let's "split the difference" between grid points, and compute the probability that $X$ is between $x_j - h/2$ and $x_j +h/2$ equal to $F(x_j+h/2) - F(x_j-h/2)$
- Let's approximate the value of $X$ itself on the interval $[x_j-h/2,x_j+h/2)$ by $x_j$
- This discretizes the random variable $X$, giving it a probability mass function and a finite number of values to take
Approximating the Expectation¶
- On the grid, our approximation of the expected value is $$ \mathbb{E}[X] \approx \sum_{j=1}^J \underbrace{x_j}_{\approx x} \times \underbrace{F(x_j+h/2)-F(x_j-h/2)}_{\approx p[x_j-h/2 \le X < x_j+h]} $$
- We want to let $h$ get small and make this "look like an integral"
- Multiply and divide by $h$, and we get this: $$ \mathbb{E}[X] \approx \underbrace{\sum_{j=1}^J}_{\rightarrow \int} \quad \underbrace{x_j}_{\rightarrow X} \times \underbrace{\frac{F(x_j+h/2)-F(x_j-h/2)}{h}}_{\rightarrow F'(x)} \times \underbrace{h}_{\rightarrow {dx}} $$
PMF to Probability Density Function¶
- So for a continuous random variable, $$ \mathbb{E}[X] = \int_x x F'(x) dx $$
- The term $F'(x)$ is the probability density function of $F(x)$, and we write $f(x) = F'(x)$
- Some random variables are more easily characterized by their distribution function $F(x)$ (e.g. uniform), and some are more easily characterized by their density $f(x)=F'(x)$ (e.g. normal)
Probability Density Functions¶
- Some distributions are easier to describe in terms of their density
- Instead of starting with the cdf $F(x)$ and taking the derivative to get the pdf $f(x)=F'(x)$, it makes more sense sometimes to start with the density $f(x)$ and then integrate, so $$ F(x) = \int_{-\infty}^x f(z)dz $$
- Since $F(x) = \text{pr}[ X \le x]$, the complementary probability is $1-F(x) = \text{pr}[X > x]$
- Likewise, $\text{pr}[a \le X < b ] = \int_{a}^{b} f(x)dx = F(b) - F(a)$
Expectation and Variance¶
- We've defined the expectation and variance a few times, depending on the scenario, but the principles are the same:
- To get the expected value, weight each $x$ by the "probability" it occurs, now $f(x)$, and sum
- To get the variance, weight each squared deviation of $X$ from its expected value, $(X-\mathbb{E}[X])^2$, by the "probability" it occurs, now $f(x)$, and sum
- With continuous random variables with a density function $f(x)$, we define the expectation as $$ \mathbb{E}[X] = \int_{x} x f(x) dx $$ and the variance as $$ \mathbb{V}[X] = \int_x (x - \mathbb{E}[X])^2 f(x) dx $$
Exercise¶
- Suppose a variable is uniformly distributed, so it has distribution function: $$ F(x) = \begin{cases} 0, & x < 0 \\ x, & 0 \le x \le 1 \\ 1, & x > 1 \end{cases} $$
- What is the probability density function, the expectation, and variance?
Exercise¶
- Suppose a variable is exponentially distributed, so it has distribution function: $$ F(x) = \begin{cases} 0, & x < 0 \\ 1-e^{-\lambda t}, & x \ge 0 \end{cases} $$
- What is the probability density function and the expectation?
Distribution Helper¶
- The next examples use small interactive plots to connect parameters, densities, distribution functions, expectation, and variance
- Move the sliders and watch how the PDF/PMF, CDF, $\mathbb{E}[X]$, and $\mathbb{V}[X]$ change
In [30]:
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
from scipy.special import gamma
import ipywidgets as widgets
def _format_stat(value):
if value is None or (isinstance(value, float) and np.isnan(value)):
return "undefined"
if np.isposinf(value):
return "infinite"
if np.isneginf(value):
return "-infinite"
return f"{value:.4g}"
def _finite_grid_from_dist(dist, support=None, q_low=0.001, q_high=0.999, n=600):
if support is not None:
lo, hi = support
else:
lo = dist.ppf(q_low)
hi = dist.ppf(q_high)
if not np.isfinite(lo):
lo = dist.ppf(0.01)
if not np.isfinite(hi):
hi = dist.ppf(0.99)
if lo == hi:
lo -= 1
hi += 1
pad = 0.04 * (hi - lo)
return np.linspace(lo - pad, hi + pad, n)
def plot_continuous_distribution(name, dist, mean, variance, support=None):
x = _finite_grid_from_dist(dist, support=support)
pdf = dist.pdf(x)
cdf = dist.cdf(x)
fig, axes = plt.subplots(1, 2, figsize=(11, 3.8))
axes[0].plot(x, pdf, color="#2d6cdf", lw=2)
axes[0].set_title("PDF")
axes[0].set_xlabel("x")
axes[0].set_ylabel("f(x)")
axes[0].grid(alpha=0.25)
axes[1].plot(x, cdf, color="#00876c", lw=2)
axes[1].set_title("CDF")
axes[1].set_xlabel("x")
axes[1].set_ylabel("F(x)")
axes[1].set_ylim(-0.04, 1.04)
axes[1].grid(alpha=0.25)
if mean is not None and np.isfinite(mean):
for ax in axes:
ax.axvline(mean, color="#9f2f2f", ls="--", lw=1.5, label="E[X]")
axes[0].legend(loc="best")
# if mean is not None and np.isfinite(mean) and np.isfinite(variance) and variance >= 0:
# sd = np.sqrt(variance)
# axes[0].axvspan(mean - sd, mean + sd, color="#9f2f2f", alpha=0.10, label="+/- 1 SD")
fig.suptitle(
f"{name}: E[X] = {_format_stat(mean)} V[X] = {_format_stat(variance)}",
y=1.05,
fontsize=12,
)
plt.tight_layout()
plt.show()
def plot_discrete_distribution(name, values, probabilities, mean, variance):
values = np.asarray(values)
probabilities = np.asarray(probabilities)
cdf = np.cumsum(probabilities)
fig, axes = plt.subplots(1, 2, figsize=(11, 3.8))
axes[0].bar(values, probabilities, color="#2d6cdf", width=0.8)
axes[0].set_title("PMF")
axes[0].set_xlabel("x")
axes[0].set_ylabel("p[X=x]")
axes[0].grid(axis="y", alpha=0.25)
axes[1].step(values, cdf, where="post", color="#00876c", lw=2)
axes[1].scatter(values, cdf, color="#00876c", s=20)
axes[1].set_title("CDF")
axes[1].set_xlabel("x")
axes[1].set_ylabel("F(x)")
axes[1].set_ylim(-0.04, 1.04)
axes[1].grid(alpha=0.25)
if mean is not None and np.isfinite(mean):
for ax in axes:
ax.axvline(mean, color="#9f2f2f", ls="--", lw=1.5, label="E[X]")
axes[0].legend(loc="best")
fig.suptitle(
f"{name}: E[X] = {_format_stat(mean)} V[X] = {_format_stat(variance)}",
y=1.05,
fontsize=12,
)
plt.tight_layout()
plt.show()
Example: Uniform¶
- The uniform distribution spreads probability evenly over an interval $[a,b]$
- Its CDF is $$ F(x) = \begin{cases} 0, & x < a \\ \dfrac{x-a}{b-a}, & a \le x \le b \\ 1, & x > b \end{cases} $$
- Its PDF is $$ f(x) = \begin{cases} \dfrac{1}{b-a}, & a \le x \le b \\ 0, & \text{otherwise} \end{cases} $$
In [ ]:
@widgets.interact(
a=widgets.FloatSlider(value=0.0, min=-5.0, max=5.0, step=0.25, description="a"),
b=widgets.FloatSlider(value=1.0, min=-4.75, max=10.0, step=0.25, description="b"),
)
def uniform_demo(a, b):
if b <= a:
print("Choose b > a.")
return
dist = stats.uniform(loc=a, scale=b - a)
mean = (a + b) / 2
variance = (b - a) ** 2 / 12
plot_continuous_distribution("Uniform(a, b)", dist, mean, variance, support=(a, b))
interactive(children=(FloatSlider(value=0.0, description='a', max=5.0, min=-5.0, step=0.25), FloatSlider(value…
Example: The Exponential Distribution¶
- The exponential distribution is supported on $[0,\infty)$
- Its CDF is $$ F(t) = \begin{cases} 0, & t<0 \\ 1 - e^{-\lambda t}, & t \ge 0 \end{cases} $$
- Its PDF is $$ f(t) = \begin{cases} \lambda e^{-\lambda t}, & t \ge 0 \\ 0, & t<0 \end{cases} $$
In [ ]:
@widgets.interact(
rate=widgets.FloatSlider(value=1.0, min=0.1, max=5.0, step=0.1, description="lambda"),
)
def exponential_demo(rate):
dist = stats.expon(scale=1 / rate)
mean = 1 / rate
variance = 1 / rate**2
plot_continuous_distribution("Exponential(lambda)", dist, mean, variance, support=(0, dist.ppf(0.995)))
interactive(children=(FloatSlider(value=1.0, description='lambda', max=5.0, min=0.1), Output()), _dom_classes=…
Example: The Logistic Distribution¶
- The logistic distribution has CDF $$ F(x) = \dfrac{1}{1+e^{-(x-\mu)/\sigma}} $$
- Its PDF is $$ f(x) = \dfrac{e^{-(x-\mu)/\sigma}}{\sigma\left(1+e^{-(x-\mu)/\sigma}\right)^2} $$
In [33]:
@widgets.interact(
mu=widgets.FloatSlider(value=0.0, min=-5.0, max=5.0, step=0.25, description="mu"),
sigma=widgets.FloatSlider(value=1.0, min=0.2, max=4.0, step=0.1, description="sigma"),
)
def logistic_demo(mu, sigma):
dist = stats.logistic(loc=mu, scale=sigma)
mean = mu
variance = (np.pi**2 * sigma**2) / 3
plot_continuous_distribution("Logistic(mu, sigma)", dist, mean, variance)
interactive(children=(FloatSlider(value=0.0, description='mu', max=5.0, min=-5.0, step=0.25), FloatSlider(valu…
Example: Normal Distribution¶
- The normal density is $$ f(x; \mu, \sigma) = \frac{1}{\sqrt{2\pi} \sigma}e^{-(x-\mu)^2/(2\sigma^2)} $$
- The normal CDF has no elementary closed form, so we usually compute it numerically
- Notice that it is bell-shaped and symmetric around $\mu$
In [34]:
@widgets.interact(
mu=widgets.FloatSlider(value=0.0, min=-5.0, max=5.0, step=0.25, description="mu"),
sigma=widgets.FloatSlider(value=1.0, min=0.2, max=4.0, step=0.1, description="sigma"),
)
def normal_demo(mu, sigma):
dist = stats.norm(loc=mu, scale=sigma)
mean = mu
variance = sigma**2
plot_continuous_distribution("Normal(mu, sigma)", dist, mean, variance)
interactive(children=(FloatSlider(value=0.0, description='mu', max=5.0, min=-5.0, step=0.25), FloatSlider(valu…
Example: Beta Distribution¶
- The beta distribution is supported on $[0,1]$, so it is useful for probabilities, proportions, and rates
- Its PDF is $$ f(x;\alpha,\beta)=\frac{x^{\alpha-1}(1-x)^{\beta-1}}{B(\alpha,\beta)}, \qquad 0<x<1 $$
- Its CDF does not have a simple closed form for general $\alpha$ and $\beta$
In [35]:
@widgets.interact(
alpha=widgets.FloatSlider(value=2.0, min=0.2, max=10.0, step=0.2, description="alpha"),
beta=widgets.FloatSlider(value=2.0, min=0.2, max=10.0, step=0.2, description="beta"),
)
def beta_demo(alpha, beta):
dist = stats.beta(a=alpha, b=beta)
mean = alpha / (alpha + beta)
variance = alpha * beta / ((alpha + beta) ** 2 * (alpha + beta + 1))
plot_continuous_distribution("Beta(alpha, beta)", dist, mean, variance, support=(0, 1))
interactive(children=(FloatSlider(value=2.0, description='alpha', max=10.0, min=0.2, step=0.2), FloatSlider(va…
Example: Bernoulli Distribution¶
- A Bernoulli random variable records one success-or-failure trial
- Its PMF is $$ p[X=x] = p^x(1-p)^{1-x}, \qquad x\in\{0,1\} $$
- Its CDF is $$ F(x)=\begin{cases} 0, & x<0 \\ 1-p, & 0\le x<1 \\ 1, & x\ge 1 \end{cases} $$
In [36]:
@widgets.interact(
p=widgets.FloatSlider(value=0.5, min=0.0, max=1.0, step=0.01, description="p"),
)
def bernoulli_demo(p):
values = np.array([0, 1])
probabilities = np.array([1 - p, p])
mean = p
variance = p * (1 - p)
plot_discrete_distribution("Bernoulli(p)", values, probabilities, mean, variance)
interactive(children=(FloatSlider(value=0.5, description='p', max=1.0, step=0.01), Output()), _dom_classes=('w…
Example: Binomial Distribution¶
- A binomial random variable counts the number of successes in $n$ independent Bernoulli trials with success probability $p$
- Its PMF is $$ p[X=k]=\binom{n}{k}p^k(1-p)^{n-k}, \qquad k=0,1,\ldots,n $$
- Its CDF is the cumulative sum of the PMF: $$ F(k)=\sum_{j=0}^{\lfloor k \rfloor}\binom{n}{j}p^j(1-p)^{n-j} $$
In [37]:
@widgets.interact(
n=widgets.IntSlider(value=10, min=1, max=60, step=1, description="n"),
p=widgets.FloatSlider(value=0.5, min=0.0, max=1.0, step=0.01, description="p"),
)
def binomial_demo(n, p):
values = np.arange(n + 1)
dist = stats.binom(n=n, p=p)
probabilities = dist.pmf(values)
mean = n * p
variance = n * p * (1 - p)
plot_discrete_distribution("Binomial(n, p)", values, probabilities, mean, variance)
interactive(children=(IntSlider(value=10, description='n', max=60, min=1), FloatSlider(value=0.5, description=…
Example: Geometric Distribution¶
- A geometric random variable records the waiting time until the first success
- Here $T=1$ means the first trial succeeds
- Its PMF is $$ p[T=t]=(1-p)^{t-1}p, \qquad t=1,2,3,\ldots $$
- Its CDF is $$ F(t)=p[T\le t]=1-(1-p)^{\lfloor t \rfloor}, \qquad t\ge 1 $$
In [ ]:
@widgets.interact(
p=widgets.FloatSlider(value=0.3, min=0.02, max=1.0, step=0.01, description="p"),
)
def geometric_demo(p):
dist = stats.geom(p=p)
upper = int(max(8, dist.ppf(0.995)))
values = np.arange(1, upper + 1)
probabilities = dist.pmf(values)
mean = 1 / p
variance = (1 - p) / p**2
plot_discrete_distribution("Geometric(p)", values, probabilities, mean, variance)
interactive(children=(FloatSlider(value=0.3, description='p', max=1.0, min=0.02, step=0.01), Output()), _dom_c…
Example: Poisson Distribution for Count Data¶
- A Poisson random variable counts how many events occur in a fixed interval when events arrive at average rate $\lambda$
- Its PMF is $$ p[X=k]=e^{-\lambda}\frac{\lambda^k}{k!}, \qquad k=0,1,2,\ldots $$
- Its CDF is the cumulative sum of the PMF: $$ F(k)=\sum_{j=0}^{\lfloor k \rfloor}e^{-\lambda}\frac{\lambda^j}{j!} $$
In [39]:
@widgets.interact(
lam=widgets.FloatSlider(value=3.0, min=0.1, max=20.0, step=0.1, description="lambda"),
)
def poisson_demo(lam):
dist = stats.poisson(mu=lam)
upper = int(max(8, dist.ppf(0.999)))
values = np.arange(0, upper + 1)
probabilities = dist.pmf(values)
mean = lam
variance = lam
plot_discrete_distribution("Poisson(lambda)", values, probabilities, mean, variance)
interactive(children=(FloatSlider(value=3.0, description='lambda', max=20.0, min=0.1), Output()), _dom_classes…
Example: Lognormal Distribution¶
- A lognormal random variable is positive and right-skewed
- If $\log X \sim N(\mu,\sigma^2)$, then $X$ is lognormally distributed
- Its PDF is $$ f(x;\mu,\sigma)=\frac{1}{x\sigma\sqrt{2\pi}}e^{-(\log x-\mu)^2/(2\sigma^2)}, \qquad x>0 $$
- Its CDF can be written using the standard normal CDF $\Phi$: $$ F(x)=\Phi\left(\frac{\log x-\mu}{\sigma}\right), \qquad x>0 $$
In [40]:
@widgets.interact(
mu=widgets.FloatSlider(value=0.0, min=-2.0, max=2.0, step=0.1, description="mu"),
sigma=widgets.FloatSlider(value=0.5, min=0.1, max=2.0, step=0.1, description="sigma"),
)
def lognormal_demo(mu, sigma):
dist = stats.lognorm(s=sigma, scale=np.exp(mu))
mean = np.exp(mu + sigma**2 / 2)
variance = (np.exp(sigma**2) - 1) * np.exp(2 * mu + sigma**2)
plot_continuous_distribution("Lognormal(mu, sigma)", dist, mean, variance, support=(0, dist.ppf(0.995)))
interactive(children=(FloatSlider(value=0.0, description='mu', max=2.0, min=-2.0), FloatSlider(value=0.5, desc…
Example: Pareto Distribution¶
- The Pareto distribution is a simple model of heavy-tailed positive quantities
- With minimum value $x_m$ and tail parameter $\alpha$, its CDF is $$ F(x)=\begin{cases} 0, & x<x_m \\ 1-\left(\dfrac{x_m}{x}\right)^\alpha, & x\ge x_m \end{cases} $$
- Its PDF is $$ f(x)=\begin{cases} \dfrac{\alpha x_m^\alpha}{x^{\alpha+1}}, & x\ge x_m \\ 0, & x<x_m \end{cases} $$
- As $\alpha$ gets smaller, rare large values become much more important
In [ ]:
@widgets.interact(
alpha=widgets.FloatSlider(value=3.0, min=1.1, max=8.0, step=0.1, description="alpha"),
xm=widgets.FloatSlider(value=1.0, min=0.5, max=5.0, step=0.25, description="x_m"),
)
def pareto_demo(alpha, xm):
dist = stats.pareto(b=alpha, scale=xm)
mean = alpha * xm / (alpha - 1) if alpha > 1 else np.inf
variance = alpha * xm**2 / ((alpha - 1) ** 2 * (alpha - 2)) if alpha > 2 else np.inf
plot_continuous_distribution("Pareto(alpha, x_m)", dist, mean, variance, support=(xm, dist.ppf(0.99)))
interactive(children=(FloatSlider(value=3.0, description='alpha', max=8.0, min=1.1), FloatSlider(value=1.0, de…
Example: Mixture of Normals¶
- A mixture distribution combines two or more probability models
- For a two-component normal mixture with weight $w$, its PDF is $$ f(x)=w f_1(x)+(1-w)f_2(x) $$ where $f_1$ and $f_2$ are normal densities
- Its CDF is the same weighted average of the component CDFs: $$ F(x)=w F_1(x)+(1-w)F_2(x) $$
- This is a useful way to see that distributions can be multi-peaked even when each component is bell-shaped
In [42]:
@widgets.interact(
w=widgets.FloatSlider(value=0.5, min=0.0, max=1.0, step=0.01, description="w"),
mu1=widgets.FloatSlider(value=-2.0, min=-6.0, max=3.0, step=0.25, description="mu1"),
mu2=widgets.FloatSlider(value=2.0, min=-3.0, max=6.0, step=0.25, description="mu2"),
sigma1=widgets.FloatSlider(value=1.0, min=0.2, max=3.0, step=0.1, description="sigma1"),
sigma2=widgets.FloatSlider(value=1.0, min=0.2, max=3.0, step=0.1, description="sigma2"),
)
def normal_mixture_demo(w, mu1, mu2, sigma1, sigma2):
lo = min(mu1 - 4 * sigma1, mu2 - 4 * sigma2)
hi = max(mu1 + 4 * sigma1, mu2 + 4 * sigma2)
x = np.linspace(lo, hi, 700)
pdf = w * stats.norm.pdf(x, mu1, sigma1) + (1 - w) * stats.norm.pdf(x, mu2, sigma2)
cdf = w * stats.norm.cdf(x, mu1, sigma1) + (1 - w) * stats.norm.cdf(x, mu2, sigma2)
mean = w * mu1 + (1 - w) * mu2
second_moment = w * (sigma1**2 + mu1**2) + (1 - w) * (sigma2**2 + mu2**2)
variance = second_moment - mean**2
fig, axes = plt.subplots(1, 2, figsize=(11, 3.8))
axes[0].plot(x, pdf, color="#2d6cdf", lw=2)
axes[0].axvline(mean, color="#9f2f2f", ls="--", lw=1.5, label="E[X]")
axes[0].set_title("PDF")
axes[0].set_xlabel("x")
axes[0].set_ylabel("f(x)")
axes[0].grid(alpha=0.25)
axes[0].legend(loc="best")
axes[1].plot(x, cdf, color="#00876c", lw=2)
axes[1].axvline(mean, color="#9f2f2f", ls="--", lw=1.5)
axes[1].set_title("CDF")
axes[1].set_xlabel("x")
axes[1].set_ylabel("F(x)")
axes[1].set_ylim(-0.04, 1.04)
axes[1].grid(alpha=0.25)
fig.suptitle(
f"Normal mixture: E[X] = {_format_stat(mean)} V[X] = {_format_stat(variance)}",
y=1.05,
fontsize=12,
)
plt.tight_layout()
plt.show()
interactive(children=(FloatSlider(value=0.5, description='w', max=1.0, step=0.01), FloatSlider(value=-2.0, des…