Skip to content

Commit f3b0eac

Browse files
add get_state_sequence for continuous
1 parent a08f273 commit f3b0eac

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

hmm_class/hmmc.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,35 @@ def likelihood(self, x):
191191
alpha[t] = alpha[t-1].dot(self.A) * B[:,t]
192192
return alpha[-1].sum()
193193

194+
def get_state_sequence(self, x):
195+
# returns the most likely state sequence given observed sequence x
196+
# using the Viterbi algorithm
197+
T = len(x)
198+
199+
# make the emission matrix B
200+
B = np.zeros((self.M, T))
201+
for j in range(self.M):
202+
for t in range(T):
203+
for k in range(self.K):
204+
p = self.R[j,k] * mvn.pdf(x[t], self.mu[j,k], self.sigma[j,k])
205+
B[j,t] += p
206+
207+
# perform Viterbi as usual
208+
delta = np.zeros((T, self.M))
209+
psi = np.zeros((T, self.M))
210+
delta[0] = self.pi*B[:,0]
211+
for t in range(1, T):
212+
for j in range(self.M):
213+
delta[t,j] = np.max(delta[t-1]*self.A[:,j]) * B[j,t]
214+
psi[t,j] = np.argmax(delta[t-1]*self.A[:,j])
215+
216+
# backtrack
217+
states = np.zeros(T, dtype=np.int32)
218+
states[T-1] = np.argmax(delta[T-1])
219+
for t in range(T-2, -1, -1):
220+
states[t] = psi[t+1, states[t+1]]
221+
return states
222+
194223
def likelihood_multi(self, X):
195224
return np.array([self.likelihood(x) for x in X])
196225

@@ -245,6 +274,10 @@ def fake_signal(init=simple_init):
245274
L = hmm.log_likelihood_multi(signals).sum()
246275
print("LL for actual params:", L)
247276

277+
# print most likely state sequence
278+
print("Most likely state sequence for initial observation:")
279+
print(hmm.get_state_sequence(signals[0]))
280+
248281
if __name__ == '__main__':
249282
# real_signal() # will break
250283
fake_signal(init=simple_init)

0 commit comments

Comments
 (0)