\
HMM Forward algorithm
input Matrix A,B vector pi
import numpy as np
A=np.array([[0.5,0.2,0.3],[0.3,0.5,0.2],[0.2,0.3,0.5]])
B=np.array([[0.5,0.5],[0.4,0.6],[0.7,0.3]])
O=np.array([0 ,1, 0]) #T=3
pi=np.array([0.2,0.4,0.4])
N=3#N kind state
M=2#M kind of observation
T=3
initialize:
alpha=np.zeros((3,3),np.float)
for i in range(N):
alpha[0,i]=pi[i]*B[i,O[0]]
Recursion:
for t in range(T-1):
for i in range(N):
for j in range(N):
alpha[t+1,i]+=alpha[t,j]
A[j,i]
alpha[t+1,i]
compute P(O|lamda) and termination
P=0
for i in range(N):
P+=alpha[T-1,i] #begin with 0 so T-1
print P
backward
initialize:
Beta=np.zeros((T,N),np.float)
print Beta
for i in range(N):
Beta[T-1,i]=1
recursion:
for t in range(T-2,-1,-1):
for i in range(N):
for j in range(N):
Beta[t,i]+=A[i,j] B[j,O[t+1]] Beta[t+1,j]
termination:
P_back=0
for i in range(N):
P_back+=pi[i] B[i,O[0]] Beta[0,i]
print P_back
\
\
transition_probability = { ‘Healthy’ : {‘Healthy’: 0.7, ‘Fever’: 0.3}, ‘Fever’ : {‘Healthy’: 0.4, ‘Fever’: 0.6} }
emission_probability = { ‘Healthy’ : {‘normal’: 0.5, ‘cold’: 0.4, ‘dizzy’: 0.1}, ‘Fever’ : {‘normal’: 0.1, ‘cold’: 0.3, ‘dizzy’: 0.6} } def viterbi(obs, states, start_p, trans_p, emit_p): V = [{}] path = {}
# Initialize base cases (t == 0)
for y in states:
V[0][y] = start_p[y] * emit_p[y][obs[0]]
path[y] = [y]
# Run Viterbi for t > 0
for t in range(1, len(obs)):
V.append({})
newpath = {}
for y in states:
(prob, state) = max((V[t-1][y0] * trans_p[y0][y] * emit_p[y][obs[t]], y0) for y0 in states)
V[t][y] = prob
newpath[y] = path[state] + [y]
# Don't need to remember the old paths
path = newpath
n = 0 # if only one element is observed max is sought in the initialization values
if len(obs) != 1:
n = t
print_dptable(V)
(prob, state) = max((V[n][y], y) for y in states)
return (prob, path[state])
Don’t study this, it just prints a table of the steps.
def print_dptable(V): s = ” ” + ” “.join((“%7d” % i) for i in range(len(V))) + “\n” for y in V[0]: s += “%.5s: ” % y s += ” “.join(“%.7s” % (“%f” % v[y]) for v in V) s += “\n” print(s)
\