gathered resources, working on report

This commit is contained in:
aj 2021-01-01 18:53:11 +00:00
parent 534b42f4ef
commit 735275d7ae
15 changed files with 1331 additions and 126 deletions

View File

@ -1,4 +1,13 @@
Hidden Markov Models
====================
Speech recognition coursework focusing on training and analysing hidden markov models
Speech recognition coursework focusing on training and analysing hidden markov models.
![PDFs with observations marked](report/res/pdfs-w-obs.png)
Probability density functions with provided observations marked
![Occupation likelihoods](report/res/occupation-line.png)
Occupation likelihoods for each state through time
![Training iterations](report/res/iterated-pdfs.png)
Output Gaussian functions through 5 iterations of Baum-Welch training

File diff suppressed because one or more lines are too long

View File

@ -7,10 +7,10 @@ class MarkovModel:
def __init__(self, states: list, observations: list = list(), state_transitions: list = list()):
self.observations = observations
self.state_transitions = state_transitions # use state number not state index, is padded by entry and exit probs
self.state_transitions = state_transitions
# ^ use state number not state index, is padded by entry and exit probs
self.states = states # number of states
# self.timesteps = list()
self.states = states
self.forward = np.zeros((len(states), len(observations)))
self.p_obs_forward = 0
@ -55,15 +55,20 @@ class MarkovModel:
def populate_forward(self):
"""Populate forward likelihoods for all states/times"""
for t, observation in enumerate(self.observations): # iterate through observations (time)
for state_index, state in enumerate(self.states): # both states at each step
for t, observation in enumerate(self.observations):
# iterate through observations (time)
state_number = state_index + 1 # for easier reading (arrays 0-indexed, numbers start at 1)
for state_index, state in enumerate(self.states):
# both states at each step
state_number = state_index + 1
# ^ for easier reading (arrays 0-indexed, _number 1-indexed)
if t == 0: # calcualte initial, 0 = first row = initial
self.forward[state_index, t] = self.state_transitions[0, state_number] * gaussian(observation, state.mean, state.std_dev)
else:
# each state for each time has two paths leading to it, the same state (this) and the other state (other)
# each state for each time has two paths leading to it,
# the same state (this) and the other state (other)
other_index = self.get_other_state_index(state_index)
other_number = other_index + 1 # for 1 indexing
@ -81,7 +86,8 @@ class MarkovModel:
sum = 0
for state_index, final_likelihood in enumerate(self.forward[:, -1]):
sum += final_likelihood * self.state_transitions[state_index + 1, -1] # get exit prob from state transitions
sum += final_likelihood * self.state_transitions[state_index + 1, -1]
# get exit prob from state transitions ^
self.p_obs_forward = sum
return sum
@ -92,13 +98,16 @@ class MarkovModel:
# initialise with exit probabilities
self.backward[:, -1] = self.state_transitions[1:len(self.states) + 1, -1]
# below iterator skips first observation (will be used when finalising P(O|model)) then reverses list [::-1]
for t, observation in list(enumerate(self.observations[1:]))[::-1]: # iterate backwards through observations (time)
# below iterator skips first observation
# (will be used when finalising P(O|model))
# iterate backwards through observations (time) [::-1] <- reverses list
for t, observation in list(enumerate(self.observations[1:]))[::-1]:
# print(t, observation)
for state_index in range(len(self.states)):
state_number = state_index + 1 # for easier reading (arrays 0-indexed, numbers start at 1)
state_number = state_index + 1
# ^ for easier reading (arrays 0-indexed, _number 1-indexed)
other_index = self.get_other_state_index(state_index)
other_number = other_index + 1 # for 1 indexing
@ -123,7 +132,9 @@ class MarkovModel:
for state_index, initial_likelihood in enumerate(self.backward[:, 0]):
pi = self.state_transitions[0, state_index + 1]
b = gaussian(self.observations[0], self.states[state_index].mean, self.states[state_index].std_dev)
b = gaussian(self.observations[0],
self.states[state_index].mean,
self.states[state_index].std_dev)
beta = initial_likelihood
sum += pi * b * beta
@ -134,7 +145,9 @@ class MarkovModel:
def populate_occupation(self):
"""Populate occupation likelihoods for all states/times"""
for t in range(len(self.observations)): # iterate through observations (time)
for t in range(len(self.observations)):
# iterate through observations (time)
for state_index in range(len(self.states)):
forward_backward = self.forward[state_index, t] * self.backward[state_index, t]
@ -152,7 +165,9 @@ class MarkovModel:
forward = self.forward[from_index, t - 1]
transition = self.state_transitions[from_index + 1, to_index + 1]
emission = gaussian(self.observations[t], self.states[to_index].mean, self.states[to_index].std_dev)
emission = gaussian(self.observations[t],
self.states[to_index].mean,
self.states[to_index].std_dev)
backward = self.backward[to_index, t]
return (forward * transition * emission * backward) / self.observation_likelihood
@ -173,8 +188,10 @@ class MarkovModel:
for to_index in range(length):
# numerator iterates from t = 1 (when 0 indexing, 2 in the notes)
transition_sum = sum(self.transition_likelihood(from_index, to_index, t) for t in range(1, len(self.observations)))
occupation_sum = sum(self.occupation[from_index, t] for t in range(0, len(self.observations)))
transition_sum = sum(self.transition_likelihood(from_index, to_index, t)
for t in range(1, len(self.observations)))
occupation_sum = sum(self.occupation[from_index, t]
for t in range(0, len(self.observations)))
new_transitions[from_index, to_index] = transition_sum / occupation_sum
@ -185,7 +202,8 @@ class MarkovModel:
numerator = 0 # sum over observations( occupation * observation )
denominator = 0 # sum over observations( occupation )
for t, observation in enumerate(self.observations): # iterate through observations (time)
for t, observation in enumerate(self.observations):
# iterate through observations (time)
occupation_likelihood = self.occupation[state_index, t]
@ -204,7 +222,8 @@ class MarkovModel:
numerator = 0 # sum over observations( occupation * (observation - mean)^2 )
denominator = 0 # sum over observations( occupation )
for t, observation in enumerate(self.observations): # iterate through observations (time)
for t, observation in enumerate(self.observations):
# iterate through observations (time)
occupation_likelihood = self.occupation[state_index, t]

View File

@ -1,7 +1,11 @@
# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
#IMPORTS AND COMMON VARIABLES
import matplotlib
import matplotlib.cm as cm
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.pyplot import savefig
import numpy as np
from math import sqrt
@ -10,7 +14,10 @@ from maths import gaussian
from markov import MarkovModel
from markovlog import LogMarkovModel
x = np.linspace(-4, 8, 120) # x values for figures
fig_dpi = 200
fig_export = False
x = np.linspace(-4, 8, 300) # x values for figures
x_label = "Observation Space"
y_label = "Probability Density"
@ -32,6 +39,11 @@ plt.xlabel(x_label)
plt.ylabel(y_label)
plt.grid(linestyle="--")
fig = matplotlib.pyplot.gcf()
fig.set_dpi(fig_dpi)
fig.set_tight_layout(True)
if fig_export:
savefig("report/res/pdfs.png")
plt.show()
# %% [markdown]
@ -40,7 +52,8 @@ plt.show()
# %%
for obs in observations:
print(f'{obs} -> State 1: {gaussian(obs, state1.mean, state1.std_dev)}, State 2: {gaussian(obs, state2.mean, state2.std_dev)}')
print(f'{obs} -> State 1: {gaussian(obs, state1.mean, state1.std_dev)},',
'State 2: {gaussian(obs, state2.mean, state2.std_dev)}')
# %%
@ -55,7 +68,7 @@ plt.title("State Probability Density Functions With Observations")
plt.xlabel(x_label)
plt.ylabel(y_label)
plt.grid(linestyle="--")
plt.grid(linestyle="--", axis='y')
state1_pd = [gaussian(i, state1.mean, state1.std_dev) for i in observations]
state2_pd = [gaussian(i, state2.mean, state2.std_dev) for i in observations]
@ -69,16 +82,24 @@ config = {
"marker": 'x'
}
[plt.axvline(x=i, ls='--', lw=1.0, c=(0,0,0), alpha=0.4) for i in observations]
plt.scatter(observations, state1_pd, color=(0.5, 0, 0), **config)
plt.scatter(observations, state2_pd, color=(0, 0, 0.5), **config)
fig = matplotlib.pyplot.gcf()
fig.set_dpi(fig_dpi)
fig.set_tight_layout(True)
if fig_export:
savefig("report/res/pdfs-w-obs.png")
plt.show()
# %% [markdown]
# # Forward Procedure (3)
# %%
model = MarkovModel(states=[state1, state2], observations=observations, state_transitions=state_transition)
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition)
model.populate_forward()
print(model.forward)
@ -86,11 +107,42 @@ print(model.forward)
forward = model.forward
model.calculate_p_obs_forward()
# %%
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
state_x = np.arange(1, 10)
from numpy import log as ln
plt.plot(state_x, [ln(i) for i in model.forward[0, :]], c='r', label="State 1")
plt.plot(state_x, [ln(i) for i in model.forward[1, :]], c='b', label="State 2")
plt.ylim(top=0)
plt.legend()
plt.title("Forward Log-Likelihoods Over Time")
plt.xlabel("Observation (t)")
plt.ylabel("Log Likelihood")
plt.grid(linestyle="--")
fig = matplotlib.pyplot.gcf()
fig.set_dpi(fig_dpi)
fig.set_tight_layout(True)
if fig_export:
savefig("report/res/forward-logline.png")
plt.show()
# %% [markdown]
# # Backward Procedure (4)
# %%
model = MarkovModel(states=[state1, state2], observations=observations, state_transitions=state_transition)
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition)
model.populate_backward()
print(model.backward)
@ -98,11 +150,42 @@ print(model.backward)
backward = model.backward
model.calculate_p_obs_backward()
# %%
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
state_x = np.arange(1, 10)
from numpy import log as ln
plt.plot(state_x, [ln(i) for i in model.backward[0, :]], c='r', label="State 1")
plt.plot(state_x, [ln(i) for i in model.backward[1, :]], c='b', label="State 2")
plt.ylim(top=0)
plt.legend()
plt.title("Backward Log-Likelihoods Over Time")
plt.xlabel("Observation (t)")
plt.ylabel("Log Likelihood")
plt.grid(linestyle="--")
fig = matplotlib.pyplot.gcf()
fig.set_dpi(fig_dpi)
fig.set_tight_layout(True)
if fig_export:
savefig("report/res/backward-logline.png")
plt.show()
# %% [markdown]
# # Compare Forward/Backward Final
# %%
model = MarkovModel(states=[state1, state2], observations=observations, state_transitions=state_transition)
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition)
model.populate_forward()
model.populate_backward()
@ -115,16 +198,81 @@ print("diff: ", model.p_obs_forward - model.p_obs_backward)
# # Occupation Likelihoods (5)
# %%
model = MarkovModel(states=[state1, state2], observations=observations, state_transitions=state_transition).populate()
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
occupation = model.occupation
print(model.occupation)
# %%
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
fig = plt.figure(figsize=(6,6), dpi=fig_dpi, tight_layout=True)
ax = fig.add_subplot(1, 1, 1, projection="3d", xmargin=0, ymargin=0)
y_width = 0.3
X = np.arange(1, 10) - 0.5
Y = np.arange(1, 3) - 0.5*y_width
X, Y = np.meshgrid(X, Y)
Z = np.zeros(model.forward.size)
dx = np.ones(model.forward.size)
dy = y_width * np.ones(model.forward.size)
colours = [*[(1.0, 0.1, 0.1) for i in range(9)], *[(0.2, 0.2, 1.0) for i in range(9)]]
ax.bar3d(X.flatten(), Y.flatten(), Z,
dx, dy, model.occupation.flatten(),
color=colours, shade=True)
ax.set_yticks([1, 2])
ax.set_zlim(top=1.0)
ax.set_title("Occupation Likelihoods Over Time")
ax.set_xlabel("Observation")
ax.set_ylabel("State")
ax.set_zlabel("Occupation Likelihood")
ax.view_init(35, -72)
if fig_export:
savefig("report/res/occupation-bars.png")
fig.show()
# %%
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
state_x = np.arange(1, 10)
plt.plot(state_x, model.occupation[0, :], c='r', label="State 1")
plt.plot(state_x, model.occupation[1, :], c='b', label="State 2")
plt.legend()
plt.title("Occupation Likelihoods Over Time")
plt.xlabel("Observation (t)")
plt.ylabel("Occupation Likelihood")
plt.grid(linestyle="--")
fig = matplotlib.pyplot.gcf()
fig.set_dpi(fig_dpi)
fig.set_tight_layout(True)
if fig_export:
savefig("report/res/occupation-line.png")
plt.show()
# %% [markdown]
# # Re-estimate Mean & Variance (6)
# %%
model = MarkovModel(states=[state1, state2], observations=observations, state_transitions=state_transition).populate()
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
print("mean: ", [state1.mean, state2.mean])
print("variance: ", [state1.variance, state2.variance])
@ -138,7 +286,9 @@ print("variance: ", model.reestimated_variance())
# ===================
# %%
model = MarkovModel(states=[state1, state2], observations=observations, state_transitions=state_transition).populate()
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
new_mean = model.reestimated_mean()
new_var = model.reestimated_variance()
@ -157,13 +307,17 @@ plt.xlabel(x_label)
plt.ylabel(y_label)
plt.grid(linestyle="--")
fig = matplotlib.pyplot.gcf()
fig.set_dpi(fig_dpi)
plt.show()
# %% [markdown]
# # Compare PDFs (7)
# %%
model = MarkovModel(states=[state1, state2], observations=observations, state_transitions=state_transition).populate()
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
new_mean = model.reestimated_mean()
new_var = model.reestimated_variance()
@ -192,6 +346,11 @@ plt.xlabel(x_label)
plt.ylabel(y_label)
plt.grid(linestyle="--")
fig = matplotlib.pyplot.gcf()
fig.set_dpi(fig_dpi)
fig.set_tight_layout(True)
if fig_export:
savefig("report/res/re-est-pdfs.png")
plt.show()
# %% [markdown]
@ -206,8 +365,12 @@ var = [state1.variance, state2.variance]
plt.plot(x, [gaussian(i, mean[0], sqrt(var[0])) for i in x], '--', c='r', linewidth=1.0)
plt.plot(x, [gaussian(i, mean[1], sqrt(var[1])) for i in x], '--', c='b', linewidth=1.0)
label1=None
label2=None
for i in range(iterations):
model = MarkovModel(states=[State(mean[0], var[0], state1.entry, state1.exit), State(mean[1], var[1], state2.entry, state2.exit)],
model = MarkovModel(states=[State(mean[0], var[0], state1.entry, state1.exit),
State(mean[1], var[1], state2.entry, state2.exit)],
observations=observations,
state_transitions=state_transition)
model.populate()
@ -227,29 +390,35 @@ for i in range(iterations):
if i == iterations - 1:
style = '-'
linewidth = 2.0
label1='State 1'
label2='State 2'
plt.plot(x, state_1_y, style, c='r', linewidth=linewidth)
plt.plot(x, state_2_y, style, c='b', linewidth=linewidth)
plt.plot(x, state_1_y, style, c='r', label=label1, linewidth=linewidth)
plt.plot(x, state_2_y, style, c='b', label=label2, linewidth=linewidth)
plt.title("Probability Density Function Iterations")
plt.xlabel(x_label)
plt.ylabel(y_label)
plt.grid(linestyle="--")
plt.legend()
fig = matplotlib.pyplot.gcf()
fig.set_dpi(fig_dpi)
fig.set_tight_layout(True)
if fig_export or True:
savefig("report/res/iterated-pdfs.png")
plt.show()
# %% [markdown]
# # Baum-Welch State Transition Re-estimations
# %%
model = MarkovModel(states=[state1, state2], observations=observations, state_transitions=state_transition).populate()
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
print(a_matrix)
model.reestimated_state_transitions()
# %%

View File

@ -1,3 +1,4 @@
% Encoding: UTF-8
@misc{towards-data-science-markov-intro,
author = {Rocca, Joseph},
howpublished = {Online},
@ -9,3 +10,42 @@
year = {2019}
}
@Article{numpy,
author = {Charles R. Harris and K. Jarrod Millman and St{'{e}}fan J. van der Walt and Ralf Gommers and Pauli Virtanen and David Cournapeau and Eric Wieser and Julian Taylor and Sebastian Berg and Nathaniel J. Smith and Robert Kern and Matti Picus and Stephan Hoyer and Marten H. van Kerkwijk and Matthew Brett and Allan Haldane and Jaime Fern{'{a}}ndez del R{'{\i}}o and Mark Wiebe and Pearu Peterson and Pierre G{'{e}}rard-Marchant and Kevin Sheppard and Tyler Reddy and Warren Weckesser and Hameer Abbasi and Christoph Gohlke and Travis E. Oliphant},
journal = {Nature},
title = {Array programming with {NumPy}},
year = {2020},
month = sep,
number = {7825},
pages = {357--362},
volume = {585},
doi = {10.1038/s41586-020-2649-2},
publisher = {Springer Science and Business Media {LLC}},
url = {https://doi.org/10.1038/s41586-020-2649-2},
urldate = {2021-1-1},
}
@Misc{python,
author = {Van Rossum, Guido and others},
howpublished = {Online},
title = {Python 3 Documentation},
year = {2008},
url = {https://docs.python.org/3/},
urldate = {2021-1-1},
}
@InProceedings{jupyter,
author = {Thomas Kluyver and Benjamin Ragan-Kelley and Fernando P{\'e}rez and Brian Granger and Matthias Bussonnier and Jonathan Frederic and Kyle Kelley and Jessica Hamrick and Jason Grout and Sylvain Corlay and Paul Ivanov and Dami{\'a}n Avila and Safia Abdalla and Carol Willing and Jupyter development team},
booktitle = {Positioning and Power in Academic Publishing: Players, Agents and Agendas},
title = {Jupyter Notebooks - a publishing format for reproducible computational workflows},
year = {2016},
address = {Netherlands},
editor = {Fernando Loizides and Birgit Scmidt},
pages = {87--90},
publisher = {IOS Press},
abstract = {It is increasingly necessary for researchers in all fields to write computer code, and in order to reproduce research results, it is important that this code is published. We present Jupyter notebooks, a document format for publishing code, results and explanations in a form that is both readable and executable. We discuss various tools and use cases for notebook documents.},
url = {https://eprints.soton.ac.uk/403913/},
urldate = {2021-1-1},
}
@Comment{jabref-meta: databaseType:bibtex;}

View File

@ -10,6 +10,7 @@
\let\endchangemargin=\endlist
\pagenumbering{roman}
\usepackage{pxfonts}
\usepackage{color}
\definecolor{commentgreen}{RGB}{0,94,11}
@ -21,7 +22,6 @@
customHeadersFooters
minimalistic
todonotes
figs-within-sections
\end_modules
\maintain_unincluded_children false
\language english
@ -105,7 +105,7 @@ figs-within-sections
\papercolumns 1
\papersides 1
\paperpagestyle fancy
\listings_params "language=Python,breaklines=true,frame=tb,otherkeywords={self},emph={State},emphstyle={\ttb\color{darkred}},basicstyle={\ttfamily},commentstyle={\color{commentgreen}\itshape},keywordstyle={\color{darkblue}},emphstyle={\color{red}},stringstyle={\color{red}}"
\listings_params "language=Python,breaklines=true,frame=tb,otherkeywords={self},emph={State},emphstyle={\ttb\color{darkred}},basicstyle={\ttfamily},commentstyle={\bfseries\color{commentgreen}\itshape},keywordstyle={\color{darkblue}},emphstyle={\color{red}},stringstyle={\color{red}}"
\bullet 1 0 9 -1
\bullet 2 0 24 -1
\tracking_changes false
@ -418,7 +418,7 @@ noprefix "false"
\end_layout
\begin_layout Standard
As previously mentioned, the states are described 1D continuous probability
As previously mentioned, the states are described by 1D continuous probability
density functions (PDF) of a Gaussian profile.
Each has an associated mean and variance as seen below,
\end_layout
@ -557,7 +557,27 @@ Finally, a set of observations from the above model are provided below,
\begin_layout Standard
These are used as the basis for training the model using the Baum-Welch
equations.
equations
\begin_inset Flex TODO Note (Margin)
status open
\begin_layout Plain Layout
Expectation-maximisation
\end_layout
\end_inset
\begin_inset Flex TODO Note (Margin)
status open
\begin_layout Plain Layout
Cite
\end_layout
\end_inset
.
\end_layout
\begin_layout Section
@ -611,6 +631,53 @@ name "fig:State-topology"
\end_layout
\begin_layout Standard
The work was completed using Python
\begin_inset CommandInset citation
LatexCommand cite
key "python"
literal "false"
\end_inset
and the Jupyter notebook
\begin_inset CommandInset citation
LatexCommand cite
key "jupyter"
literal "false"
\end_inset
.
Apart from the standard library, NumPy
\begin_inset CommandInset citation
LatexCommand cite
key "numpy"
literal "false"
\end_inset
was used for a n-dimensional array implementation.
\end_layout
\begin_layout Standard
An implementation of the Gaussian function was written in order to derive
output probability densities for each state given an observation, see listing
\begin_inset CommandInset ref
LatexCommand ref
reference "maths-listing"
plural "false"
caps "false"
noprefix "false"
\end_inset
.
This was used to plot each of the PDFs and throughout the likelihood calculatio
ns.
\end_layout
\begin_layout Section
Results
\end_layout
@ -619,6 +686,21 @@ Results
Output Probability Density Functions
\end_layout
\begin_layout Standard
The Gaussian probability functions described by the initial parameters can
be seen in figure
\begin_inset CommandInset ref
LatexCommand ref
reference "fig:PDFs"
plural "false"
caps "false"
noprefix "false"
\end_inset
.
\end_layout
\begin_layout Standard
\begin_inset Float figure
wide false
@ -630,7 +712,8 @@ status open
\align center
\begin_inset Graphics
filename res/pdfs.png
width 50col%
lyxscale 50
width 70col%
\end_inset
@ -669,6 +752,33 @@ name "fig:PDFs"
Observation Probability Densities
\end_layout
\begin_layout Standard
The output probability densities for each observation in each state can
be seen in table
\begin_inset CommandInset ref
LatexCommand ref
reference "tab:obs-prob-dens"
plural "false"
caps "false"
noprefix "false"
\end_inset
.
These observations can be seen overlaid on the original PDFs in figure
\begin_inset CommandInset ref
LatexCommand ref
reference "fig:PDFs-w-obs"
plural "false"
caps "false"
noprefix "false"
\end_inset
.
\end_layout
\begin_layout Standard
\begin_inset Float table
wide false
@ -1161,7 +1271,8 @@ status open
\align center
\begin_inset Graphics
filename res/pdfs-w-obs.png
width 50col%
lyxscale 50
width 70col%
\end_inset
@ -1206,6 +1317,50 @@ name "fig:PDFs-w-obs"
Forward Procedure and Likelihoods
\end_layout
\begin_layout Standard
The forward likelihoods calculated as part of the forward procedure can
be seen in figure
\begin_inset CommandInset ref
LatexCommand ref
reference "tab:Forward-likelihoods"
plural "false"
caps "false"
noprefix "false"
\end_inset
.
The natural logarithm of these results can be seen graphically in figure
\begin_inset CommandInset ref
LatexCommand ref
reference "fig:forward-log-like"
plural "false"
caps "false"
noprefix "false"
\end_inset
.
The log-likelihoods were used here as subsequent values can decrease by
orders of magnitude making it hard to display, as a monotonic function,
the relationship between values remains relevant when presenting the log
of each value
\begin_inset Flex TODO Note (Margin)
status open
\begin_layout Plain Layout
Reword?
\end_layout
\end_inset
.
For state 1, the forward likelihood generally decreases over time, this
pattern is not followed by state 2.
State 2 begins decreasing before rapidly decreasing and increasing.
\end_layout
\begin_layout Standard
\begin_inset Float table
wide false
@ -1620,7 +1775,41 @@ name "tab:Forward-likelihoods"
\end_layout
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Float figure
wide false
sideways false
status open
\begin_layout Plain Layout
\noindent
\align center
\begin_inset Graphics
filename res/forward-logline.png
lyxscale 50
width 50col%
\end_inset
\end_layout
\begin_layout Plain Layout
\begin_inset Caption Standard
\begin_layout Plain Layout
Forward log-likelihood for each state over all observations
\begin_inset CommandInset label
LatexCommand label
name "fig:forward-log-like"
\end_inset
\end_layout
@ -1629,10 +1818,76 @@ name "tab:Forward-likelihoods"
\end_layout
\end_inset
\end_layout
\begin_layout Standard
Using the forward procedure, the observation likelihood,
\begin_inset Formula $P\left(\mathcal{O}|\lambda\right)$
\end_inset
, was calculated as follows
\end_layout
\begin_layout Standard
\begin_inset Formula
\begin{equation}
P\left(\mathcal{O}|\lambda\right)=\eta_{1}\alpha_{9}\left(1\right)+\eta_{2}\alpha_{9}\left(2\right)\label{eq:forward-symbolic}
\end{equation}
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Formula
\begin{equation}
P\left(\mathcal{O}|\lambda\right)=\left(0.02\cdot5.63\times10^{-10}\right)+\left(0.03\cdot6.02\times10^{-9}\right)=1.92\times10^{-10}\label{eq:forward}
\end{equation}
\end_inset
to 2 decimal places.
\end_layout
\begin_layout Subsection
Backward Procedure and Likelihoods
\end_layout
\begin_layout Standard
The backward likelihoods were calculated as part of the backwards procedure
and can be seen in table
\begin_inset CommandInset ref
LatexCommand ref
reference "tab:Backward-likelihoods"
plural "false"
caps "false"
noprefix "false"
\end_inset
, the log-likelihoods can be seen in figure
\begin_inset CommandInset ref
LatexCommand ref
reference "fig:backward-log-like"
plural "false"
caps "false"
noprefix "false"
\end_inset
.
Reading backwards in time (from bottom to top), for both states the backwards
likelihood can be seen to decrease to a minimum at
\begin_inset Formula $t=1$
\end_inset
.
\end_layout
\begin_layout Standard
\begin_inset Float table
wide false
@ -2055,14 +2310,130 @@ name "tab:Backward-likelihoods"
\end_layout
\begin_layout Subsection
Observations Likelihood
\begin_layout Standard
\begin_inset Float figure
wide false
sideways false
status open
\begin_layout Plain Layout
\noindent
\align center
\begin_inset Graphics
filename res/backward-logline.png
lyxscale 50
width 50col%
\end_inset
\end_layout
\begin_layout Plain Layout
\begin_inset Caption Standard
\begin_layout Plain Layout
Backward log-likelihood for each state over all observations
\begin_inset CommandInset label
LatexCommand label
name "fig:backward-log-like"
\end_inset
\end_layout
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Standard
Finalising the backward procedure can also produce
\begin_inset Formula $P\left(\mathcal{O}|\lambda\right)$
\end_inset
,
\end_layout
\begin_layout Standard
\begin_inset Formula
\begin{equation}
P\left(\mathcal{O}|\lambda\right)=\pi_{1}b_{1}\left(o_{1}\right)\beta_{1}\left(1\right)+\pi_{2}b_{2}\left(o_{1}\right)\beta_{1}\left(2\right)\label{eq:backward-symbolic}
\end{equation}
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Formula
\begin{equation}
P\left(\mathcal{O}|\lambda\right)=\left(0.44\cdot0.022\cdot6.58\times10^{-11}\right)+\left(0.56\cdot0.55\cdot6.25\times10^{-10}\right)=1.92\times10^{-10}\label{eq:backward}
\end{equation}
\end_inset
to 2 decimal places.
Looking back to equation
\begin_inset CommandInset ref
LatexCommand ref
reference "eq:forward"
plural "false"
caps "false"
noprefix "false"
\end_inset
, these can be seen to be the same, as expected
\begin_inset Flex TODO Note (Margin)
status open
\begin_layout Plain Layout
Maybe move to discussion?
\end_layout
\end_inset
.
\end_layout
\begin_layout Subsection
Occupation Likelihoods
\end_layout
\begin_layout Standard
The above forward and backward likelihoods were used to calculate the occupation
likelihoods of each state at each time step, the results can be seen in
table
\begin_inset CommandInset ref
LatexCommand ref
reference "tab:Occupation-likelihoods"
plural "false"
caps "false"
noprefix "false"
\end_inset
and are presented graphically in figure
\begin_inset CommandInset ref
LatexCommand ref
reference "fig:occupation-likelihood-bars"
plural "false"
caps "false"
noprefix "false"
\end_inset
.
\end_layout
\begin_layout Standard
\begin_inset Float table
wide false
@ -2438,6 +2809,49 @@ name "tab:Occupation-likelihoods"
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Float figure
wide false
sideways false
status open
\begin_layout Plain Layout
\noindent
\align center
\begin_inset Graphics
filename res/occupation-line.png
lyxscale 50
width 70col%
\end_inset
\end_layout
\begin_layout Plain Layout
\begin_inset Caption Standard
\begin_layout Plain Layout
Occupation likelihoods for each state for each observation
\begin_inset CommandInset label
LatexCommand label
name "fig:occupation-likelihood-bars"
\end_inset
\end_layout
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Subsection
@ -2448,6 +2862,266 @@ Baum-Welch Re-estimations
Output Parameters
\end_layout
\begin_layout Standard
Following one iteration of Baum-Welch training, the output Gaussian parameters
were estimated as follows (2 d.p.),
\end_layout
\begin_layout Standard
\noindent
\align center
\begin_inset Tabular
<lyxtabular version="3" rows="3" columns="3">
<features tabularvalignment="middle">
<column alignment="center" valignment="top">
<column alignment="center" valignment="top">
<column alignment="center" valignment="top">
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
State,
\begin_inset Formula $i$
\end_inset
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
1
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
2
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Mean,
\begin_inset Formula $\mu_{i}$
\end_inset
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
1.67
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
4.09
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Variance,
\begin_inset Formula $\varSigma_{i}$
\end_inset
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
1.85
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
0.37
\end_layout
\end_inset
</cell>
</row>
</lyxtabular>
\end_inset
\end_layout
\begin_layout Standard
This represents the following deltas from the original parameters (2 s.f.),
\end_layout
\begin_layout Standard
\noindent
\align center
\begin_inset Tabular
<lyxtabular version="3" rows="3" columns="3">
<features tabularvalignment="middle">
<column alignment="center" valignment="top">
<column alignment="center" valignment="top">
<column alignment="center" valignment="top">
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
State,
\begin_inset Formula $i$
\end_inset
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
1
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
2
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Mean,
\begin_inset Formula $\mu_{i}$
\end_inset
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
+0.67
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
+0.089
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Variance,
\begin_inset Formula $\varSigma_{i}$
\end_inset
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
+0.41
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
-0.11
\end_layout
\end_inset
</cell>
</row>
</lyxtabular>
\end_inset
\end_layout
\begin_layout Standard
Displayed graphically, these two sets of Gaussian functions can be seen
in figure
\begin_inset CommandInset ref
LatexCommand ref
reference "fig:Re-estimated-PDFs"
plural "false"
caps "false"
noprefix "false"
\end_inset
.
Compared to the original function, increasing the standard deviation has
widened and shortened the new function for state 1.
The slight increase in mean has also shifted the function to the right.
For state 2, the new function has a tighter, taller distribution as a result
of the decreased variance; the mean has, again, been slightly shifted to
the right.
\end_layout
\begin_layout Standard
\begin_inset Float figure
wide false
@ -2459,7 +3133,8 @@ status open
\align center
\begin_inset Graphics
filename res/re-est-pdfs.png
width 50col%
lyxscale 50
width 70col%
\end_inset
@ -2490,10 +3165,6 @@ name "fig:Re-estimated-PDFs"
\end_layout
\begin_layout Subsubsection
State Transitions
\end_layout
\begin_layout Section
Discussion
\end_layout
@ -2526,13 +3197,6 @@ options "bibtotoc"
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Newpage newpage
\end_inset
\end_layout
\begin_layout Section
@ -2567,11 +3231,7 @@ lstparams "caption={Maths utility file with definition for a gaussian},label={ma
\end_layout
\begin_layout Standard
\begin_inset CommandInset include
LatexCommand lstinputlisting
filename "../markov.py"
lstparams "caption={Markov model object defining forward and backward procedure, occupation likelihoods, Baum-Welch equations},label={markov-listing}"
\begin_inset Newpage newpage
\end_inset
@ -2580,8 +3240,8 @@ lstparams "caption={Markov model object defining forward and backward procedure,
\begin_layout Standard
\begin_inset CommandInset include
LatexCommand lstinputlisting
filename "../markovlog.py"
lstparams "caption={Child Markov model re-implementing calculations using log probability and likelihood},label={log-markov-listing}"
filename "../markov.py"
lstparams "caption={Markov model object defining forward and backward procedure, occupation likelihoods, Baum-Welch equations},label={markov-listing}"
\end_inset
@ -2599,14 +3259,97 @@ lstparams "caption={Child Markov model re-implementing calculations using log pr
The development of the model behind this report was completed using Jupyter
Notebook.
The used notebook can be seen formatted in plain text below, the relevant
mark scheme elements are referenced in brackets.
mark scheme elements are referenced in brackets (
\begin_inset listings
inline true
status open
\begin_layout Plain Layout
\noindent
%%
\end_layout
\end_inset
= cell delimiter).
\end_layout
\begin_layout Standard
\begin_inset CommandInset include
LatexCommand lstinputlisting
filename "../notebook.py"
lstparams "caption={Plain output of Jupyter Notebook used for development and debugging},label={notebook-listing}"
lstparams "commentstyle={\\large\\bfseries\\color{commentgreen}},caption={Plain output of Jupyter Notebook used for development and debugging},label={notebook-listing}"
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Newpage newpage
\end_inset
\end_layout
\begin_layout Section
Extensions
\end_layout
\begin_layout Standard
A few extra calculations were done with the model, figure
\begin_inset CommandInset ref
LatexCommand ref
reference "fig:5-training-iterations"
plural "false"
caps "false"
noprefix "false"
\end_inset
shows how the output probability density functions move during 5 iterations
of training.
\end_layout
\begin_layout Standard
\begin_inset Float figure
placement h
wide false
sideways false
status open
\begin_layout Plain Layout
\noindent
\align center
\begin_inset Graphics
filename res/iterated-pdfs.png
lyxscale 50
width 70col%
\end_inset
\end_layout
\begin_layout Plain Layout
\begin_inset Caption Standard
\begin_layout Plain Layout
5 iterations of training completed using the Baum-Welch equations
\begin_inset CommandInset label
LatexCommand label
name "fig:5-training-iterations"
\end_inset
\end_layout
\end_inset
\end_layout
\end_inset

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 98 KiB

View File

@ -320,13 +320,6 @@
"\n",
"model.baum_welch_state_transitions()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {