维特比算法的目的:

寻找最可能的隐藏状态序列(Finding most probable sequence of hidden states)


关于原理的讲解可以参考下面两篇文章,讲的比较清楚
小白给小白详解维特比算法1.
小白给小白详解维特比算法2.


本文通过分析维特比算法的例子,来学习该算法

  1. 定义HMM的五个重要元素,
# 隐藏序列 S
states = ("Rainy", "Sunny")# 观测序列 K
observations = ('walk', 'shop', 'clean')# 初始概率 π
start_probability = {'Rainy': 0.6, "Sunny": 0.4}# 转移概率 A
transition_probability = {'Rainy': {"Rainy": 0.7, "Sunny": 0.3},"Sunny": {"Rainy": 0.4, "Sunny": 0.6}
}# 发射概率  B
emission_probability = {"Rainy": {"walk": 0.1, "shop": 0.4, "clean": 0.5},"Sunny": {"walk": 0.6, "shop": 0.3, "clean": 0.1},
}

2.定义初始化状态

    # 路径概率表 V[时间][隐状态] = 概率V = [{}]# 一个中间变量,代表当前状态是哪个隐状态path = {}# 初始化初始状态 t=0for y in states:V[0][y] = start_p[y] * emit_p[y][obs[0]]path[y] = [y]

V[时间][天气] = 概率
观测序列(observations)得到的结果 观测对象第一天是散步
计算第一天的天气:
V[第一天][天晴] = 初始概率[天晴] * 发射概率[散步] = 0.4 * 0.6 = 0.24
V[第一天][下雨] = 初始概率[下雨] * 发射概率[散步] = 0.6 * 0.1 = 0.06
计算结果可见,第一天天晴的概率比较大。
此时初始的路径 path = {}


  1. 后面天气的情况都是根据前一天天气概率×转移概率×发射概率得到
def vierbi(obs, states, start_p, trans_p, emit_p):""":param obs:     观察序列    K:param states:  隐藏状态    S:param start_p: 初始概率    π:param trans_p: 转移概率    A:param emit_p:  发射概率    B:return:"""# 路径概率表 V[时间][隐状态] = 概率V = [{}]# 一个中间变量,代表当前状态是哪个隐状态path = {}# 初始化初始状态 t=0for y in states:V[0][y] = start_p[y] * emit_p[y][obs[0]]path[y] = [y]# 对t>0 跑一遍维特比算法for t in range(1, len(obs)):V.append({})newpath = {}for y in states:# 概率 隐状态 =  前状态是y0的概率 * y0转移到y的概率 * y表现为当前状态的概率(prob, state) = max([(V[t - 1][y0] * trans_p[y0][y] * emit_p[y][obs[t]], y0) for y0 in states])# 记录最大概率V[t][y] = prob# 记录路径newpath[y] = path[state] + [y]# 不需要保存旧路径path = newpathprint_dptable(V)(prob, state) = max([(V[len(obs) - 1][y], y) for y in states])return prob, path[state]

第二天: 由观测序列可得 observations[1] = ‘购物’
① 首先看计算第二天下雨的概率

  • V[第二天][下雨] = V[第一天][下雨] * 转移概率[下雨][下雨] * 发射概率[下雨][购物] = 0.06 * 0.7 * 0.4 = 0.0168
  • V[第二天][下雨] = V[第一天][天晴] * 转移概率[天晴][下雨] * 发射概率[下雨][购物] = 0.24 * 0.4 * 0.4 = 0.0384
    同样在这里取最大概率
    V[第二天][下雨] = 0.0384
    得到的新路径 newpath[下雨] = [晴天,下雨]

②然后计算第二天天晴的概率

  • V[第二天][天晴] = V[第一天][下雨] * 转移概率[下雨][天晴] * 发射概率[天晴][购物] = 0.06 * 0.3 * 0.3 = 0.0054
  • V[第二天][天晴] = V[第一天][天晴] * 转移概率[天晴][天晴] * 发射概率[天晴][购物] = 0.24 * 0.6 * 0.3 = 0.0432
    V[第二天][天晴] = 0.0432
    得到的新路径 newpath[晴天] = [晴天,晴天]

第二天计算完成之后得到前两天的路径
paht={雨天:[晴天,下雨],晴天:[晴天,晴天]}

以同样的方式得到第三天的结果
observations[1] = 打扫

  • V[第三天][下雨] = V[第二天][下雨] * 转移概率[下雨][下雨] * 发射概率[下雨][打扫] = 0.0384 * 0.7 * 0.5 = 0.01344
  • V[第三天][下雨] = V[第二天][天晴] * 转移概率[天晴][下雨] * 发射概率[下雨][打扫] = 0.0432 * 0.4 * 0.5 = 0.00864
    V[第三天][下雨] = 0.01344
    newpath[下雨] = [晴天,下雨,下雨]
  • V[第三天][天晴] = V[第二天][下雨] * 转移概率[下雨][天晴] * 发射概率[天晴][打扫] = 0.0384* 0.3 * 0.1 = 0.001152
  • V[第三天][天晴] = V[第二天][天晴] * 转移概率[天晴][天晴] * 发射概率[天晴][打扫] = 0.0432 * 0.6 * 0.1 = 0.002592
    V[第三天][天晴] = 0.002592
    newpath[晴天] = [晴天,晴天,晴天]
    把得到的newpath赋值给path

最后通过找出V[第三天]中天气最大的那个概率得到天气的情况
因此第三天的天气为V[第三天][下雨] = 0.01344
由此可反推得到路径path[下雨] = [晴天,下雨,下雨]

图形表示如下,第二天之后的天气概率计算后取最大值,根据第三天天气的最大概率再反推天气的路径

上面就是维特比算法实现的详解,下面是完整代码。

# -*- coding:utf-8 -*-
# @Time     :2019/5/27 15:30
# @author   :ding
# @filename :vertibi.py"""
维特比算法的实现
HMM 五个重要元素
S 隐藏序列的集合
K 输出状态或观测状态的集合
π对应隐藏状态的的初始概率
A 隐藏状态的转移概率 是一个N*M的概率矩阵
B 影厂状态到观测状态的混淆矩阵,是一个N*M的发射概率的矩阵
"""# 隐藏序列 S
states = ("Rainy", "Sunny")# 观测序列 K
observations = ('walk', 'shop', 'clean')# 初始概率 π
start_probability = {'Rainy': 0.6, "Sunny": 0.4}# 转移概率 A
transition_probability = {'Rainy': {"Rainy": 0.7, "Sunny": 0.3},"Sunny": {"Rainy": 0.4, "Sunny": 0.6}
}# 发射概率  B
emission_probability = {"Rainy": {"walk": 0.1, "shop": 0.4, "clean": 0.5},"Sunny": {"walk": 0.6, "shop": 0.3, "clean": 0.1},
}def print_dptable(V):print("     ")for i in range(len(V)): print("%7d" % i, end="")print()for y in V[0].keys():print("%.5s: " % y, end=" ")for t in range(len(V)):print("%.7s" % V[t][y], end=" ")print()def vierbi(obs, states, start_p, trans_p, emit_p):""":param obs:     观察序列    K:param states:  隐藏状态    S:param start_p: 初始概率    π:param trans_p: 转移概率    A:param emit_p:  发射概率    B:return:"""# 路径概率表 V[时间][隐状态] = 概率V = [{}]# 一个中间变量,代表当前状态是哪个隐状态path = {}# 初始化初始状态 t=0for y in states:V[0][y] = start_p[y] * emit_p[y][obs[0]]path[y] = [y]# 对t>0 跑一遍维特比算法for t in range(1, len(obs)):V.append({})newpath = {}for y in states:# 概率 隐状态 =  前状态是y0的概率 * y0转移到y的概率 * y表现为当前状态的概率(prob, state) = max([(V[t - 1][y0] * trans_p[y0][y] * emit_p[y][obs[t]], y0) for y0 in states])# 记录最大概率V[t][y] = prob# 记录路径newpath[y] = path[state] + [y]# 不需要保存旧路径path = newpathprint_dptable(V)(prob, state) = max([(V[len(obs) - 1][y], y) for y in states])return prob, path[state]def test():return vierbi(observations,states,start_probability,transition_probability,emission_probability)print(test())

打印结果如下


维特比算法在NLP方面有很多的应用

  • 词性标注:给定一个词的序列,找出最可能的词性序列
  • 分词:给定一个字的序列,找出最可能的标签序列,可利用BMES这些标签来分词B(开头)M(中间词)E(结尾)S(单个词)
  • 明明实体识别:给定一个词的序列,找出最可能的标签序列

本文讲的可能不是很清楚,有不对的地方,还请不吝指教。

viterbi-algorithm 维特比算法的例子解析相关推荐

  1. 隐马尔可夫模型HMM+维特比算法(Viterbi Algorithm)进行词性标注代码实现(自然语言处理课程第二次作业)

    文章目录 一.理论描述 二.算法描述 三.详例描述 具体过程 分析题目 数据预处理 转移概率矩阵: 发射概率矩阵: HMM+维特比算法进行词性标注 开始进行词性标注: The: bear: is: o ...

  2. 条件随机场(CRF) - 4 - 学习方法和预测算法(维特比算法)

    声明: 1,本篇为个人对<2012.李航.统计学习方法.pdf>的学习总结,不得用作商用,欢迎转载,但请注明出处(即:本帖地址). 2,由于本人在学习初始时有很多数学知识都已忘记,所以为了 ...

  3. 机器学习:维特比算法(Viterbi Algorithm)

    一.维特比算法(Viterbi Algorithm)讲解方式01:篱笆网络(Lattice)的最短路径问题 已知下图的篱笆网络,每个节点之间的数字表示相邻节点之间的距离,举个例子来说,如果我走,这个距 ...

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

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

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

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

  6. 维特比算法(Viterbi algorithm) 的理解

    维特比算法实际是动态规划解隐马尔科夫模型预测问题,用动态规划求概率最大路径,这时一条路径就是一个状态序列. 根据动态规划原理,最优路径在时刻t,如果最优路径 通过节点Node_t_k, 那么这一路径从 ...

  7. 维特比算法Viterbi Algorithm

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

  8. 简述维特比算法(Viterbi Algorithm)

    维特比算法是一个特殊但应用最广的动态规划算法.利用动态规划,可以解决任何一个图中的最短路径问题.而维特比算法是针对一个特殊的图--篱笆网络(Lattice)的有向图最短路径的问题而提出的.它之所以重要 ...

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

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

最新文章

  1. 读书不言迟,不读终身痴[转]
  2. 【Python基础】Python数据分析实战之分布分析
  3. 打开terminal后conda出现ERROR REPORT
  4. 计算机巧用剪纸做画册教案,大班绘画剪纸制作的教案总结
  5. Redux学习(一)——Redux的使用过程
  6. 【转载保存】hadoop三个配置文件的参数含义说明core-site.xml、hdfs-site.xml、...
  7. signature=d5d679bcec778027f40bcf8a2796c61b,Processing damaged items using image data lift
  8. redis的默认配置文件redis.conf详解
  9. jnid中mysql的驱动类_JDBC与JNDI的区别
  10. Java8实战(Java8 in Action)精华篇
  11. 计算机管理如何格式化u盘,技术编辑器会教您如何格式化U盘
  12. iWebOffice2015入门(一)
  13. 为什么郭台铭才是夏普的最佳归宿?
  14. 百度智能云NIRO MAX机器人,打造智慧党建新体验!
  15. 【Python训练营】Python每日一练----第28天:鲁卡斯队列(round函数用法)
  16. 关于本人树莓派捣鼓过程中的一些记录
  17. 【OneAPM】极客编程挑战#025:发挥想象生成漂亮炫酷的SVG动画效果
  18. FLUENT操作--VOF模型局部初始化的TUI命令
  19. 一天一个 Linux 命令(37):killall 命令
  20. JS模块化的'前世今生'

热门文章

  1. 【坑】javascript中appName总是Netscape的原因
  2. dayjs 入门及常用方法
  3. mysql 根据身份证号更新年龄
  4. 三层交换机配置MSTP协议详解【华为eNSP实验】
  5. 华为Mate 20电脑模式说明
  6. halcon算子表参考
  7. Java 代码界 3% 的王者?看我是如何解错这 5 道题的
  8. 国内10个最美高校图书馆!一定要考上!
  9. 视屏剪辑背景音乐_文本背景和带有背景剪辑的渐变
  10. 漫谈程序员系列 无BUG不生活