共计 1683 个字符,预计需要花费 5 分钟才能阅读完成。
viterbi 过程
1.hmm 类似。状态转移,发射概率
2. 逐次计算每个序列节点的所有状态下的概率值,最大概率值对应的 index。
3. 概率值的计算,上一个节点的概率值 * 转移概率 + 当前概率值。
4. 最后取出最大的一个值对应的 indexes
难点:理解 viterbi 的核心点,在于每个时间步都保留每一个可视状态,每一个可视状态保留上一个时间步的最大隐状态转移,
每一个时间步 t 记录上一个最大概率转移过来的时间步 t - 1 的信息,包括 index/ 概率值累积。
迭代完时间步,根据最后一个最大累积概率值,逐个往前找即可。根据 index 对应的状态逐个往前找。
应用:状态转移求解最佳转移路径。只要连续时间步,每个时间步有状态分布,前后时间步之间有状态转移,就可以使用 viterbi 进行最佳状态转移计算求解。
状态转移矩阵的作用在于 在每个状态转移概率计算时,和固有的状态转移矩阵进行加和,再计算。相当于额外的概率添加。
import numpy as np
def viterbi_decode(score, transition_params):
“””
保留所有可视状态下,对 seqlen 中的每一步的所有可视状态情况下的中间状态求解概率最大值,如此
:param score:
:param transition_params:
:return:
“””
# score [seqlen,taglen] transition_params [taglen,taglen]
trellis=np.zeros_like(score)
trellis[0]=score[0]
backpointers=np.zeros_like(score,dtype=np.int32)
for t in range(1,len(score)):
matrix_node=np.expand_dims(trellis[t-1],axis=1)+transition_params #axis=0 代表发射概率初始状态
trellis[t]=score[t]+np.max(matrix_node,axis=0)
backpointers[t]=np.argmax(matrix_node,axis=0)
viterbi=[np.argmax(trellis[-1],axis=0)]
for backpointer in reversed(backpointers[1:]):
viterbi.append(backpointer[viterbi[-1]])
viterbi_score = np.max(trellis[-1])
viterbi.reverse()
print(trellis)
return viterbi,viterbi_score
def calculate():
score = np.array([[1, 2, 3],
[2, 1, 3],
[1, 3, 2],
[3, 2,1]]) # (batch_size, time_step, num_tabs)
transition = np.array([[2, 1, 3], [1, 3, 2], [3, 2, 1] ] )# (num_tabs, num_tabs)
lengths = [len(score[0])] # (batch_size, time_step) # numpy print(“[numpy]”)
# np_op = viterbi_decode(score=np.array(score[0]), transition_params=np.array(transition))
# print(np_op[0])
# print(np_op[1])
print(“=============”) # tensorflow
# score_t = tf.constant(score, dtype=tf.int64)
# transition_t = transition, dtype=tf.int64
tf_op = viterbi_decode(score, transition)
print(‘——————–‘)
print(tf_op)
if __name__==’__main__’:
calculate()