HMM-维特比算法理解与实现(python)
HMM-前向后向算法理解与实现(python)
HMM-维特比算法理解与实现(python)
解码问题
- 给定观测序列 \(O=O_1O_2...O_T\),模型 \(\lambda (A,B,\pi)\),找到最可能的状态序列 \(I^∗=\{i^∗_1,i^∗_2,...i^∗_T\}\)
近似算法
- 在每个时刻 \(t\) 选择最可能的状态,得到对应的状态序列
根据HMM-前向后向算法计算时刻 \(t\) 处于状态 \(i^*_t\) 的概率:
\gamma_t(i) = \frac{\alpha_{i}(t) \beta_{i}(t)}{\sum_{i=1}^{N} \alpha_{i}(t) \beta_{i}(t)}
\]
但是无法保证得到的解是全局最优解
维特比算法
维特比算法的基础可以概括为下面三点(来源于吴军:数学之美):
如果概率最大的路径经过篱笆网络的某点,则从起始点到该点的子路径也一定是从开始到该点路径中概率最大的。
假定第
t时刻有k个状态,从开始到t时刻的k个状态有k条最短路径,而最终的最短路径必然经过其中的一条。根据上述性质,在计算第
t+1时刻的最短路径时,只需要考虑从开始到当前的k个状态值的最短路径和当前状态值到第t+1时刻的最短路径即可。如求t=3时的最短路径,等于求t=2时,从起点到当前时刻的所有状态结点的最短路径加上t=2到t=3的各节点的最短路径。

通俗理解维特比算法,对上面三点加深理解
假如你从S和E之间找一条最短的路径,最简单的方法就是列出所有可能的路径 (\(O(T^N)\)),选出最小的,显然时间复杂度太高。怎么办?(摘自[3])
使用维特比算法

S到A列的路径有三种可能:S-A1,S-A2,S-A3,如下图

S-A1,S-A2,S-A3 中必定有一个属于全局最短路径。继续往右,到了B列
对B1:

会产生3条路径:
S-A1-B1,S-A2-B1,S-A3-B1
假设S-A3-B1是最短的一条,删掉其他两条。得到

对B2:

会产生3条路径:
S-A1-B2,S-A2-B2,S-A3-B2
假设S-A1-B2是最短的一条,删掉其他两条。得到

对B3:

会产生3条路径:
S-A1-B3,S-A2-B3,S-A3-B3
假设S-A2-B3是最短的一条,删掉其他两条。得到

现在我们看看对B列的每个节点有哪些,回顾维特比算法第二点
假定第
t时刻有k个状态,从开始到t时刻的k个状态有k条最短路径,而最终的最短路径必然经过其中的一条
B列有三个节点,所以会有三条最短路径,最终的最短路径一定会经过其中一条。如下图

同理,对C列,会得到三条最短路径,如下图

到目前为止,仍然无法确定哪条属于全局最短。最后,我们继续看E节点

最终发现最短路径为S-A1-B2-C3-E
数学描述
在上述过程中,对每一列(每个时刻)会得到对应状态数的最短路径。在数学上如何表达?记录路径的最大概率值 $ \delta_t(i)$ 和对应路径经过的节点 \(\psi_t(i)\)。
定义在时刻 \(t\) 状态为 \(i\) 的所有单条路径中概率最大值为
\]
递推公式
\]
定义在时刻 \(t\) 状态为 \(i\) 的所有单条路径中,概率最大路径的第 \(t - 1\) 个节点为
\]
维特比算法步骤:
step1:初始化
\]
step2:递推,对 \(t=2,3,...,T\)
\]
step3:计算时刻 \(T\) 最大的 \(\delta_T(i)\) ,即为最可能隐藏状态序列出现的概率。计算时刻\(T\)最大的 \(\psi_T(i)\) ,即为时刻\(T\)最可能的隐藏状态。
\]
step4:最优路径回溯,对\(t=T-1,...,1\)
\]
代码实现
假设从三个 袋子 {1,2,3}中 取出 4 个球 O={red,white,red,white},模型参数\(\lambda = (A,B,\pi)\) 如下,计算状态序列,即取出的球来自哪个袋子
#状态 1 2 3
A = [[0.5,0.2,0.3],
[0.3,0.5,0.2],
[0.2,0.3,0.5]]
pi = [0.2,0.4,0.4]
# red white
B = [[0.5,0.5],
[0.4,0.6],
[0.7,0.3]]
def hmm_viterbi(A,B,pi,O):
T = len(O)
N = len(A[0])
delta = [[0]*N for _ in range(T)]
psi = [[0]*N for _ in range(T)]
#step1: init
for i in range(N):
delta[0][i] = pi[i]*B[i][O[0]]
psi[0][i] = 0
#step2: iter
for t in range(1,T):
for i in range(N):
temp,maxindex = 0,0
for j in range(N):
res = delta[t-1][j]*A[j][i]
if res>temp:
temp = res
maxindex = j
delta[t][i] = temp*B[i][O[t]]#delta
psi[t][i] = maxindex
#step3: end
p = max(delta[-1])
for i in range(N):
if delta[-1][i] == p:
i_T = i
#step4:backtrack
path = [0]*T
i_t = i_T
for t in reversed(range(T-1)):
i_t = psi[t+1][i_t]
path[t] = i_t
path[-1] = i_T
return delta,psi,path
A = [[0.5,0.2,0.3],[0.3,0.5,0.2],[0.2,0.3,0.5]]
B = [[0.5,0.5],[0.4,0.6],[0.7,0.3]]
pi = [0.2,0.4,0.4]
O = [0,1,0,1]
hmm_viterbi(A,B,pi,O)
结果

references:
[1]https://www.cnblogs.com/kaituorensheng/archive/2012/12/04/2802140.html
[2] https://blog.csdn.net/hudashi/java/article/details/87875259
[3] https://www.zhihu.com/question/20136144
HMM-维特比算法理解与实现(python)的更多相关文章
- Java实现:抛开jieba等工具,写HMM+维特比算法进行词性标注
一.前言:词性标注 二.经典维特比算法(Viterbi) 三.算法实现 四.完整代码 五.效果演示: 六.总结 一.前言:词性标注 词性标注(Part-Of-Speech tagging, POS t ...
- HMM——维特比算法(Viterbi algorithm)
1. 前言维特比算法针对HMM第三个问题,即解码或者预测问题,寻找最可能的隐藏状态序列: 对于一个特殊的隐马尔可夫模型(HMM)及一个相应的观察序列,找到生成此序列最可能的隐藏状态序列. 也就是说给定 ...
- 详解隐马尔可夫模型(HMM)中的维特比算法
笔记转载于GitHub项目:https://github.com/NLP-LOVE/Introduction-NLP 4. 隐马尔可夫模型与序列标注 第3章的n元语法模型从词语接续的流畅度出发,为全切 ...
- 隐马尔科夫模型HMM(四)维特比算法解码隐藏状态序列
隐马尔科夫模型HMM(一)HMM模型 隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率 隐马尔科夫模型HMM(三)鲍姆-韦尔奇算法求解HMM参数 隐马尔科夫模型HMM(四)维特比算法解码隐藏状态 ...
- 维特比算法Python实现
前言 维特比算法是隐马尔科夫问题的一个基本问题算法.维特比算法解决的问题是已知观察序列,求最可能的标注序列. 什么是维特比算法? 维特比算法尽管是基于严格的数学模型的算法,但是维特比算法毕竟是算法,因 ...
- viterbi维特比算法和隐马尔可夫模型(HMM)
隐马尔可夫模型(HMM) 原文地址:http://www.cnblogs.com/jacklu/p/7753471.html 本文结合了王晓刚老师的ENGG 5202 Pattern Recognit ...
- 【机器学习】【条件随机场CRF-2】CRF的预测算法之维特比算法(viterbi alg) 详解 + 示例讲解 + Python实现
1.CRF的预测算法条件随机场的预测算法是给定条件随机场P(Y|X)和输入序列(观测序列)x,求条件概率最大的输出序列(标记序列)y*,即对观测序列进行标注.条件随机场的预测算法是著名的维特比算法(V ...
- HMM-前向后向算法理解与实现(python)
目录 基本要素 HMM三大问题 概率计算问题 前向算法 后向算法 前向-后向算法 基本要素 状态 \(N\)个 状态序列 \(S = s_1,s_2,...\) 观测序列 \(O=O_1,O_2,.. ...
- HMM 自学教程(六)维特比算法
本系列文章摘自 52nlp(我爱自然语言处理: http://www.52nlp.cn/),原文链接在 HMM 学习最佳范例,这是针对 国外网站上一个 HMM 教程 的翻译,作者功底很深,翻译得很精彩 ...
随机推荐
- SpringCloud(四)学习笔记之Feign
Feign是一个声明式的Web服务客户端,可帮助我们更加便捷.优雅地调用HTTP API Feign可以与Eureka和Ribbon组合使用以支持负载均衡 一.构建Eureka Server [基于第 ...
- Apache Hudi集成Apache Zeppelin实战
1. 简介 Apache Zeppelin 是一个提供交互数据分析且基于Web的笔记本.方便你做出可数据驱动的.可交互且可协作的精美文档,并且支持多种语言,包括 Scala(使用 Apache Spa ...
- php静态变量的销毁
什么都不说,先上代码: public function _childrenids($data,$cate_id,$clear=false) { static $arr = array(); if ($ ...
- Docker help详细帮助
常用的 docker 命令 docker # docker 命令帮助 Commands: attach Attach to a running container # 当前 shell 下 attac ...
- Service Location Protocol SLP
https://www.ibm.com/developerworks/cn/linux/l-slp/ 服务发现(service discovery) 是在网络环境中发现必须使用的服务的能力.例如,如果 ...
- Inno Setup [Run] Section 双引号嵌套
https://stackoverflow.com/questions/26257808/inno-setup-how-to-run-a-code-procedure-in-run-section-o ...
- OpenCV学习(4)——动态结构
学习一个新知识,无外乎学习它本身和它的工具.OpenCV提供许多内置的结构及处理函数,非常值得学习. 内存存储 在OpenCV中,内存存储器是一个可以用来存储序列.数组和图像的动态增长的数据结构.它由 ...
- 编写管理IP地址参数脚本(永久性)
1.用各种命令取出/etc/passwd文件前5行的最后一个字母.(2种) 2.编写管理IP地址参数脚本(永久性) a.只能用sed命令完成 b.提示用户变量赋值(IP.子网掩码.网关.DNS等) c ...
- 即将进行论文答辩的我发现MyEclipse 2016 激活过期害得我又一次把 MyEclipse 2016 给重新激活注册,详细的图文解说激活过程
背景: 在家美滋滋的上着网课享受着因为疫情带来的平静,没想到随着微信.钉钉铃声响起打破了我半年以来的平静的生活:通知我们过完劳动节要进行答辩,由于我的答辩项目是由 MyEclipse 这个工具编写的我 ...
- var、let、const
var.let.const之间的区别和使用 1.var声明变量可以重复声明,而let不可以重复声明 let a = 1; let a = 2; var b = 3; var b = 4; a // I ...