states = ('Healthy', 'Fever')
observations = ('normal', 'cold', 'dizzy')
start_probability = {'Healthy': 0.6, 'Fever': 0.4}
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},
}
# Helps visualize the steps of Viterbi.
def print_dptable(V):
print " ",
for i in range(len(V)): print "%7s" % ("%d" % i),
print
for y in V[0].keys():
print "%.5s: " % y,
for t in range(len(V)):
print "%.7s" % ("%f" % V[t][y]),
print
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
print_dptable(V)
(prob, state) = max([(V[len(obs) - 1][y], y) for y in states])
return (prob, path[state])
c3RhdGVzID0gKCdIZWFsdGh5JywgJ0ZldmVyJykKIApvYnNlcnZhdGlvbnMgPSAoJ25vcm1hbCcsICdjb2xkJywgJ2Rpenp5JykKIApzdGFydF9wcm9iYWJpbGl0eSA9IHsnSGVhbHRoeSc6IDAuNiwgJ0ZldmVyJzogMC40fQogCnRyYW5zaXRpb25fcHJvYmFiaWxpdHkgPSB7CiAgICdIZWFsdGh5JyA6IHsnSGVhbHRoeSc6IDAuNywgJ0ZldmVyJzogMC4zfSwKICAgJ0ZldmVyJyA6IHsnSGVhbHRoeSc6IDAuNCwgJ0ZldmVyJzogMC42fSwKICAgfQogCmVtaXNzaW9uX3Byb2JhYmlsaXR5ID0gewogICAnSGVhbHRoeScgOiB7J25vcm1hbCc6IDAuNSwgJ2NvbGQnOiAwLjQsICdkaXp6eSc6IDAuMX0sCiAgICdGZXZlcicgOiB7J25vcm1hbCc6IDAuMSwgJ2NvbGQnOiAwLjMsICdkaXp6eSc6IDAuNn0sCiAgIH0KIyBIZWxwcyB2aXN1YWxpemUgdGhlIHN0ZXBzIG9mIFZpdGVyYmkuCmRlZiBwcmludF9kcHRhYmxlKFYpOgogICAgcHJpbnQgIiAgICAiLAogICAgZm9yIGkgaW4gcmFuZ2UobGVuKFYpKTogcHJpbnQgIiU3cyIgJSAoIiVkIiAlIGkpLAogICAgcHJpbnQKIAogICAgZm9yIHkgaW4gVlswXS5rZXlzKCk6CiAgICAgICAgcHJpbnQgIiUuNXM6ICIgJSB5LAogICAgICAgIGZvciB0IGluIHJhbmdlKGxlbihWKSk6CiAgICAgICAgICAgIHByaW50ICIlLjdzIiAlICgiJWYiICUgVlt0XVt5XSksCiAgICAgICAgcHJpbnQKIApkZWYgdml0ZXJiaShvYnMsIHN0YXRlcywgc3RhcnRfcCwgdHJhbnNfcCwgZW1pdF9wKToKICAgIFYgPSBbe31dCiAgICBwYXRoID0ge30KIAogICAgIyBJbml0aWFsaXplIGJhc2UgY2FzZXMgKHQgPT0gMCkKICAgIGZvciB5IGluIHN0YXRlczoKICAgICAgICBWWzBdW3ldID0gc3RhcnRfcFt5XSAqIGVtaXRfcFt5XVtvYnNbMF1dCiAgICAgICAgcGF0aFt5XSA9IFt5XQogCiAgICAjIFJ1biBWaXRlcmJpIGZvciB0ID4gMAogICAgZm9yIHQgaW4gcmFuZ2UoMSxsZW4ob2JzKSk6CiAgICAgICAgVi5hcHBlbmQoe30pCiAgICAgICAgbmV3cGF0aCA9IHt9CiAKICAgICAgICBmb3IgeSBpbiBzdGF0ZXM6CiAgICAgICAgICAgIChwcm9iLCBzdGF0ZSkgPSBtYXgoWyhWW3QtMV1beTBdICogdHJhbnNfcFt5MF1beV0gKiBlbWl0X3BbeV1bb2JzW3RdXSwgeTApIGZvciB5MCBpbiBzdGF0ZXNdKQogICAgICAgICAgICBWW3RdW3ldID0gcHJvYgogICAgICAgICAgICBuZXdwYXRoW3ldID0gcGF0aFtzdGF0ZV0gKyBbeV0KIAogICAgICAgICMgRG9uJ3QgbmVlZCB0byByZW1lbWJlciB0aGUgb2xkIHBhdGhzCiAgICAgICAgcGF0aCA9IG5ld3BhdGgKIAogICAgcHJpbnRfZHB0YWJsZShWKQogICAgKHByb2IsIHN0YXRlKSA9IG1heChbKFZbbGVuKG9icykgLSAxXVt5XSwgeSkgZm9yIHkgaW4gc3RhdGVzXSkKICAgIHJldHVybiAocHJvYiwgcGF0aFtzdGF0ZV0p