1
+ # -*- coding: utf-8 -*-
2
+ # @Author: WuLC
3
+ # @Date: 2017-04-02 08:52:24
4
+ # @Last Modified by: WuLC
5
+ # @Last Modified time: 2017-04-02 09:50:31
6
+
7
+ ###########################################################################################################
8
+ # Viterbi Algorithm for HMM
9
+ # dynamic programming, time complexity O(mn^2), m is the length of sequence of observation, n is the number of hidden states
10
+ # more details can be obtained from: https://tinyurl.com/y8xt2lcf
11
+ ##########################################################################################################
12
+
13
+
14
+ # five elements for HMM
15
+ states = ('Healthy' , 'Fever' )
16
+
17
+ observations = ('normal' , 'cold' , 'dizzy' )
18
+
19
+ start_probability = {'Healthy' : 0.6 , 'Fever' : 0.4 }
20
+
21
+ transition_probability = {
22
+ 'Healthy' : {'Healthy' : 0.7 , 'Fever' : 0.3 },
23
+ 'Fever' : {'Healthy' : 0.4 , 'Fever' : 0.6 },
24
+ }
25
+
26
+ emission_probability = {
27
+ 'Healthy' : {'normal' : 0.5 , 'cold' : 0.4 , 'dizzy' : 0.1 },
28
+ 'Fever' : {'normal' : 0.1 , 'cold' : 0.3 , 'dizzy' : 0.6 },
29
+ }
30
+
31
+
32
+
33
+ def Viterbit (obs , states , s_pro , t_pro , e_pro ):
34
+ path = { s :[] for s in states } # init path: path[s] represents the path ends with s
35
+ curr_pro = {}
36
+ for s in states :
37
+ curr_pro [s ] = s_pro [s ]* e_pro [s ][obs [0 ]]
38
+ for i in xrange (1 , len (obs )):
39
+ last_pro = curr_pro
40
+ curr_pro = {}
41
+ for curr_state in states :
42
+ max_pro , last_sta = max (((last_pro [last_state ]* t_pro [last_state ][curr_state ]* e_pro [curr_state ][obs [i ]], last_state )
43
+ for last_state in states ))
44
+ curr_pro [curr_state ] = max_pro
45
+ path [curr_state ].append (last_sta )
46
+
47
+ # find the final largest probability
48
+ max_pro = - 1
49
+ max_path = None
50
+ for s in states :
51
+ path [s ].append (s )
52
+ if curr_pro [s ] > max_pro :
53
+ max_path = path [s ]
54
+ max_pro = curr_pro [s ]
55
+ # print '%s: %s'%(curr_pro[s], path[s]) # different path and their probability
56
+ return max_path
57
+
58
+
59
+ if __name__ == '__main__' :
60
+ obs = ['normal' , 'cold' , 'dizzy' ]
61
+ print Viterbit (obs , states , start_probability , transition_probability , emission_probability )
0 commit comments