viterbi-algorithm 维特比算法的例子解析
维特比算法的目的:
寻找最可能的隐藏状态序列(Finding most probable sequence of hidden states)
关于原理的讲解可以参考下面两篇文章,讲的比较清楚
小白给小白详解维特比算法1.
小白给小白详解维特比算法2.
本文通过分析维特比算法的例子,来学习该算法
- 定义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 = {}
- 后面天气的情况都是根据前一天天气概率×转移概率×发射概率得到
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 维特比算法的例子解析相关推荐
- 隐马尔可夫模型HMM+维特比算法(Viterbi Algorithm)进行词性标注代码实现(自然语言处理课程第二次作业)
文章目录 一.理论描述 二.算法描述 三.详例描述 具体过程 分析题目 数据预处理 转移概率矩阵: 发射概率矩阵: HMM+维特比算法进行词性标注 开始进行词性标注: The: bear: is: o ...
- 条件随机场(CRF) - 4 - 学习方法和预测算法(维特比算法)
声明: 1,本篇为个人对<2012.李航.统计学习方法.pdf>的学习总结,不得用作商用,欢迎转载,但请注明出处(即:本帖地址). 2,由于本人在学习初始时有很多数学知识都已忘记,所以为了 ...
- 机器学习:维特比算法(Viterbi Algorithm)
一.维特比算法(Viterbi Algorithm)讲解方式01:篱笆网络(Lattice)的最短路径问题 已知下图的篱笆网络,每个节点之间的数字表示相邻节点之间的距离,举个例子来说,如果我走,这个距 ...
- HMM——维特比算法(Viterbi algorithm)
1. 前言 维特比算法针对HMM第三个问题,即解码或者预测问题,寻找最可能的隐藏状态序列: 对于一个特殊的隐马尔可夫模型(HMM)及一个相应的观察序列,找到生成此序列最可能的隐藏状态序列. 也就是说给 ...
- 语音识别学习日志 2019-7-17 语音识别基础知识准备6 {维特比算法(Viterbi Algorithm)}
HMM 维特比算法(Viterbi Algorithm)详细解释参考:http://www.52nlp.cn/hmm-learn-best-practices-six-viterbi-algorith ...
- 维特比算法(Viterbi algorithm) 的理解
维特比算法实际是动态规划解隐马尔科夫模型预测问题,用动态规划求概率最大路径,这时一条路径就是一个状态序列. 根据动态规划原理,最优路径在时刻t,如果最优路径 通过节点Node_t_k, 那么这一路径从 ...
- 维特比算法Viterbi Algorithm
1.简介 维特比算法是一个特殊但应用最广的动态规划算法,它是针对篱笆网络的有向图(Lattice)的最短路径问题而提出的.凡是使用隐含马尔可夫模型描述的问题都可以用维特比算法来解码,包括今天的数 ...
- 简述维特比算法(Viterbi Algorithm)
维特比算法是一个特殊但应用最广的动态规划算法.利用动态规划,可以解决任何一个图中的最短路径问题.而维特比算法是针对一个特殊的图--篱笆网络(Lattice)的有向图最短路径的问题而提出的.它之所以重要 ...
- CRF(条件随机场)与Viterbi(维特比)算法原理详解
摘自:https://mp.weixin.qq.com/s/GXbFxlExDtjtQe-OPwfokA https://www.cnblogs.com/zhibei/p/9391014.html C ...
最新文章
- 读书不言迟,不读终身痴[转]
- 【Python基础】Python数据分析实战之分布分析
- 打开terminal后conda出现ERROR REPORT
- 计算机巧用剪纸做画册教案,大班绘画剪纸制作的教案总结
- Redux学习(一)——Redux的使用过程
- 【转载保存】hadoop三个配置文件的参数含义说明core-site.xml、hdfs-site.xml、...
- signature=d5d679bcec778027f40bcf8a2796c61b,Processing damaged items using image data lift
- redis的默认配置文件redis.conf详解
- jnid中mysql的驱动类_JDBC与JNDI的区别
- Java8实战(Java8 in Action)精华篇
- 计算机管理如何格式化u盘,技术编辑器会教您如何格式化U盘
- iWebOffice2015入门(一)
- 为什么郭台铭才是夏普的最佳归宿?
- 百度智能云NIRO MAX机器人,打造智慧党建新体验!
- 【Python训练营】Python每日一练----第28天:鲁卡斯队列(round函数用法)
- 关于本人树莓派捣鼓过程中的一些记录
- 【OneAPM】极客编程挑战#025:发挥想象生成漂亮炫酷的SVG动画效果
- FLUENT操作--VOF模型局部初始化的TUI命令
- 一天一个 Linux 命令(37):killall 命令
- JS模块化的'前世今生'