hmm 求隐藏序列_自然语言处理(3)隐马尔科夫模型 HMM
1 前言
隐马尔科夫模型(Hidden Markov Model,以下简称 HMM)是比较经典的机器学习模型了,它在语音识别,自然语言处理,模式识别等领域得到广泛的应用。隐马尔科夫模型继承了马尔科夫链的性质,即马尔科夫性。关于马尔科夫性的介绍,可以参考:
随风:自然语言处理(2)主题模型 LDA (1 数学基础篇)zhuanlan.zhihu.com
第 5 节的 5.2 马尔科夫链(Markov Chain)。
2 什么是隐马尔科夫模型?
如下图所示,假设我们有 3 个筛子,一个六面体(D6:1~6),一个四面体(D4:1~4),一个八面体(D8:1~8)。
现在我们随机选取一个筛子,假设选取了 D6,并且将 D6 抛掷一次,假设得到数字 1。下一步我们再选取一个骰子,假设选取了 D8,并且将 D8 抛掷一次,假设得到数字 6。按照上面的方法重复多次,将得到两个序列:一个是筛子的序列,另一个是数字的序列,如下图所示:
假设 A 每次掷骰子得到一个数字,B 作为观测者,只能看到每次得到的数字,而不知道是哪个骰子。我们将筛子的状态序列称为隐含序列,将数字序列称为观测序列。隐含序列具有马尔科夫性,即下一个骰子是 D4、D6 还是 D8,仅由上一个骰子决定,骰子之间的转移概率可以表示为:
而观测值由它所对应的隐含状态决定,即假设当前数字为 8,那么可以肯定它对应的隐含状态为骰子 D8,而与它前后的骰子没有关系。
上面这个例子涉及到两个序列,一个是具有马尔科夫性的骰子序列,另一个是观测序列,这就是 HMM,下面给出 HMM 的定义。
假设
对于一个长度为 T 的序列,隐含状态序列
HMM 做了两个假设如下:
(1)马尔科夫性,即任意时刻的隐含状态只依赖于它前一个隐含状态(其实当前状态可能依赖于前面的几个状态,这样假设是为了使模型极大的简化)。如果在时刻 t 的隐含状态
这样
(2)观测独立性,即任意时刻的观测状态只依赖于当前时刻的隐含状态。如果在时刻 t 的隐含状态
这样
此外,我们还需要一组在时刻 t = 1 的隐含状态概率分布,即初始概率分布:
一个 HMM,由初始隐含概率分布
3 关于 HMM 的三个问题
如下图所示,描述了一天的天气与人的行为的概率转移图。其中,隐含状态集合
现在我们连续观测三天,得到观测序列为
隐含状态转移概率矩阵为:
观测结果生成概率矩阵为:
这样我们就得到了 HMM,
针对一个 HMM,有三大问题:
- 评估观测序列的概率:已知
,,求即给定模型的条件下,产生序列的概率。
- 计算隐含状态序列:已知
,,求隐含状态序列。即求出最可能出现的隐含状态序列。
- 模型参数学习:已知
,求。即给定观测序列求模型,使得最大。
这三个问题的难度依次递增,下面分别求解问题 1、2。由于问题 3 的求解过于复杂(Baum-Welch算法),且在数学上只能得到局部最优解,这里不再讨论。
4 前向后向算法评估观测序列的概率
先来解决第一个问题:已知
如上图所示,当模型给定的情况下,显然,我们可以通过暴力求解的方式得到结果。比如我们的观测序列为
这是其中一条可以形成观测序列
显然,这样计算的时间复杂度太高。那应该如何求解呢?可以通过前向后向算法求解。
4.1 前向算法求解
前向算法本质上属于动态规划的算法,也就是我们要通过找到局部状态递推的公式,这样一步步的从子问题的最优解拓展到整个问题的最优解。
定义“前向概率”:
表示 t 时刻,隐含状态为
现在假设 t 时刻的隐含状态为
我们从 t=1 开始,到 T 时刻结束,由于
总结一下前向算法的过程:
输入:HMM
输出:观测序列出现的概率
(1)计算 t=1 的前向概率:
(2)递推 t=2,3...,T 的前向概率:
(3)计算最终结果:
下面求解一下观测序列
1) t=1:
2)t=2:
3)t=3:
因此
4.2 后向算法求解
后向算法和前向算法非常类似,都是用的动态规划,唯一的区别是选择的局部状态不同,后向算法用的是“后向概率”。定义“后向概率”:
表示 t 时刻,隐含状态为
现在假设 t 时刻的隐含状态为
总结一下前向算法的过程:
输入:HMM
输出:观测序列出现的概率
(1)初始化 T 时刻的隐含状态的后向概率:
注意 T 时刻以后已经没有观测序列,
(2)递推 t=T-1,T-2,...,1 时刻的后向概率:
(3)计算最终结果:
5 Viterbi 算法计算隐含状态序列
HMM 的解码问题最常用的算法是维特比算法,当然也有其他的算法可以求解这个问题。同时维特比算法是一个通用的求序列最短路径的动态规划算法,也可以用于很多其他问题。
5.1 最短路径问题
先来看一个问题,如下图所示,描述了各个节点之间的距离。比如从 A 走到 E,可以走的路线是 A-B1-C1-D1-E,这条路线的距离为 6+5+7+4=22。现在的问题是,选择哪条路径从 A 到 E 的距离最短呢?
当然可以通过暴力求解的方式遍历从 A 到 E 的所有路径,求出最小的。显然,这种方法的时间复杂度太高。那么有没有更简单的方法呢?
将上图先改造成这样:
如果我们知道 A-D1、A-D2、A-D3 的最短路径(对应图中三个问号),就可以很容易的得到 A-E 的最短路径。
为了确定从哪个 D 到 E 才是最短的,我们就必须确定 A 到每一个 D 的最短路径,这样 A-E 的最短路径问题,就变成了 A-D 的最短路径问题。我们把一个问题变为了求解它的子问题,这不正是动态规划的思想吗?
要求解 A-D 的最短路径,就需要分别求出 A-D1、A-D2、A-D3 的最短路径,然后取最小的一个。假设我们先求解 A-D1 的最短路径,如下图:
又需要求解 A-C 的最短路径,先来看一下 A-C1 的最短路径:
哈哈,小学生都会了!好了,现在我们从前往后来完整的推一遍。
1)A-C 的最短路径:
A-C1 的路径(6+5,7+4,5+4),显然 A-C1 的最短路径为 9,路径为 A-B3-C1
A-C2 的路径(6+6,7+3,5+6),显然 A-C2 的最短路径为 10,路径为 A-B2-C2
A-C3 的路径(6+9,7+7,5+6),显然 A-C1 的最短路径为 11,路径为 A-B3-C3
因此 A-C 的最短路径为 A-B3-C1,距离为 9
2)A-D 的最短路径:
A-D1 的路径(9+8,10+5,11+5),显然 A-D1 的最短路径为 15,路径为 A-B2-C2-D1
A-D2 的路径(9+7,10+4,11+7),显然 A-D2 的最短路径为 14,路径为 A-B2-C2-D2
A-D3 的路径(9+3,10+3,11+6),显然 A-D3 的最短路径为 12,路径为 A-B3-C1-D3
因此 A-D 的最短路径为 A-B3-C1-D3,距离为12
3)A-E 的最短路径:
显然,A-E 的最短路径为 A-B3-C1-D3-E, 距离为 17。这样我们就用一层层的递推方法解决了最短路径问题,这就是 Viterbi 算法。
5.2 计算隐含状态序列问题
还是以上面这张图为例,来构建一个类似于最短路径问题的网络:
其中 R 表示 Rainy,S 表示 Sunny。下面求解一下观测序列
注意这里和最短路径问题的区别,这里的距离换成了状态转移概率,概率之间变成了相乘的关系而不是相加,我们要求的问题也变成了求一条路径最大的概率。再来看一下从状态到观测结果的概率:
注意前面的节点表示隐含状态,发射出去的节点表示观测结果,因此状态到结果的概率也称为发射概率。下面按照 Viterbi 算法的过程来求解:
1)Start-2 且产生
A-R2 的路径(Start-R1-R2,Start-S1-R2),概率为(0.6*0.1*0.7*0.4,0.4*0.6*0.4*0.4)=(0.0168,0.0384),显然 A-R2 的最大概率为 0.0384,路径为 Start-S1-R2。
A-S2 的路径(Start-R1-S2,Start-S1-S2),概率为(0.6*0.1*0.3*0.3,0.4*0.6*0.6*0.3)=(0.0054,0.0432),显然 A-S2 的最大概率为 0.0432,路径为 Start-S1-S2。
因此 Start-2 的最大路径为 Start-S1-S2,概率为 0.0432
2)Start-3 且产生
A-R3 的路径(Start-S1-R2-R3,Start-S1-S2-R3),概率为(0.0384*0.7*0.5,0.0432*0.4*0.5)=(0.01344,0.00864),显然 A-R3 的最大概率为 0.01344,路径为 Start-S1-R2-R3。
A-S3 的路径(Start-S1-R2-RS3,Start-S1-S2-S3),概率为(0.0384*0.3*0.1,0.0432*0.6*0.1)=(0.001152,0.0025924),显然 A-S3 的最大概率为 0.0025924,路径为 Start-S1-S2-S3。
因此 Start-3 的最大路径为 Start-S1-R2-R3,概率为 0.01344。
这样我们就得到了隐含状态序列
首先定义两个变量:
1)定义变量
注意这里不但要考虑每一个时刻隐含状态产生观测结果的概率,还需要考虑从当前隐含状态转移到下一个隐含状态的概率,使其概率乘积尽可能大,所以用联合概率表示。
由
2)定义变量
任意 t-1 时刻的状态
正如我们在定义变量
注意这里
有了这两个变量,我们就可以从 t=1 一直递推到 t=T,利用
现在就可以总结下 Viterbi 算法的流程:
输入:HMM
输出:最有可能的隐含状态序列
1)初始化变量
2)递推 t=2,3,...,T 时刻的变量:
3)计算 T 时刻最大的
4)因为之前每一步都计算了
6 HMM 实战
来看一个词性标注问题。比如有这样一句话:“I like nlp”,现在要标注每个词的词性。这句话的词性为人称代词(PRON)、动词(VERB)、名词(NOUN)。
下面看这两句话:
- Please book my flight for Shanghai
- I am going to read this book in the flight
这两句话中, book 的含义不同,如果我们能标注 book 的词性,就能够消除歧义。另一方面,在做词频统计时,我们应该区分这两个 book,即(book_VB,1),(book_NN,1)。这样做可以强化基于单词的特征。
看下面这张图,一句话中的每个单词,是以一定的概率选择某个词性,再从该词性中以一定概率选择某个词(有点像 LDA)。在 HMM 中,我们把一句话的词性序列看作隐含状态序列,把单词序列看作观测结果序列。
以“I like nlp”这句话为例,因为 HMM 需要开始状态,我们在一句话的开始位置添加 Start,结束位置添加 End。这句话就变成了“Start I like nlp End”。这句话出现的概率为:
公式里面有两个变量需要求解,一个是词性的隐含状态转移概率,即隐含状态转移概率矩阵 A;另一个是词性到词语的喷射概率,即观测结果生成的概率矩阵 B。这就需要一个已经标注过词性的语料库,假设我们有了这样一个语料库,就可以通过统计的方法计算这两个变量:
1)
2)
HMM 还有一个参数是初始状态
词性标注问题属于 HMM 的第二类问题,即已知一句话(观测序列),需要找到出现概率最大的词性序列(隐含序列)。这里的语料库使用 nltk 自带的布朗大学标注的语料库来生成 HMM。
import nltk
from nltk.corpus import brown# 获取状态转移矩阵 A
def get_tags_pro(brown_tags):cfd_tags = nltk.ConditionalFreqDist(nltk.bigrams(brown_tags))cpd_tags = nltk.ConditionalProbDist(cfd_tags, nltk.MLEProbDist)return cpd_tags# 获取喷射矩阵 B
def get_tags_words_pro(brown_tags_words):cfd_tag_words = nltk.ConditionalFreqDist(brown_tags_words)cpd_tag_words = nltk.ConditionalProbDist(cfd_tag_words, nltk.MLEProbDist)return cpd_tag_words# viterbi 算法
def exc_viterbi(distinct_tags, tags_pro, tags_words_pro, sentence):values = []traces = []# 初始化first_value = {}first_layer = {}for tag in distinct_tags:if tag == 'START': continuefirst_value[tag] = tags_pro['START'].prob(tag) * tags_words_pro[tag].prob(sentence[0])first_layer[tag] = 'START'values.append(first_value)traces.append(first_layer)best_current_tag = max(first_value.keys(), key=lambda tag: first_value[tag])print("Word", "'" + sentence[0] + "'", "current best two-tag sequence:", first_layer[best_current_tag], best_current_tag)# 递推关系for word_index in range(1, len(sentence)):this_value = {}this_layer = {}prev_value = values[-1]for tag in distinct_tags:if tag == 'START': continuebest_prev_tag = max(prev_value.keys(), key=lambda prev_tag: prev_value[prev_tag] * tags_pro[prev_tag].prob(tag) * tags_words_pro[tag].prob(sentence[word_index]))this_value[tag] = prev_value[best_prev_tag] * tags_pro[best_prev_tag].prob(tag) * tags_words_pro[tag].prob(sentence[word_index])this_layer[tag] = best_prev_tagbest_current_tag = max(this_value.keys(), key=lambda tag: this_value[tag])print("Word", "'" + sentence[word_index] + "'", "current best two-tag sequence:", this_layer[best_current_tag], best_current_tag)values.append(this_value)traces.append(this_layer)# 语句最后一个单词到结束词 End 的处理prev_value = values[-1]best_prev_tag = max(prev_value.keys(), key=lambda prev_tag: prev_value[prev_tag] * tags_pro[prev_tag].prob('END'))best_pro = prev_value[best_prev_tag] * tags_pro[best_prev_tag].prob('END')best_tag_seq = ['END', best_prev_tag]traces.reverse()current_best_tag = best_prev_tagfor trace in traces:best_tag_seq.append(trace[current_best_tag])current_best_tag = trace[current_best_tag]best_tag_seq.reverse()return best_tag_seq, best_probrown_tags_words = []
for sent in brown.tagged_sents():# 先加开头brown_tags_words.append(('START', 'START'))# 为了省事儿,我们把 tag 都省略成前两个字母brown_tags_words.extend([(tag, word) for (word, tag) in sent])# 加个结尾brown_tags_words.append(('END', 'END'))brown_tags = [tag for (tag, word) in brown_tags_words]
tags_pro = get_tags_pro(brown_tags)tags_words_pro = get_tags_words_pro(brown_tags_words)distinct_tags = set(brown_tags)
sentence = ['I', 'like', 'nature', 'language', 'processing']
best_tag_seq, best_pro = exc_viterbi(distinct_tags, tags_pro, tags_words_pro, sentence)print('the best hidden seq: ', best_tag_seq)
print('the best pro: ', best_pro)结果:
Word 'I' current best two-tag sequence: START PPSS
Word 'like' current best two-tag sequence: PPSS VB
Word 'nature' current best two-tag sequence: VB NN
Word 'language' current best two-tag sequence: NN NN
Word 'processing' current best two-tag sequence: NN NN
the best hidden seq: ['START', 'PPSS', 'VB', 'NN', 'NN', 'NN', 'END']
the best pro: 3.0637465502036634e-22
可以看到,标注的结果是正确的,但是概率非常低。从原理来看,HMM 在解决词性标注问题的效果,完全依赖于语料库的好坏,个人感觉布朗大学的这个语料库不是很好,如果能找到更丰富的语料库,出现概率应该会有明显提升。
hmm 求隐藏序列_自然语言处理(3)隐马尔科夫模型 HMM相关推荐
- python地图匹配_基于隐马尔科夫模型(HMM)的地图匹配(Map-Matching)算法
1. 摘要 本篇博客简单介绍下用隐马尔科夫模型(Hidden Markov Model, HMM)来解决地图匹配(Map-Matching)问题.转载请注明网址. 2. Map-Matching(MM ...
- 隐马尔科夫模型(HMM)算法的理解与超详细推导
今天看了徐亦达教授的HMM讲解,感觉有所收获,并将隐马尔科夫模型算法的推导整理了一下,帮助大家一起理解这个算法.首先我们通过一个股票的案例来引入这个算法,我们来看看这个股票行情和涨跌观测值的一个状态图 ...
- 一、隐马尔科夫模型HMM
隐马尔科夫模型HMM(一)HMM模型基础 隐马尔科夫模型(Hidden Markov Model,以下简称HMM)是比较经典的机器学习模型了,它在语言识别,自然语言处理,模式识别等领域得到广泛的应用. ...
- 隐马尔科夫模型 (HMM) 算法介绍及代码实现
Table of Contents Hidden Markov Model (隐马尔科夫模型) 定义 基本问题 前向算法 算法流程 实现代码 后向算法 算法流程 实现代码 Viterbi算法 算法流程 ...
- 【NLP】用于语音识别、分词的隐马尔科夫模型HMM
大家好,今天介绍自然语言处理中经典的隐马尔科夫模型(HMM).HMM早期在语音识别.分词等序列标注问题中有着广泛的应用. 了解HMM的基础原理以及应用,对于了解NLP处理问题的基本思想和技术发展脉络有 ...
- 隐马尔科夫模型HMM(三)鲍姆-韦尔奇算法求解HMM参数
在本篇我们会讨论HMM模型参数求解的问题,这个问题在HMM三个问题里算是最复杂的.在研究这个问题之前,建议先阅读这个系列的前两篇以熟悉HMM模型和HMM的前向后向算法,以及EM算法原理总结,这些在本篇 ...
- m基于隐马尔科夫模型(HMM)的手机用户行为预测(MMUB)算法matlab仿真
目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 隐马尔可夫模型(Hidden Markov Model,HMM)是一种统计模型,广泛应用在语音识别, ...
- 隐马尔科夫模型HMM自学 (2)
HMM 定义 崔晓源 翻译 HMM是一个三元组 (,A,B). the vector of the initial state probabilities; the state transitio ...
- 第九章 隐马尔科夫模型HMM
文章目录 1 隐马尔科夫模型定义 2 概率计算算法 2.1 前向概率 2.2 概率计算 3 学习算法 3.1 EM算法 3.2EM在HMM 4 预测算法 1 隐马尔科夫模型定义 隐马尔科夫模型是一个s ...
- 隐马尔科夫模型(HMM)择时应用的量化策略
HMM模型 隐马尔科夫模型(HMM)择时应用的量化策略. 仅为研究学习使用, 不作为任何投资策略建议. 文章内容从各处整理汇总而成, 感谢各位大神分享. 具体策略代码均调试通过. 一.从大奖章讲起 ...
最新文章
- jwt 私钥_一分钟带你了解JWT认证
- iOS开发 关于启动页和停留时间的设置
- 怎样把字符1变成数字1
- 1%学者拥有21%引用量,全球学术圈两极分化扩大
- Android反编译apk并重新打包签名(Mac环境)
- 2019研究生数学建模比赛题目
- Symbian编程总结-图形图像篇-打开非Bitmap类型的图像
- ASP.NET Web API中展示实体Link相关的方面
- 前端学习(1815):前端调试之css flex 练习1
- 组合数的和(java)
- 「技术大牛」是如何缩短事件平均解决时间的?
- python精简总结
- python3使用pickle读取文件提示TypeError或者UnicodeDecodeError的解决办法
- ElementUI:input表单验证
- Could not read JSON: Cannot construct instance of `java.util.ArrayList$SubList`Redis反序列化异常
- 人物动画计算机课教学反思,flash课教学反思
- 在线搜索全网音乐支持歌曲外链下载等源码[免费开源]
- 你真的懂协程 (Coroutine) 吗 ? Kotlin Coroutines — Suspending Functions
- 强化学习笔记一 N-armed bandit Problem
- 本机号码认证黑科技:极光(JG)开发者服务推出“极光认证”新产品
热门文章
- Fedora上配置一个安全FTP
- C++编译器默默编写并调用哪些函数
- Shell脚本中date的用法小结
- Qt-Qt Creator的下载、安装与配置(Windows)
- mysql最小费用最大流问题_最小费用最大流问题
- 域做文件服务器,linux 做域文件服务器
- js parsefloat 精度_javascript中的float运算精度
- python中怎么替换字母_python去除拼音声调字母,替换为字母的方法
- 自动化比手工测试成本高?使用Selenium评估测试自动化的ROI指标
- oracle11g 时间失效,关于oracle11g RAC 的CTSS与ntp时间同步的疑问