# Bayesian inference for simple linear regression with known noise variance
# The goal is to reproduce fig 3.7 from Bishop's book.
# We fit the linear model f(x,w) = w0 + w1*x and plot the posterior over w.
import numpy as np
import matplotlib.pyplot as plt
import os
# try:
# import probml_utils as pml
# except ModuleNotFoundError:
# %pip install -qq git+https://github.com/probml/probml-utils.git
# import probml_utils as pml
from scipy.stats import uniform, norm, multivariate_normal
from tueplots import bundles
plt.rcParams.update(bundles.icml2022())
Bayesian Linear Regression Posterior Figures
'figure.figsize': (4.5, 2.0086104634371584)}) plt.rcParams.update({
0)
np.random.seed(
# Number of samples to draw from posterior distribution of parameters.
= 10
NSamples
# Each of these corresponds to a row in the graphic and an amount of data the posterior will reflect.
# First one must be zero, for the prior.
= [0, 1, 2, 5, 10, 20, 100]
DataIndices
# True regression parameters that we wish to recover. Do not set these outside the range of [-1,1]
= -0.3
a0 = 0.5
a1
= 100 # Number of (x,y) training points
NPoints = 0.2 # True noise standard deviation
noiseSD = 2.0 # Fix the prior precision, alpha. We will use a zero-mean isotropic Gaussian.
priorPrecision = noiseSD # Assume the likelihood precision, beta, is known.
likelihoodSD = 1.0 / (likelihoodSD**2)
likelihoodPrecision
# Because of how axises are set up, x and y values should be in the same range as the coefficients.
= 2 * uniform().rvs(NPoints) - 1
x = a0 + a1 * x + norm(0, noiseSD).rvs(NPoints)
y
def MeanCovPost(x, y):
# Given data vectors x and y, this returns the posterior mean and covariance.
= np.array([[1, x1] for x1 in x])
X = np.diag([priorPrecision] * 2) + likelihoodPrecision * X.T.dot(X)
Precision = np.linalg.inv(Precision)
Cov = likelihoodPrecision * Cov.dot(X.T.dot(y))
Mean return {"Mean": Mean, "Cov": Cov}
def GaussPdfMaker(mean, cov):
# For a given (mean, cov) pair, this returns a vectorized pdf function.
def out(w1, w2):
return multivariate_normal.pdf([w1, w2], mean=mean, cov=cov)
return np.vectorize(out)
def LikeFMaker(x0, y0):
# For a given (x,y) pair, this returns a vectorized likelhood function.
def out(w1, w2):
= y0 - (w1 + w2 * x0)
err return norm.pdf(err, loc=0, scale=likelihoodSD)
return np.vectorize(out)
# Grid space for which values will be determined, which is shared between the coefficient space and data space.
= np.linspace(-1, 1, 50)
grid = np.array([[1, g] for g in grid])
Xg = np.meshgrid(grid, grid)
G1, G2
# If we have many samples of lines, we make them a bit transparent.
= 5.0 / NSamples if NSamples > 50 else 1.0
alph
# A function to make some common adjustments to our subplots.
def adjustgraph(whitemark):
if whitemark:
r"$\theta_0$")
plt.ylabel(r"$\theta_1$")
plt.xlabel(# plt.scatter(a0, a1, marker="+", color="white", s=100)
else:
"y")
plt.ylabel("x")
plt.xlabel(-1, 1])
plt.ylim([-1, 1])
plt.xlim([-1, 0, 1])
plt.xticks([-1, 0, 1])
plt.yticks([return None
def create_figure(data_index):
= plt.figure()
fig
# Left graph
if(data_index==0):
= fig.add_subplot(1, 3, 1)
ax1 "likelihood")
ax1.set_title("off")
ax1.axis(else:
= fig.add_subplot(1, 3, 1)
ax1 = LikeFMaker(x[di - 1], y[di - 1])
likfunc 100)
ax1.contourf(G1, G2, likfunc(G1, G2), True)
adjustgraph("likelihood")
ax1.set_title(# ax1.axis("off")
# Middle graph
= fig.add_subplot(1, 3, 2)
ax2 = GaussPdfMaker(postM, postCov)
postfunc 100)
ax2.contourf(G1, G2, postfunc(G1, G2), True)
adjustgraph("prior/posterior")
ax2.set_title(
# Right graph
= fig.add_subplot(1, 3, 3)
ax3 = multivariate_normal(postM, postCov).rvs(NSamples)
Samples = Xg.dot(Samples.T)
Lines if data_index != 0:
=140, facecolors="none", edgecolors="b")
ax3.scatter(x[:data_index], y[:data_index], sfor j in range(Lines.shape[1]):
=2, color="r", alpha=alph)
ax3.plot(grid, Lines[:, j], linewidthFalse)
adjustgraph('data space')
ax3.set_title(
return fig
# Loop through DataIndices to create separate figures for each row
for di in DataIndices:
if di == 0:
= [0, 0]
postM = np.diag([1.0 / priorPrecision] * 2)
postCov else:
= MeanCovPost(x[:di], y[:di])
Post = Post["Mean"]
postM = Post["Cov"]
postCov
= create_figure(di)
fig
plt.tight_layout()f"blr_{di}.png", dpi=900)
plt.savefig( plt.show()
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm, multivariate_normal
0)
np.random.seed(
= 10
NSamples = [0, 1, 2, 5, 10, 20, 100]
DataIndices = -0.3
a0 = 0.5
a1 = 100
NPoints = 0.2
noiseSD = 2.0
priorPrecision = noiseSD
likelihoodSD = 1.0 / (likelihoodSD**2)
likelihoodPrecision
= 2 * np.random.random(NPoints) - 1
x = a0 + a1 * x + np.random.normal(0, noiseSD, NPoints)
y
def MeanCovPost(x, y):
= np.array([[1, x1] for x1 in x])
X = np.diag([priorPrecision] * 2) + likelihoodPrecision * X.T.dot(X)
Precision = np.linalg.inv(Precision)
Cov = likelihoodPrecision * Cov.dot(X.T.dot(y))
Mean return {"Mean": Mean, "Cov": Cov}
def GaussPdfMaker(mean, cov):
def out(w1, w2):
return multivariate_normal.pdf([w1, w2], mean=mean, cov=cov)
return np.vectorize(out)
def LikeFMaker(x0, y0):
def out(w1, w2):
= y0 - (w1 + w2 * x0)
err return norm.pdf(err, loc=0, scale=likelihoodSD)
return np.vectorize(out)
= np.linspace(-1, 1, 50)
grid = np.array([[1, g] for g in grid])
Xg = np.meshgrid(grid, grid)
G1, G2
= 5.0 / NSamples if NSamples > 50 else 1.0
alph
def adjustgraph(whitemark):
if whitemark:
r"$\theta_0$")
plt.ylabel(r"$\theta_1$")
plt.xlabel(else:
"y")
plt.ylabel("x")
plt.xlabel(-1, 1])
plt.ylim([-1, 1])
plt.xlim([-1, 0, 1])
plt.xticks([-1, 0, 1])
plt.yticks([return None
def create_figure(data_index):
= plt.figure(figsize=(15, 5))
fig
= fig.add_subplot(1, 3, 1)
ax1 if data_index == 0:
"likelihood")
ax1.set_title("off")
ax1.axis(else:
= LikeFMaker(x[di - 1], y[di - 1])
likfunc 100)
ax1.contourf(G1, G2, likfunc(G1, G2), True)
adjustgraph("likelihood")
ax1.set_title(
= fig.add_subplot(1, 3, 2)
ax2 = GaussPdfMaker(postM, postCov)
postfunc 100)
ax2.contourf(G1, G2, postfunc(G1, G2), True)
adjustgraph("prior/posterior")
ax2.set_title(
= fig.add_subplot(1, 3, 3)
ax3 = multivariate_normal(postM, postCov).rvs(NSamples)
Samples = Xg.dot(Samples.T)
Lines if data_index != 0:
=140, facecolors="none", edgecolors="b")
ax3.scatter(x[:data_index], y[:data_index], sfor j in range(Lines.shape[1]):
=2, color="r", alpha=alph)
ax3.plot(grid, Lines[:, j], linewidthFalse)
adjustgraph('data space')
ax3.set_title(
plt.tight_layout()return fig
for di in DataIndices:
if di == 0:
= [0, 0]
postM = np.diag([1.0 / priorPrecision] * 2)
postCov else:
= MeanCovPost(x[:di], y[:di])
Post = Post["Mean"]
postM = Post["Cov"]
postCov
= create_figure(di)
fig #plt.savefig(f"blr_{di}.png", dpi=300)
plt.show()
/tmp/ipykernel_3006897/2174210570.py:86: UserWarning: This figure was using constrained_layout, but that is incompatible with subplots_adjust and/or tight_layout; disabling constrained_layout.
plt.tight_layout()
/tmp/ipykernel_3006897/2174210570.py:86: UserWarning: This figure was using constrained_layout, but that is incompatible with subplots_adjust and/or tight_layout; disabling constrained_layout.
plt.tight_layout()
/tmp/ipykernel_3006897/2174210570.py:86: UserWarning: This figure was using constrained_layout, but that is incompatible with subplots_adjust and/or tight_layout; disabling constrained_layout.
plt.tight_layout()
/tmp/ipykernel_3006897/2174210570.py:86: UserWarning: This figure was using constrained_layout, but that is incompatible with subplots_adjust and/or tight_layout; disabling constrained_layout.
plt.tight_layout()
/tmp/ipykernel_3006897/2174210570.py:86: UserWarning: This figure was using constrained_layout, but that is incompatible with subplots_adjust and/or tight_layout; disabling constrained_layout.
plt.tight_layout()
/tmp/ipykernel_3006897/2174210570.py:86: UserWarning: This figure was using constrained_layout, but that is incompatible with subplots_adjust and/or tight_layout; disabling constrained_layout.
plt.tight_layout()
/tmp/ipykernel_3006897/2174210570.py:86: UserWarning: This figure was using constrained_layout, but that is incompatible with subplots_adjust and/or tight_layout; disabling constrained_layout.
plt.tight_layout()