一站式解决:隐马尔可夫模型(HMM)全过程推导及实现
【导读】隐马尔可夫模型(Hidden Markov Model,HMM)是关于时许的概率模型,是一个生成模型,描述由一个隐藏的马尔科夫链随机生成不可观测的状态序列,每个状态生成一个观测,而由此产生一个观测序列。
定义抄完了,下面我们从一个简单的生成过程入手,顺便引出HMM的参数。
假设有4个盒子,每个盒子里面有不同数量的红、白两种颜色的球,具体如下表:
本栗子引用自《统计学习方法》
现在从这些盒子中抽取若干( )个球,每次抽取后记录颜色,再放回原盒子,采样的规则如下:
开始时,按照一个初始概率分布随机选择第一个盒子,这里将第一个盒子用 表示:
将的值用变量 表示。因为有4个盒子可共选择,所以 。然后随机从该盒子中抽取一个球,使用表示:
将 的值用变量 表示。因为只有两种球可供选择,所以 。一共有4个箱子,2种球,结合前面的箱子的详细数据,可以得到从每一个箱子取到各种颜色球的可能性,用一个表格表示:
进一步,可以用一个矩阵(称为观测概率矩阵,也有资料叫做发射矩阵)来表示该表
其中 表示在当前时刻给定 的条件下,给定
表示当前的时刻,例如现在是第1时刻;然后是前面标注的初始概率分布,这个概率分布可以用一个向量(称作初始状态概率向量)来表示:
其中的
例如该分布是均匀分布的话,对应的向量就是
记录抽取的球的颜色后将其放回,然后在按照如下规则选择下一个盒子():
- 如果当前是盒子1,则选择盒子2
- 如果当前是盒子2或3,则分布以概率0.4和0.6选择前一个或后一个盒子
- 如果当前是盒子4,则各以0.5的概率停留在盒子4或者选择盒子3
import numpy as np class HMM(object): def __init__(self, N, M, pi=None, A=None, B=None): self.N = N self.M = M self.pi = pi self.A = A self.B = B def get_data_with_distribute(self, dist): # 根据给定的概率分布随机返回数据(索引) r = np.random.rand() for i, p in enumerate(dist): if r < p: return i r -= p def generate(self, T: int): ''' 根据给定的参数生成观测序列 T: 指定要生成数据的数量 ''' z = self.get_data_with_distribute(self.pi) # 根据初始概率分布生成第一个状态 x = self.get_data_with_distribute(self.B[z]) # 生成第一个观测数据 result = [x] for _ in range(T-1): # 依次生成余下的状态和观测数据 z = self.get_data_with_distribute(self.A[z]) x = self.get_data_with_distribute(self.B[z]) result.append(x) return result if __name__ == "__main__": pi = np.array([.25, .25, .25, .25]) A = np.array([ [0, 1, 0, 0], [.4, 0, .6, 0], [0, .4, 0, .6], [0, 0, .5, .5]]) B = np.array([ [.5, .5], [.3, .7], [.6, .4], [.8, .2]]) hmm = HMM(4, 2, pi, A, B) print(hmm.generate(10)) # 生成10个数据 # 生成结果如下
[0, 0, 1, 1, 1, 1, 0, 1, 0, 0] # 0代表红球,1代表白球
- 齐次马尔可夫假设:即任意时刻的状态只依赖于前一时刻的状态,与其他时刻的状态无关(当然,初始时刻的状态由参数π决定):
- 观测独立假设:即任意时刻的观测只依赖于该时刻的状态,与其他无关:概率计算算法
概率计算算法
即使不考虑内部的计算,这起码也是 阶的计算量,所以需要更有效的算法,下面介绍两种:前向算法和后向算法。
也就是下图中标记的那一部分
接着,根据(2)式,还可以得到:
由此公式,遍历的取值求和,可以得到 的边际概率
class HMM(object): def evaluate(self, X): ''' 根据给定的参数计算条件概率 X: 观测数据 ''' alpha = self.pi * self.B[:,X[0]] for x in X[1:]: # alpha_next = np.empty(self.N) # for j in range(self.N): # alpha_next[j] = np.sum(self.A[:,j] * alpha * self.B[j,x]) # alpha = alpha_next alpha = np.sum(self.A * alpha.reshape(-1,1) * self.B[:,x].reshape(1,-1), axis=0) return alpha.sum() print(hmm.evaluate([0,0,1,1,0])) # 0.026862016
def evaluate_backward(self, X): beta = np.ones(self.N) for x in X[:0:-1]: beta_next = np.empty(self.N) for i in range(self.N): beta_next[i] = np.sum(self.A[i,:] * self.B[:,x] * beta) beta = beta_next return np.sum(beta * self.pi * self.B[:,X[0]])
学习算法
最终得到:
同样,使用拉格朗日乘数法,构造目标函数
然后化简:
代入(7)式,得到
M是矩阵B的列数,前面已经定义过的,构造拉格朗日函数:
class HMM(object): def fit(self, X): ''' 根据给定观测序列反推参数 ''' # 初始化参数 pi, A, B self.pi = np.random.sample(self.N) self.A = np.ones((self.N,self.N)) / self.N self.B = np.ones((self.N,self.M)) / self.M self.pi = self.pi / self.pi.sum() T = len(X) for _ in range(50): # 按公式计算下一时刻的参数 alpha, beta = self.get_something(X) gamma = alpha * beta for i in range(self.N): for j in range(self.N): self.A[i,j] = np.sum(alpha[:-1,i]*beta[1:,j]*self.A[i,j]*self.B[j,X[1:]]) / gamma[:-1,i].sum() for j in range(self.N): for k in range(self.M): self.B[j,k] = np.sum(gamma[:,j]*(X == k)) / gamma[:,j].sum() self.pi = gamma[0] / gamma[-1].sum() def get_something(self, X): ''' 根据给定数据与参数,计算所有时刻的前向概率和后向概率 ''' T = len(X) alpha = np.zeros((T,self.N)) alpha[0,:] = self.pi * self.B[:,X[0]] for i in range(T-1): x = X[i+1] alpha[i+1,:] = np.sum(self.A * alpha[i].reshape(-1,1) * self.B[:,x].reshape(1,-1), axis=0) beta = np.ones((T,self.N)) for j in range(T-1,0,-1): for i in range(self.N): beta[j-1,i] = np.sum(self.A[i,:] * self.B[:,X[j]] * beta[j]) return alpha, beta if __name__ == "__main__": import matplotlib.pyplot as plt def triangle_data(T): # 生成三角波形状的序列 data = [] for x in range(T): x = x % 6 data.append(x if x <= 3 else 6-x) return data data = np.array(triangle_data(30)) hmm = HMM(10, 4) hmm.fit(data) # 先根据给定数据反推参数 gen_obs = hmm.generate(30) # 再根据学习的参数生成数据 x = np.arange(30) plt.scatter(x, gen_obs, marker='*', color='r') plt.plot(x, data, color='g') plt.show()
预测算法
class HMM(object): def decode(self, X): T = len(X) x = X[0] delta = self.pi * self.B[:,x] varphi = np.zeros((T, self.N), dtype=int) path = [0] * T for i in range(1, T): delta = delta.reshape(-1,1) # 转成一列方便广播 tmp = delta * self.A varphi[i,:] = np.argmax(tmp, axis=0) delta = np.max(tmp, axis=0) * self.B[:,X[i]] path[-1] = np.argmax(delta) # 回溯最优路径 for i in range(T-1,0,-1): path[i-1] = varphi[i,path[i]] return path
◆
精彩推荐
◆
推荐阅读
确认!语音识别大牛Daniel Povey将入职小米,曾遭霍普金斯大学解雇,怒拒Facebook
大规模1.4亿中文知识图谱数据,我把它开源了
自动驾驶关键环节:行人的行为意图建模和预测(上)
不足 20 行 Python 代码,高效实现 k-means 均值聚类算法
巨头垂涎却不能染指,loT 数据库风口已至
【建议收藏】数据中心服务器基础知识大全
从4个维度深度剖析闪电网络现状,在CKB上实现闪电网络的理由 | 博文精选
身边程序员同事竟说自己敲代码速度快!Ctrl+C、Ctrl+V ?
100 美元一行代码,开源软件到底咋赚钱?
你点的每个“在看”,我都认真当成了AI
一站式解决:隐马尔可夫模型(HMM)全过程推导及实现相关推荐
- 隐马尔科夫模型 (HMM) 算法介绍及代码实现
Table of Contents Hidden Markov Model (隐马尔科夫模型) 定义 基本问题 前向算法 算法流程 实现代码 后向算法 算法流程 实现代码 Viterbi算法 算法流程 ...
- 机器学习知识点(二十四)隐马尔可夫模型HMM维特比Viterbi算法Java实现
1.隐马尔可夫模型HMM 学习算法,看中文不如看英文,中文喜欢描述的很高深. http://www.comp.leeds.ac.uk/roger/HiddenMarkovModels/ht ...
- 隐马尔科夫模型HMM自学 (3)
Viterbi Algorithm 本来想明天再把后面的部分写好,可是睡觉今天是节日呢?一时情不自禁就有打开电脑.......... 找到可能性最大的隐含状态序列 崔晓源 翻译 多数情况下,我们都希望 ...
- 隐马尔科夫模型HMM自学 (2)
HMM 定义 崔晓源 翻译 HMM是一个三元组 (,A,B). the vector of the initial state probabilities; the state transitio ...
- 隐马尔科夫模型HMM自学(1)
介绍 崔晓源 翻译 我们通常都习惯寻找一个事物在一段时间里的变化规律.在很多领域我们都希望找到这个规律,比如计算机中的指令顺序,句子中的词顺序和语音中的词顺序等等.一个最适用的例子就是天气的预测. 首 ...
- 【NLP】用于语音识别、分词的隐马尔科夫模型HMM
大家好,今天介绍自然语言处理中经典的隐马尔科夫模型(HMM).HMM早期在语音识别.分词等序列标注问题中有着广泛的应用. 了解HMM的基础原理以及应用,对于了解NLP处理问题的基本思想和技术发展脉络有 ...
- 用隐马尔可夫模型(HMM)做命名实体识别——NER系列(二)
上一篇文章里<用规则做命名实体识别--NER系列(一)>,介绍了最简单的做命名实体识别的方法–规则.这一篇,我们循序渐进,继续介绍下一个模型--隐马尔可夫模型. 隐马尔可夫模型,看上去,和 ...
- 隐马尔可夫模型HMM学习备忘
隐马尔可夫模型HMM学习备忘 目录 隐马尔可夫模型HMM学习备忘 1.马尔可夫模型的理解 2.隐马尔可夫模型 2.1.HHM的组成 2.2.HMM解决的三个基本问题 隐马尔可夫模型示意图如图[1]: ...
- 《两日算法系列》之第四篇:隐马尔可夫模型HMM
目录 1. 定义与假设 2. 相关概念的表示 3. 三个基本问题 3.1. 概率计算问题 3.2. 学习问题 3.3. 预测问题 总结 1. 定义与假设 李雷雷所在城市的天气有三种情况,分别是:晴天. ...
- 【机器学习算法】隐马尔可夫模型HMM(一)
目录 一.马尔可夫模型 1. 马尔可夫性 2. 马尔可夫链 3. 马尔可夫链案例 二.隐马尔可夫模型HMM 1. named entity recognition(命名实体识别)问题概述 2. 什么是 ...
最新文章
- 大疆车载招聘|SLAM、地图定位、感知算法、机器学习算法工程师
- TreeView获取目录下的所有文件
- 浅析Mysql InnoDB存储引擎事务原理
- saltstack 主题说明
- php 随机颜色,php生成随机颜色的代码实例
- IT永远也不可能做到整体外包,这句话是我说的。。。
- 在PyQt中构建 Python 菜单栏、菜单和工具栏
- 【英语学习】【科学】【Glencoe Science】【B】From Bacteria to Plants 目录及术语表
- 人工智能将是人类最后的需要 | 大咖来了
- C++是C语言演变过来的,为何不能代替C语言?
- 虚拟机下安装BackTrack5 (BT5)教程及BT5汉化
- matlab纹理分析,基于MATLAB的遥感影像纹理特征分析
- 数据分析师面试题目_数据分析师面试|新公布的大数据分析师面试题,这个细节值得被注意...
- php_enchant,Enchant - [ php中文手册 ] - 在线原生手册 - php中文网
- MTK6577+Android之Camera驱动) ~% d
- 【Encoder-Decoder】
- rabbitmq的web管理界面-密码管理
- 实现ISA2004的WPAD(自动发现功能)
- win10 蓝屏问题及解决
- 分享一个简单好用的快递查询、物流管理软件
热门文章
- 敏捷软件开发的12个原则
- [原创]Gerrit中文乱码问题解决方案分享
- ssh-keygen
- Cookie 位置_无需整理
- .net_ckeditor+ckfinder的图片上传配置
- OpenCV编译viz模块
- 转:YUV RGB 常见视频格式解析
- 巧妙使用Firebug插件,快速监控网站打开缓慢的原因
- [转] Gradle: 此时不应有 Androidandroid-studiosdk oolslib\find_java.exe。解决方法
- NEWS - InstallShield 2013 SP1发布