from scipy.stats import norm, multivariate_normal, entropy
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
42)
np.random.seed("../aux-files/custom-theme.mplstyle")
plt.style.use(= "#FFC300"
yellow = "#3399FF"
blue = "#FF3399"
pink = "#121212"
grey = "#E5E5E5"
white = [yellow, blue, pink]
colors
= [grey, yellow]
cmap_colors = LinearSegmentedColormap.from_list("my_cmap", cmap_colors) custom_cmap
= 6
n = np.random.rand(n ** 2)
joint = joint / joint.sum()
joint = joint.reshape(n, n)
joint
= sns.heatmap(joint.T, annot=True, fmt=".3f", cmap=custom_cmap, linewidth=8, linecolor=grey)
ax "x")
plt.xlabel("y")
plt.ylabel(
ax.invert_yaxis() plt.show()
= plt.subplots(nrows=2, ncols=3, sharey=True, sharex=True)
fig, axes = axes.flatten()
axes = []
conditionals
for x, ax in enumerate(axes):
= joint[x, :] / joint[x, :].sum()
conditional
conditionals.append(conditional)range(n), conditional, width=0.4, zorder=2)
ax.bar(range(n))
ax.set_xticks(range(n))
ax.set_xticklabels(rf"$x={x}$")
ax.set_title(
r"$y$")
fig.supxlabel("probability")
fig.supylabel(r"conditional distributions $f(y\mid x)$")
fig.suptitle(
plt.tight_layout() plt.show()
= joint.sum(axis=1)
X = joint.sum(axis=0)
Y
= plt.subplots(ncols=2, sharey=True, sharex=True, figsize=(7, 3))
fig, axes
0].bar(range(n), X, width=0.4)
axes[0].set_xlabel(r"$x$")
axes[0].set_title(r"marginal distribution $f(x)$")
axes[
1].bar(range(n), Y, width=0.4)
axes[1].set_xlabel(r"$y$")
axes[1].set_title(r"marginal distribution $f(y)$")
axes[
"probability")
fig.supylabel(
plt.tight_layout()=0.4)
plt.subplots_adjust(wspace plt.show()
= entropy(Y) - sum([entropy(conditional) * X[x] for x, conditional in enumerate(conditionals)])
info print(f"The mutual information between X and Y is {info:.4f}.")
The mutual information between $X$ and $Y$ is 0.2032.
def plot_multivar(ax, muX, muY, sigmaX, sigmaY, x, y, labels=False):
= np.array([[sigmaX ** 2, rho * sigmaX * sigmaY], [rho * sigmaX * sigmaY, sigmaY ** 2]])
Sigma = np.array([muX, muY])
Mu = multivariate_normal(mean=Mu, cov=Sigma)
U = np.dstack((x, y))
grid = U.pdf(grid)
z = ax.contour(x, y, z, colors=yellow, alpha=0.5)
contour if labels:
=True, fontsize=8)
ax.clabel(contour, inline
def plot_conditional(ax, muX, muY, sigmaX, sigmaY, rho, y, x_obs):
= muY + (x_obs - muX) * rho * sigmaY / sigmaX
mu = sigmaY * np.sqrt(1 - rho ** 2)
sigma = norm(loc=mu, scale=sigma).pdf(y)
x -x + x_obs, y, color=blue)
ax.plot(-x + x_obs, x_obs, color=blue, alpha=0.4)
ax.fill_betweenx(y,
def plot_combined(ax, muX, muY, sigmaX, sigmaY, rho, x, y, x_obs, labels=False):
plot_multivar(ax, muX, muY, sigmaX, sigmaY, x, y, labels)= np.linspace(np.min(y), np.max(y), num=250)
y 0])
plot_conditional(ax, muX, muY, sigmaX, sigmaY, rho, y, x_obs[1])
plot_conditional(ax, muX, muY, sigmaX, sigmaY, rho, y, x_obs[2])
plot_conditional(ax, muX, muY, sigmaX, sigmaY, rho, y, x_obs[rf"$\rho ={rho}$")
ax.set_title(r"$x$")
ax.set_xlabel(r"$y$")
ax.set_ylabel(
plt.tight_layout()
plt.show()
= plt.subplots()
_, ax = np.mgrid[-1:3:0.01, -4:6:0.01]
x, y
= 1
muX = 1
muY = 1
sigmaX = 2
sigmaY = 0.15
rho
=[0, 1, 2], labels=False) plot_combined(ax, muX, muY, sigmaX, sigmaY, rho, x, y, x_obs
= plt.subplots()
_, ax = 0.50
rho =[0, 1, 2], labels=False) plot_combined(ax, muX, muY, sigmaX, sigmaY, rho, x, y, x_obs
= plt.subplots()
_, ax = 0.85
rho =[0, 1, 2], labels=False) plot_combined(ax, muX, muY, sigmaX, sigmaY, rho, x, y, x_obs