维特比算法

看一下维基百科的解释,维特比算法(Viterbi algorithm)是一种动态规划算法。它用于寻找最有可能产生观测事件序列的维特比路径——隐含状态序列,特别是在马尔可夫信息源上下文和隐马尔可夫模型中。
通俗易懂的解释知乎有很多,如:如何通俗地讲解 viterbi 算法?,我我这里重点是如何用python代码实现这个算法。

算法原理

维特比算法就是求所有观测序列中的最优,如下图所示,我们要求从S到E的最优序列,中间有3个时刻,每个时刻都有对应的不同观察的概率,下图中每个时刻不同的观测标签有3个。

求所有路径中最优路径,最容易想到的就是暴力解法,直接把所有路径全部计算出来,然后找出最优的。这方法理论上是可行,但当序列很长时,时间复杂夫很高。而且进行了大量的重复计算,viterbi算法就是用动态规划的方法就减少这些重复计算。
viterbi算法是每次记录到当前时刻,每个观察标签的最优序列,如下图,假设在t时刻已经保存了从0到t时刻的最优路径,那么t+1时刻只需要计算从t到t+1的最优就可以了,图中红箭头表示从t时刻到t+1时刻,观测标签为1,2,3的最优。

每次只需要保存到当前位置最优路径,之后循环向后走。到结束时,从最后一个时刻的最优值回溯到开始位置,回溯完成后,这个从开始到结束的路径就是最优的。

代码实现

下面用python简单实现一下viterbi算法

import numpy as npdef viterbi_decode(nodes, trans):"""Viterbi算法求最优路径其中 nodes.shape=[seq_len, num_labels],trans.shape=[num_labels, num_labels]."""# 获得输入状态序列的长度,以及观察标签的个数seq_len, num_labels = len(nodes), len(trans)# 简单起见,先不考虑发射概率,直接用起始0时刻的分数scores = nodes[0].reshape((-1, 1))paths = []# 递推求解上一时刻t-1到当前时刻t的最优for t in range(1, seq_len):# scores 表示起始0到t-1时刻的每个标签的最优分数scores_repeat = np.repeat(scores, num_labels, axis=1)# observe当前时刻t的每个标签的观测分数observe = nodes[t].reshape((1, -1))observe_repeat = np.repeat(observe, num_labels, axis=0)# 从t-1时刻到t时刻最优分数的计算,这里需要考虑转移分数transM = scores_repeat + trans + observe_repeat# 寻找到t时刻的最优路径scores = np.max(M, axis=0).reshape((-1, 1))idxs = np.argmax(M, axis=0)# 路径保存paths.append(idxs.tolist())best_path = [0] * seq_lenbest_path[-1] = np.argmax(scores)# 最优路径回溯for i in range(seq_len-2, -1, -1):idx = best_path[i+1]best_path[i] = paths[i][idx]return best_path

代码中整队scores和observe的repeat复制操作,是为了方便矩阵运算,减少循环的操作。
如果将M = scores_repeat + trans + observe_repeat,展开用for循环写,在t时刻M[i][j] = scores[i] + trans[i][j] + observe[j],M[i][j]表示从t-1时刻为i-1状态,t时刻为j-1状态的分数。

下面就是展开用for训练一步一步求解的伪码。

# 每个时刻scores更新的伪码
for t in range(1, seq_len):tmp_scores = scoresfor 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 <= i < nums_labels)scores = tmp_scores

可以利用矩阵计算的原理,合并一些步骤。

for t in range(1, seq_len):scores_repeat = np.repeat(scores, num_labels, axis=1)observe = nodes[t].reshape((1, -1))observe_repeat = np.repeat(observe, num_labels, axis=0)M = scores_repeat + trans + observe_repeatscores = np.max(M, axis=0).reshape((-1, 1))

这里还有对scores和observe进行复制的操作,numpy运算中还可以在简化。

for t in range(1, seq_len):observe = nodes[t].reshape((1, -1))M = scores + trans + observescores = np.max(M, axis=0).reshape((-1, 1))

numpy在相加时可以自动扩充维度,横向和纵向都可以。

经过简化的viterbi算法完整版。

def viterbi_decode_v2(nodes, trans):"""Viterbi算法求最优路径v2其中 nodes.shape=[seq_len, num_labels],trans.shape=[num_labels, num_labels]."""seq_len, num_labels = len(nodes), len(trans)scores = nodes[0].reshape((-1, 1))paths = []# # 递推求解上一时刻t-1到当前时刻t的最优for t in range(1, seq_len):observe = nodes[t].reshape((1, -1))M = scores + trans + observescores = np.max(M, axis=0).reshape((-1, 1))idxs = np.argmax(M, axis=0)paths.append(idxs.tolist())best_path = [0] * seq_lenbest_path[-1] = np.argmax(scores)# 最优路径回溯for i in range(seq_len-2, -1, -1):idx = best_path[i+1]best_path[i] = paths[i][idx]return best_path

还有一种写法,最后不用回溯,每次把最优路径的索引都保存起来,并添加一个正常的路径,最后直接按索引找出最优路径,这个代码很少,但是不太好理解。

def viterbi_decode_v3(nodes, trans):"""Viterbi算法求最优路径其中 nodes.shape=[seq_len, num_labels],trans.shape=[num_labels, num_labels]."""seq_len, num_labels = len(nodes), len(trans)labels = np.arange(num_labels).reshape((1, -1))scores = nodes[0].reshape((-1, 1))paths = labelsfor t in range(1, seq_len):observe = nodes[t].reshape((1, -1))M = scores + trans + observescores = np.max(M, axis=0).reshape((-1, 1))idxs = np.argmax(M, axis=0)paths = np.concatenate([paths[:, idxs], labels], 0)best_path = paths[:, scores.argmax()]return best_path

维特比算法(viterbi)原理以及简单实现相关推荐

  1. HMM——维特比算法(Viterbi algorithm)

    1. 前言 维特比算法针对HMM第三个问题,即解码或者预测问题,寻找最可能的隐藏状态序列: 对于一个特殊的隐马尔可夫模型(HMM)及一个相应的观察序列,找到生成此序列最可能的隐藏状态序列. 也就是说给 ...

  2. Viterbi 原理及简单实现

    Viterbi 原理及简单实现 维特比算法: 维特比算法由安德鲁·维特比(Andrew Viterbi) 于1967年提出,用于在数字通信链路中解卷积以消除噪音. 此算法被广泛应用于 CDMA 和 G ...

  3. 语音识别学习日志 2019-7-17 语音识别基础知识准备6 {维特比算法(Viterbi Algorithm)}

    HMM 维特比算法(Viterbi Algorithm)详细解释参考:http://www.52nlp.cn/hmm-learn-best-practices-six-viterbi-algorith ...

  4. 维特比算法(Viterbi)

    维特比算法 (Viterbi algorithm) 是机器学习中应用非常广泛的动态规划算法,在求解隐马尔科夫.条件随机场的预测以及seq2seq模型概率计算等问题中均用到了该算法.实际上,维特比算法不 ...

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

    维特比算法的python简单实现 简单介绍 实现了李航书籍p210的例子,例子非常经典.我有三个盒子,每个盒子都有红球和白球,我观测到了三次结果:红.白和红,现在需要求出盒子的可能序列是什么. 通过这 ...

  6. C语言维特比算法,viterbi维特比算法

    维特比算法:使用动态规划,找出最短路径 以下以图的形式来解释: 图的节点按列组织,每列的节点数量可以不一样,每一列的节点只能和相邻列的节点相连,不能跨列相连,节点之间有着不同的距离,距离的值就不在图上 ...

  7. 维特比算法Viterbi Algorithm

     1.简介 维特比算法是一个特殊但应用最广的动态规划算法,它是针对篱笆网络的有向图(Lattice)的最短路径问题而提出的.凡是使用隐含马尔可夫模型描述的问题都可以用维特比算法来解码,包括今天的数 ...

  8. 分类算法学习(二)——贝叶斯算法的原理及简单实现

    1.3.贝叶斯分类的基础--贝叶斯定理 每次提到贝叶斯定理,我心中的崇敬之情都油然而生,倒不是因为这个定理多高深,而是因为它特别有用.这个定理解决了现实生活里经常遇到的问题:已知某条件概率,如何得到两 ...

  9. CRF(条件随机场)与Viterbi(维特比)算法原理详解

    摘自:https://mp.weixin.qq.com/s/GXbFxlExDtjtQe-OPwfokA https://www.cnblogs.com/zhibei/p/9391014.html C ...

最新文章

  1. 决策树算法python源代码_决的解释|决的意思|汉典“决”字的基本解释
  2. 英伟达公开课 | 如何突破Decoder性能瓶颈?揭秘FasterTransformer2.0的原理与应用,已开源...
  3. pandas的基本使用
  4. Linux之CentOS安装composer与git
  5. burp爆破线程设置多少_你知道线程池创建多少线程比较合理吗?
  6. 职业规划:少走弯路的十条忠告
  7. 函数传参数_算法笔记(7)第二章C、C++快速入门函数,main函数,
  8. python中的sklearn.svm.svr_python机器学习库scikit-learn:SVR的基本应用
  9. java连接虚拟机hadoop_本地eclipse java api连接远程虚拟机HBase
  10. c语言综合性程序设计,《C语言程序设计》综合性实验报告撰写格式
  11. 【相机标定系列】单目相机,内参,外参
  12. python opencv 找到圆点标定板所有点后通过距离找四个角点2
  13. github上写简历
  14. 语音识别中输入输出的可能形式有哪些
  15. docset文件,aviary sdk,一个bug
  16. Netty in Action 翻译说明
  17. 9款别出心裁的jQuery插件
  18. 常见前端九十道面试题及答案-韩烨
  19. [FPGA] 1、Artix-7 35T Arty FPGA 评估套件学习
  20. //编写一个学生类(Students),包括姓名(name)、性别(sex)、学号(num)、语文课(Chinese)、英语课(English)、 //数学课(Math)和平均值(avg)

热门文章

  1. 基因和疾病:缺陷、脱轨以及妥协
  2. 2021年焊工(初级)考试试卷及焊工(初级)复审考试
  3. 全球与中国无线门铃对讲设备市场深度研究分析报告
  4. Mac系统运行“exe”文件最简单的解决办法
  5. Spring Cloud 工具集
  6. 人工智能和机器学习方面重要会议
  7. CF 1696 E. Placing Jinas 组合数 2000
  8. AD实用操作(三)- 原理图器件配置参数批量修改
  9. RDF 1.1 N-Triples
  10. 【C语言程序设计】C语言求最小公倍数(详解版)!