markov-models/notebook.py

433 lines
11 KiB
Python
Raw Permalink Normal View History

2021-01-01 18:53:11 +00:00
# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
2020-12-31 19:30:39 +00:00
# %%
#IMPORTS AND COMMON VARIABLES
2021-01-01 18:53:11 +00:00
import matplotlib
import matplotlib.cm as cm
2020-12-31 19:30:39 +00:00
import matplotlib.pyplot as plt
2021-01-01 18:53:11 +00:00
from matplotlib.pyplot import savefig
2020-12-31 19:30:39 +00:00
import numpy as np
from math import sqrt
from constants import *
from maths import gaussian
from markov import MarkovModel
from markovlog import LogMarkovModel
2021-01-01 18:53:11 +00:00
fig_dpi = 200
fig_export = False
x = np.linspace(-4, 8, 300) # x values for figures
2020-12-31 19:30:39 +00:00
x_label = "Observation Space"
y_label = "Probability Density"
# %% [markdown]
# State Probability Functions (1)
# ===================
# %%
state_1_y = [gaussian(i, state1.mean, state1.std_dev) for i in x]
state_2_y = [gaussian(i, state2.mean, state2.std_dev) for i in x]
plt.plot(x, state_1_y, c='r', label="State 1")
plt.plot(x, state_2_y, c='b', label="State 2")
plt.legend()
plt.title("State Probability Density Functions")
plt.xlabel(x_label)
plt.ylabel(y_label)
plt.grid(linestyle="--")
2021-01-01 18:53:11 +00:00
fig = matplotlib.pyplot.gcf()
fig.set_dpi(fig_dpi)
fig.set_tight_layout(True)
if fig_export:
savefig("report/res/pdfs.png")
2020-12-31 19:30:39 +00:00
plt.show()
# %% [markdown]
# Output Probability Densities (2)
# ==========
# %%
for obs in observations:
2021-01-01 18:53:11 +00:00
print(f'{obs} -> State 1: {gaussian(obs, state1.mean, state1.std_dev)},',
2021-01-05 11:10:29 +00:00
f'State 2: {gaussian(obs, state2.mean, state2.std_dev)}')
2020-12-31 19:30:39 +00:00
# %%
state_1_y = [gaussian(i, state1.mean, state1.std_dev) for i in x]
state_2_y = [gaussian(i, state2.mean, state2.std_dev) for i in x]
plt.plot(x, state_1_y, c='r', label="State 1")
plt.plot(x, state_2_y, c='b', label="State 2")
plt.legend()
plt.title("State Probability Density Functions With Observations")
plt.xlabel(x_label)
plt.ylabel(y_label)
2021-01-01 18:53:11 +00:00
plt.grid(linestyle="--", axis='y')
2020-12-31 19:30:39 +00:00
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]
#############################################
# Observation Marks
#############################################
config = {
"s": 65,
"marker": 'x'
}
2021-01-01 18:53:11 +00:00
[plt.axvline(x=i, ls='--', lw=1.0, c=(0,0,0), alpha=0.4) for i in observations]
2020-12-31 19:30:39 +00:00
plt.scatter(observations, state1_pd, color=(0.5, 0, 0), **config)
plt.scatter(observations, state2_pd, color=(0, 0, 0.5), **config)
2021-01-01 18:53:11 +00:00
fig = matplotlib.pyplot.gcf()
fig.set_dpi(fig_dpi)
fig.set_tight_layout(True)
if fig_export:
savefig("report/res/pdfs-w-obs.png")
2020-12-31 19:30:39 +00:00
plt.show()
# %% [markdown]
# # Forward Procedure (3)
# %%
2021-01-01 18:53:11 +00:00
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition)
2020-12-31 19:30:39 +00:00
model.populate_forward()
print(model.forward)
forward = model.forward
model.calculate_p_obs_forward()
2021-01-01 18:53:11 +00:00
# %%
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()
2020-12-31 19:30:39 +00:00
# %% [markdown]
# # Backward Procedure (4)
# %%
2021-01-01 18:53:11 +00:00
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition)
2020-12-31 19:30:39 +00:00
model.populate_backward()
print(model.backward)
backward = model.backward
model.calculate_p_obs_backward()
2021-01-01 18:53:11 +00:00
# %%
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()
2020-12-31 19:30:39 +00:00
# %% [markdown]
# # Compare Forward/Backward Final
# %%
2021-01-01 18:53:11 +00:00
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition)
2020-12-31 19:30:39 +00:00
model.populate_forward()
model.populate_backward()
print("forward:", model.calculate_p_obs_forward())
print("backward:", model.calculate_p_obs_backward())
print("diff: ", model.p_obs_forward - model.p_obs_backward)
# %% [markdown]
# # Occupation Likelihoods (5)
# %%
2021-01-01 18:53:11 +00:00
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
2020-12-31 19:30:39 +00:00
occupation = model.occupation
print(model.occupation)
2021-01-01 18:53:11 +00:00
# %%
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()
2020-12-31 19:30:39 +00:00
# %% [markdown]
# # Re-estimate Mean & Variance (6)
# %%
2021-01-01 18:53:11 +00:00
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
2020-12-31 19:30:39 +00:00
print("mean: ", [state1.mean, state2.mean])
print("variance: ", [state1.variance, state2.variance])
print()
print("mean: ", model.reestimated_mean())
print("variance: ", model.reestimated_variance())
# %% [markdown]
# New PDFs (7)
# ===================
# %%
2021-01-01 18:53:11 +00:00
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
2020-12-31 19:30:39 +00:00
new_mean = model.reestimated_mean()
new_var = model.reestimated_variance()
new_std_dev = [sqrt(x) for x in new_var]
state_1_y = [gaussian(i, new_mean[0], new_std_dev[0]) for i in x]
state_2_y = [gaussian(i, new_mean[1], new_std_dev[1]) for i in x]
plt.plot(x, state_1_y, c='r', label="State 1")
plt.plot(x, state_2_y, c='b', label="State 2")
plt.legend()
plt.title("Re-estimated Probability Density Functions")
plt.xlabel(x_label)
plt.ylabel(y_label)
plt.grid(linestyle="--")
2021-01-01 18:53:11 +00:00
fig = matplotlib.pyplot.gcf()
fig.set_dpi(fig_dpi)
2020-12-31 19:30:39 +00:00
plt.show()
# %% [markdown]
# # Compare PDFs (7)
# %%
2021-01-01 18:53:11 +00:00
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
2020-12-31 19:30:39 +00:00
new_mean = model.reestimated_mean()
new_var = model.reestimated_variance()
new_std_dev = [sqrt(x) for x in new_var]
#######################################
# Original
#######################################
state_1_y = [gaussian(i, state1.mean, state1.std_dev) for i in x]
state_2_y = [gaussian(i, state2.mean, state2.std_dev) for i in x]
plt.plot(x, state_1_y, '--', c='r', label="State 1", linewidth=1.0)
plt.plot(x, state_2_y, '--', c='b', label="State 2", linewidth=1.0)
#######################################
# Re-Estimated
#######################################
state_1_new_y = [gaussian(i, new_mean[0], new_std_dev[0]) for i in x]
state_2_new_y = [gaussian(i, new_mean[1], new_std_dev[1]) for i in x]
plt.plot(x, state_1_new_y, c='r', label="New State 1")
plt.plot(x, state_2_new_y, c='b', label="New State 2")
plt.legend()
plt.title("Re-estimated Probability Density Functions")
plt.xlabel(x_label)
plt.ylabel(y_label)
plt.grid(linestyle="--")
2021-01-01 18:53:11 +00:00
fig = matplotlib.pyplot.gcf()
fig.set_dpi(fig_dpi)
fig.set_tight_layout(True)
if fig_export:
savefig("report/res/re-est-pdfs.png")
2020-12-31 19:30:39 +00:00
plt.show()
# %% [markdown]
# # Multiple Iterations
# %%
2021-01-05 11:10:29 +00:00
iterations = 50
2020-12-31 19:30:39 +00:00
2021-01-05 11:10:29 +00:00
fig = plt.figure(dpi=fig_dpi, tight_layout=True)
ax = fig.add_subplot(1, 1, 1, xmargin=0, ymargin=0)
2020-12-31 19:30:39 +00:00
2021-01-05 11:10:29 +00:00
iter_mean = [state1.mean, state2.mean]
iter_var = [state1.variance, state2.variance]
iter_state_transitions = state_transition
ax.plot(x, [gaussian(i, iter_mean[0], sqrt(iter_var[0])) for i in x], '--', c='r', linewidth=1.0)
ax.plot(x, [gaussian(i, iter_mean[1], sqrt(iter_var[1])) for i in x], '--', c='b', linewidth=1.0)
2020-12-31 19:30:39 +00:00
2021-01-01 18:53:11 +00:00
label1=None
label2=None
2020-12-31 19:30:39 +00:00
for i in range(iterations):
2021-01-05 11:10:29 +00:00
iter_model = MarkovModel(states=[State(iter_mean[0], iter_var[0], state1.entry, state1.exit),
State(iter_mean[1], iter_var[1], state2.entry, state2.exit)],
observations=observations,
state_transitions=iter_state_transitions).populate()
# NEW PARAMETERS
iter_mean = iter_model.reestimated_mean()
iter_var = iter_model.reestimated_variance()
iter_state_transitions[1:3, 1:3] = iter_model.reestimated_state_transitions()
print(f"mean ({i}): ", iter_mean)
print(f"var ({i}): ", iter_var)
print(iter_model.reestimated_state_transitions())
2020-12-31 19:30:39 +00:00
print()
2021-01-05 11:10:29 +00:00
state_1_y = [gaussian(i, iter_mean[0], sqrt(iter_var[0])) for i in x]
state_2_y = [gaussian(i, iter_mean[1], sqrt(iter_var[1])) for i in x]
2020-12-31 19:30:39 +00:00
style = '--'
linewidth = 1.0
if i == iterations - 1:
style = '-'
linewidth = 2.0
2021-01-01 18:53:11 +00:00
label1='State 1'
label2='State 2'
2020-12-31 19:30:39 +00:00
2021-01-05 11:10:29 +00:00
ax.plot(x, state_1_y, style, c='r', label=label1, linewidth=linewidth)
ax.plot(x, state_2_y, style, c='b', label=label2, linewidth=linewidth)
2020-12-31 19:30:39 +00:00
2021-01-05 11:10:29 +00:00
ax.set_title("Probability Density Function Iterations")
2020-12-31 19:30:39 +00:00
2021-01-05 11:10:29 +00:00
ax.set_xlabel(x_label)
ax.set_ylabel(y_label)
ax.grid(linestyle="--")
ax.legend()
2020-12-31 19:30:39 +00:00
2021-01-05 11:10:29 +00:00
if fig_export:
2021-01-01 18:53:11 +00:00
savefig("report/res/iterated-pdfs.png")
2021-01-05 11:10:29 +00:00
fig.show()
2020-12-31 19:30:39 +00:00
# %% [markdown]
# # Baum-Welch State Transition Re-estimations
# %%
2021-01-01 18:53:11 +00:00
model = MarkovModel(states=[state1, state2],
observations=observations,
state_transitions=state_transition).populate()
2020-12-31 19:30:39 +00:00
print(a_matrix)
2021-01-05 11:10:29 +00:00
print(model.reestimated_state_transitions())
2020-12-31 19:30:39 +00:00
model.reestimated_state_transitions()
2021-01-05 11:10:29 +00:00
# %%