维特比算法的python的简单实现

维特比算法的python简单实现

简单介绍

实现了李航书籍p210的例子,例子非常经典。我有三个盒子,每个盒子都有红球和白球,我观测到了三次结果:红、白和红,现在需要求出盒子的可能序列是什么。

通过这个例子更加深刻理解“求解HMM的隐变量(这里是盒子的序列)”,也就是HMM的预测问题。

两个矩阵pathtracingMatrix(追溯矩阵)和statedSavedMatrix(状态存储矩阵)
pathtracingMatrix[i][j]存储的是第i时刻,第j状态的前t-1最有可能的状态
statedSavedMatrix[i][j] 存储的是第i时刻,第j状态,最大值是多少,保存的目的方便下一时刻计算。

维特比算法最大优势在于利用动态规划算法,将复杂度从N^T降低到了T*N^2,将计算量降低了很多。

我写的算法比较小白,如果你有更好建议,欢迎留言讨论,谢谢反馈。

python代码

import numpy as np

#给定参数、观测序列的情况下,求出
#parameters

pai = np.array([0.2,0.4,0.4]) #initial probability
A = np.array([[0.5,0.2,0.3],[0.3,0.5,0.2],[0.2,0.3,0.5]]) #transmission probability
B = np.array([[0.5,0.5],[0.4,0.6],[0.7,0.3]]) # observer probability

print("pai:",pai.shape)
print("A:",A.shape)
print("B:",B.shape)

#状态值
statesN = 3
stateDict = dict()
stateDict[0] = "box_1"
stateDict[1] = "box_2"
stateDict[2] = "box_3"

#观测值
observedN = 2
observedDict = dict()
observedDict[0] = 'red ball'
observedDict[1] = 'white ball'
observedSequence = np.array([0,1,0])

#时间长度(HMM的长度)
T = 3

#check
assert(pai.shape == (statesN,))
assert(A.shape == (statesN,statesN))
assert(B.shape == (statesN,observedN))


#viterbi

#追溯矩阵
pathtracingMatrix = np.zeros((T,statesN))-1
#状态存储矩阵
statedSavedMatrix = np.zeros((T,statesN))

for t in range(T):

	if t == 0:
		for i in range(statesN):
			statedSavedMatrix[t][i] = pai[i]*B[i][observedSequence[t]]
		continue

	for i in range(statesN):
		#time :t
		t_state_index = i
		currentMaxWeight = 0
		currentMaxLastStateI = 0

		for j in range(statesN):
			#time :t-1
			weight = statedSavedMatrix[t-1][j]*A[j][i]
			if weight > currentMaxWeight:
				currentMaxWeight = weight
				currentMaxLastStateI = j

		pathtracingMatrix[t][i] = currentMaxLastStateI
		statedSavedMatrix[t][i] = currentMaxWeight*B[i][observedSequence[t]]

 			
print("pathtracingMatrix:",pathtracingMatrix)
print("statedSavedMatrix:",statedSavedMatrix)


#tracing 进行回溯
lastMaxWeightStateIndex = np.argmax(pathtracingMatrix[T-1])

results = np.array([lastMaxWeightStateIndex])


for i in range(T-1,0,-1):
	lastIndex = pathtracingMatrix[i][int(lastMaxWeightStateIndex)]
	results = np.append(results,lastIndex)
	lastMaxWeightStateIndex = lastIndex

#注意输出结果应该反转输出
print("vitebi输出状态index为:",results[::-1])

#可读性输出

print("即:在观测值为:",[observedDict[i] for i in observedSequence])

print("最有可能盒子序列(隐状态)为:",[stateDict[i] for i in results[::-1]])
print("算法的复杂度为:T*N^2(N为隐状态的数量)")

运行结果

运行结果为;
vitebi输出状态index为: [2. 2. 2.]
即:在观测值为: [‘red ball’, ‘white ball’, ‘red ball’]
最有可能盒子序列(隐状态)为: [‘box_3’, ‘box_3’, ‘box_3’]
算法的复杂度为:T*N^2(N为隐状态的数量)

与书上的结果一致

你可能感兴趣的:(算法实现,AI,python,机器学习,算法,维特比算法)