forked from probml/pyprobml
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgauss_seq_update_sigma_1d.py
More file actions
61 lines (52 loc) · 2.29 KB
/
gauss_seq_update_sigma_1d.py
File metadata and controls
61 lines (52 loc) · 2.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# Based on https://github.com/probml/pmtk3/blob/master/demos/gaussSeqUpdateSigma1D.m
# Converted by John Fearns - jdf22@infradead.org
# Sequential updating of Sigma in 1d given fixed mean
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
from scipy.stats import invgamma
from pyprobml_utils import save_fig
# Ensure stochastic reproducibility.
np.random.seed(4)
# Take 100 samples from a Gaussian with mean 5 and variance 10 as our data.
mu = 5
data = norm.rvs(size=100, loc=mu, scale=np.sqrt(10))
# Assume an uninformative prior on the variance of the Gaussian and knowledge
# that the mean is 5.
# This corresponds to a scaled inverse Chi-squared distribution on the variance
# with 0 degrees of freedom. We don't need any variables to model this.
# Define a function that returns updated scaled-inverse-chi-squared posterior parameters for
# our knowledge of the variance, given observed data and the above prior.
# Returns dof, scale.
def posterior_parameters(data):
n = data.shape[0]
return n, np.sum(np.square(data - mu)) / n
# A function that plots a scaled-inverse-chi-squared distribution given its parameters
def plot_posterior(dof, scaling, colour, linestyle, label):
x = np.arange(0, 16, 0.01)
p = scaled_inverse_chi_squared(dof, scaling).pdf(x)
plt.plot(x, p, color=colour, linestyle=linestyle, linewidth=2, label=label)
def scaled_inverse_chi_squared(dof, scale):
# The scaled inverse Chi-squared distribution with the provided params
# is equal to an inverse-gamma distribution with these parameters:
ig_shape = dof / 2
ig_scale = dof * scale / 2
return invgamma(ig_shape, scale=ig_scale)
# For various first-n observations, plot the posterior.
ns = [2, 5, 50, 100]
colours = ['blue', 'red', 'black', 'green']
linestyles = ['-', ':', '-.', '--']
plt.figure()
for i in range(len(ns)):
n = ns[i]
colour = colours[i]
linestyle = linestyles[i]
label = 'N = {}'.format(n)
plot_data = data[:n]
dof, scaling = posterior_parameters(plot_data)
plot_posterior(dof, scaling, colour, linestyle, label)
plt.title(r'prior = IG($\nu=0$), true $\sigma^2=10$')
plt.xlabel(r"$\sigma^2$")
plt.legend(loc='upper right')
save_fig('gaussSeqUpdateSigma1D.pdf')
plt.show()