Viterbi动态规划算法
参考文章https://www.zhihu.com/question/20136144
我们以上图为例讲解从阶段1到阶段3的最短路径。首先如果按照贪婪算法,我们一共需要计算
3
×
3
×
3
=
27
3\times3\times3=27
3×3×3=27次,而使用Viterbi动态规划算法,我们只需要计算
3
×
3
×
2
=
18
3\times3\times2=18
3×3×2=18次
Viterbi的最主要核心点为计算并仅保留到达当前节点的最短路径,只要理解这个理论,维特比动态规划算法就一点都不难了。以
A
2
A_2
A2为例,当我们处在
A
2
A_2
A2时,可以到达
A
2
A_2
A2的路径一共有3条:
[
A
1
−
A
2
,
B
1
−
A
2
,
C
1
−
A
2
]
[A_1-A_2,B_1-A_2,C_1-A_2]
[A1−A2,B1−A2,C1−A2],当我们第三层中的路径经过
A
2
A_2
A2时,最短的路径一定是到达
A
2
A_2
A2的最短路径,因此可以不用计算到达
A
2
A_2
A2的其他路径,因此大大的减少了计算量。
根据上述理论,我们可以用python写一个demo:
import numpy as np
def viterbi(nodes):
# loglikelihood
paths = {'A': np.log(nodes[0]['A']), 'B':np.log(nodes[0]['B']), 'C':np.log(nodes[0]['C'])}
for l in range(1, len(nodes)):
# 拷贝当前路径
paths_ = paths.copy()
paths = {}
for i in nodes[l].keys():
nows = {}
# 计算到达节点i的所有路径
for j in paths_.keys():
nows[j+i] = paths_[j]+np.log(nodes[l][i])
# 对节点i选择最优路径
k = np.argmax(list(nows.values()))
# 保存到达节点i的最优路径
paths[list(nows.keys())[k]] = list(nows.values())[k]
return list(paths.keys())[np.argmax(list(paths.values()))], np.max(list(paths.values()))
nodes = [{'A':0.1, 'B':0.3, 'C':0.6}, {'A':0.2, 'B':0.4, 'C':0.4}, {'A':0.6, 'B':0.2, 'C':0.2}]
print(viterbi(nodes))
最终的输出结果为CBA