Viterbi算法实现代码

本代码来自github地址。添加注释仅供理解。
Viterbi算法参考自《统计学习方法》

Viterbi算法:

Viterbi算法实现代码_第1张图片
Viterbi算法实现代码_第2张图片

算法实现:
# HMM的五个元素
# -------------------------------------
# 隐状态集合 states
# 记录所有可能的隐状态 ('Healthy', 'Fever')
# -------------------------------------
# 观测集合 observations
# 记录所有可能的观测 ('normal', 'cold', 'dizzy') [当前的观测序列obs另给出]
# -------------------------------------
# 初始概率分布 start_probability
# 记录所有隐状态发生的初始概率
# healthy  0.6
# fever    0.4
# -------------------------------------
# 状态转移概率分布 transition_probability
#           healthy    fever
# healthy     0.7       0.3
# fever       0.4       0.6
# -------------------------------------
# 观测概率分布 emission_probability
#           normal   cold   dizzy
# healthy     0.5     0.4    0.1
# fever       0.1     0.3    0.6

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},
   }


# 观测,状态,初始概率分布,状态转移概率分布,观测概率分布
def Viterbit(obs, states, s_pro, t_pro, e_pro):
	path = { s:[] for s in states} # init path: path[s] represents the path ends with s
	print("initial path is : %s" % (path))

	# 初始化:初始时刻,隐状态概率*由该状态产生指定观测(初始时刻的观测)的概率
	curr_pro = {}
	for s in states:
		curr_pro[s] = s_pro[s]*e_pro[s][obs[0]]
	print ("curr_pro is : %s " % (curr_pro))

	# 遍历每一个时刻i,循环内代表在时刻i的计算工作
	for i in range(1, len(obs)):
		last_pro = curr_pro
		curr_pro = {}
		# 遍历全部隐状态
		for curr_state in states:
			print("\nin time %s , curr_state is %s" % (i,curr_state))

			# 计算在时刻i状态为curr_state的所有单个路径中概率最大值max_pro
			# 计算在时刻i状态为curr_state的所有单个路径中概率最大路径的第i-1个节点last_sta
			max_pro, last_sta = max(((last_pro[last_state]*t_pro[last_state][curr_state]*e_pro[curr_state][obs[i]], last_state) 
				                       for last_state in states)) # 遍历全部状态(i-1时刻的)
			print("max_pro is : %s \nlast_sta is :%s" % (max_pro,last_sta))

			# 将计算得到的最大概率记录到当前状态上
			curr_pro[curr_state] = max_pro
			print("curr_pro is : %s" % (curr_pro))
			# 将最大概率路径对应的前一个(i-1个)状态记录到当前状态 组成路径
			path[curr_state].append(last_sta)
			print("new path is : %s" % (path))

	print("\t")
	# 寻找最大概率路径
	max_pro = -1
	max_path = None # 最大概率路径
	# 遍历隐状态列表中所有状态
	for s in states:
		path[s].append(s) # 将当前(最后一个时刻)的状态添加到其值中。形成[state0,state1,state2,……,stateN]
		print("path %s with the probability %s" % (path[s], curr_pro[s]))
		# 比较判断出最大概率的路径
		if curr_pro[s] > max_pro: # 这里的curr_pro由上一个循环最后一圈给出,记录了最后时刻每个状态的概率
			max_path = path[s]
			max_pro = curr_pro[s]
	return max_path

if __name__ == '__main__':
	obs = ['normal', 'cold', 'dizzy']
	print ("\n%s" % (Viterbit(obs, states, start_probability, transition_probability, emission_probability)))
运行结果:

Viterbi算法实现代码_第3张图片

你可能感兴趣的:(Viterbi算法实现代码)