Viterbi的算法在这边就不解释了。 主要可以参考:
(1) Wiki
详细介绍了算法的原理与python实现。
不过个人感觉看这个python的实现没太看懂。 于是乎自己在下面又写了一遍而且感觉相对来说要更清楚一些
(2) 知乎:谁能通俗的讲解下viterbi算法吗?
其中最高票的答案非常详细的一步步的描写了运算的过程
最好各位再在草稿纸上面写写画画以求彻底明白
最后贴一下我自己写出来的python实现:
# -*- coding: utf-8 -*-
# ---- init some data ----
# 隐藏变量, states
states = ['h', 'f']
# 状态转移矩阵
Tr_p = {}
Tr_p['h'] = { 'h': 0.7, 'f': 0.3}
Tr_p['f'] = { 'h': 0.4, 'f': 0.6}
# 初始概率, star=*, 有的是用π来表示
star = {}
star['h'] = 0.6
star['f'] = 0.4
# 放射矩阵, n=normal, c=cold, d=dizzy
emission_p = {}
emission_p['h'] = { 'n' : 0.5, 'c' : 0.4, 'd':0.1 }
emission_p['f'] = { 'n' : 0.1, 'c' : 0.3, 'd':0.6 }
# 实际的观察值
obser_vals = ['n', 'c', 'd']
def get_max_from_dict(delta) :
max_val = 0
max_key = ""
for key in delta.keys() :
if delta[key] > max_val :
max_key = key
max_val = delta[key]
return max_key, max_val
def viterbi() :
# delta 用于保存当前状态下
delta_i = {}
path_i = []
prob_i = []
# 首先计算第一天的状态
# delta_i['h'] = star['h'] * emission_p['h']['n']
# delta_i['f'] = star['f'] * emission_p['f']['n']
for state in states :
delta_i[state] = star[state] * emission_p[state][obser_vals[0]]
key, val = get_max_from_dict(delta_i)
path_i.append(key)
prob_i.append(val)
# 从第二天开始计算,直到最后一天
for i in range(1, len(obser_vals)) :
lastState = path_i[-1]
obser_val = obser_vals[i]
# 防止出错,清空delta_i
delta_i = {}
for state in states :
# Δ2(h) = Δ1(h) * Tr(h->h) * e(h | c)
delta_i[state] = prob_i[-1] * Tr_p[lastState][state] * emission_p[state][obser_val]
print "delta_i[state]=", delta_i[state]
# 获取当前概率最大的路径
key, val = get_max_from_dict(delta_i)
path_i.append(key)
prob_i.append(val)
print path_i
viterbi()