viterbi算法 python,viterbi维特比算法

  viterbi算法 python,viterbi维特比算法

  深情猎豹算法看维基百科的解释。深情猎豹算法是一种动态规划算法。用于寻找猎豹路径——最有可能产生观测事件序列的深情隐态序列,特别是在马尔可夫信息源和隐马尔可夫模型的背景下。

  知乎有很多通俗易懂的解释,比如:如何通俗地解释维特比算法?我在这里的重点是如何用python代码实现这个算法。

  原理深情猎豹算法是在所有观测序列中寻找最优的,如下图所示。我们要求从S到E的最佳序列,中间有三个矩,每个矩都有不同观测值对应的概率。下图中的每个时刻都有三个不同的观察标签。

  要在所有路径中寻找最佳路径,最容易想到的方法就是暴力解法,直接计算所有路径,然后找出最佳路径。这种方法理论上是可行的,但是当序列较长时,时间就比较复杂,时间要求很高。而且进行了大量的重复计算,维特比算法就是通过动态规划来减少这些重复计算。

  维特比算法是每次记录当前时间时每个观察标签的最优顺序,如下图所示。假设T时刻从0到T的最优路径已经保存,那么只需要计算T时刻从T到t 1的最优。图中红色箭头表示从T时刻到t 1时刻,观测标签为1、2、3的最优。

  每次只需要保存到当前位置的最佳路径,然后循环后退。最后,将最后时刻的最优值追溯到起始位置。描摹完成后,从开始到结束的路径是最好的。

  下面的代码是viterbi算法在python中的简单实现。

  import numpy as NP def viterbi _ decode(nodes,trans): viterbi算法查找最佳路径,其中nodes.shape=[seq _ len,num _ labels],trans.shape=[num _ labels,Num _ Labels]。 #得到输入状态序列的长度,和观测标签的个数SEQ _ LEN,Num _ Labels=LEN(节点),LEN (trans) #为简单起见,不考虑发射概率,只用score=nodes [0]即可。reshape ((-1,1)) paths=[] #从前一时刻t-1到当前时刻t在范围(1,seq _ len)内递归求解t的最优:# scores表示每个标签从起始时刻0到时刻t-1的最优得分,scores _ repeat=np.repeat (scores,num _ labels,Axis=1)# observe=nodes[t]。reshape ((1,-1))observe _ repeat=NP . repeat(observe,num _ labels,axis=0) #从时间t-1到时间t的最优得分的计算,这里,我们需要考虑过渡得分trans m=scores _ repeat trans observe _ repeat #来寻找到时间t scores=np.max (m,axis=0)的最佳路径。reshape ((-1,1)) idxs=np.argmax (m,Axis=0)# path saving paths . append(idxs . to list())best _ path=[0]* seq _ len best _ path[-1]=NP . arg max(scores)#对范围内的I进行最优路径回溯(seq_len-2,-1,-1):idx=best _ path[I 1]best _ path[I]=paths[I][idx]返回整行分数的重复复制操作并在代码中观察

  如果m=scores _ repeat transobserve _ repeat,将其展开,写在for循环中。在时间T,M[i][j]=scores[I]trans[I][j]observe[j],M[I][j]表示从时间t-1开始的i-1状态,时间T为j。

  以下是针对训练逐步解决的伪代码。

  # range中t的伪代码(1,seq _ len):tmp _ scores=scores for j in range(nums _ labels):for I in range(nums _ labels):M[I][j]=scores[I]trans[I][j]observe[t][j]tmp _ scores[j]=max(M[I][j])(0=inums _ labels)scores=tmp _ scores可以利用矩阵计算的原理将一些步骤组合起来,

  对于范围(1,seq_len)中的t:分数_重复=NP。repeat(scores,num_labels,axis=1) observe=nodes[t].shape((1,-1))observe _ repeat=NP。repeat(observe,num_labels,axis=0)M=scores _ repeat trans observe _ repeat scores=NP。最大值(M,轴=0).整形((-1,1))这里还有对得分和观察进行复制的操作,numpy运算中还可以在简化。

  对于范围(1,seq_len)中的观察=节点[t].整形((1,-1))M=分数trans观察分数=NP。最大值(M,轴=0).整形(((-1,1)) numpy在相加时可以自动扩充维度,横向和纵向都可以。

  经过简化的维特比(译码器)算法完整版。

  def viterbi_decode_v2(nodes,trans): Viterbi算法求最优路径v2其中nodes . shape=[序列长度,数量标签],trans . shape=[数量标签,数量标签]. seq_len,num_labels=len(nodes),len(trans) scores=nodes[0].重塑((-1,1))路径=[] # #递推求解上一时刻t-1到当前时刻t的最优对于范围(1,seq_len)中的观察=节点[t].整形((1,-1))M=分数trans观察分数=NP。最大值(M,轴=0).整形((-1,1)) idxs=np.argmax(M,axis=0)路径。追加(idxs。to list())best _ path=[0]* seq _ len best _ path[-1]=NP。arg max(分数)#最优路径回溯对于范围内的I(序列长度-2,-1,-1): idx=最佳路径[i 1]最佳路径[我]=路径[i][idx]返回最佳路径还有一种写法,最后不用回溯,每次把最优路径的索引都保存起来,并添加一个正常的路径,最后直接按索引找出最优路径,这个代码很少,但是不太好理解。

  def viterbi_decode_v3(nodes,trans): Viterbi算法求最优路径其中nodes . shape=[序列长度,数量标签],trans . shape=[数量标签,数量标签]." seq_len,num_labels=len(节点),len(trans)labels=NP。arange(num _ labels).整形((1,-1))分数=节点数[0]。整形((-1,1))路径=范围(1,序列长度)中t的标签:观察=节点[t]的缩写.整形((1,-1))M=分数trans观察分数=NP。最大值(M,轴=0).reshape((-1,1)) idxs=np.argmax(M,axis=0)paths=NP。concatenate([路径[:idxs],标签],0) best_path=路径[:分数。arg max()]返回最佳路径

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: