Python实现隐马尔可夫模型的前向后向算法的示例代码


Posted in Python onDecember 31, 2019

本篇文章对隐马尔可夫模型的前向和后向算法进行了Python实现,并且每种算法都给出了循环和递归两种方式的实现。

前向算法Python实现

循环方式

import numpy as np
def hmm_forward(Q, V, A, B, pi, T, O, p):
  """
  :param Q: 状态集合
  :param V: 观测集合
  :param A: 状态转移概率矩阵
  :param B: 观测概率矩阵
  :param pi: 初始概率分布
  :param T: 观测序列和状态序列的长度
  :param O: 观测序列
  :param p: 存储各个状态的前向概率的列表,初始为空
  """
  for t in range(T):
    # 计算初值
    if t == 0:
      for i in range(len(Q)):
        p.append(pi[i] * B[i, V[O[0]]])
    # 初值计算完毕后,进行下一时刻的递推运算
    else:
      alpha_t_ = 0
      alpha_t_t = []
      for i in range(len(Q)):
        for j in range(len(Q)):
          alpha_t_ += p[j] * A[j, i]
        alpha_t_t.append(alpha_t_ * B[i, V[O[t]]])
        alpha_t_ = 0
      p = alpha_t_t
  return sum(p)
# 《统计学习方法》书上例10.2
Q = [1, 2, 3]
V = {'红':0, '白':1}
A = np.array([[0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5]])
B = np.array([[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]])
pi = [0.2, 0.4, 0.4]
T = 3
O = ['红', '白', '红']
p = []
print(hmm_forward(Q, V, A, B, pi, T, O, p)) # 0.130218

递归方式

import numpy as np
def hmm_forward_(Q, V, A, B, pi, T, O, p, T_final):
  """
  :param T_final:递归的终止条件
  """
  if T == 0:
    for i in range(len(Q)):
      p.append(pi[i] * B[i, V[O[0]]])
  else:
    alpha_t_ = 0
    alpha_t_t = []
    for i in range(len(Q)):
      for j in range(len(Q)):
        alpha_t_ += p[j] * A[j, i]
      alpha_t_t.append(alpha_t_ * B[i, V[O[T]]])
      alpha_t_ = 0
    p = alpha_t_t
  if T >= T_final:
    return sum(p)
  return hmm_forward_(Q, V, A, B, pi, T+1, O, p, T_final)

Q = [1, 2, 3]
V = {'红':0, '白':1}
A = np.array([[0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5]])
B = np.array([[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]])
pi = [0.2, 0.4, 0.4]
T = 0
O = ['红', '白', '红']
p = []
T_final = 2 # T的长度是3,T的取值是(0时刻, 1时刻, 2时刻)
print(hmm_forward_(Q, V, A, B, pi, T, O, p, T_final))

后向算法Python实现

循环方式

import numpy as np
def hmm_backward(Q, V, A, B, pi, T, O, beta_t, T_final):
  for t in range(T, -1, -1):
    if t == T_final:
      beta_t = beta_t
    else:
      beta_t_ = 0
      beta_t_t = []
      for i in range(len(Q)):
        for j in range(len(Q)):
          beta_t_ += A[i, j] * B[j, V[O[t + 1]]] * beta_t[j]
        beta_t_t.append(beta_t_)
        beta_t_ = 0
      beta_t = beta_t_t
    if t == 0:
      p=[]
      for i in range(len(Q)):
        p.append(pi[i] * B[i, V[O[0]]] * beta_t[i])
      beta_t = p
  return sum(beta_t)
# 《统计学习方法》课后题10.1
Q = [1, 2, 3]
V = {'红':0, '白':1}
A = np.array([[0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5]])
B = np.array([[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]])
pi = [0.2, 0.4, 0.4]
T = 3
O = ['红', '白', '红', '白']
beta_t = [1, 1, 1]
T_final = 3
print(hmm_backward_(Q, V, A, B, pi, T, O, beta_t, T_final)) # 0.06009

递归方式

import numpy as np
def hmm_backward(Q, V, A, B, pi, T, O, beta_t, T_final):
  if T == T_final:
    beta_t = beta_t
  else:
    beta_t_ = 0
    beta_t_t = []
    for i in range(len(Q)):
      for j in range(len(Q)):
        beta_t_ += A[i, j] * B[j, V[O[T+1]]] * beta_t[j]
      beta_t_t.append(beta_t_)
      beta_t_ = 0
    beta_t = beta_t_t
  if T == 0:
    p=[]
    for i in range(len(Q)):
      p.append(pi[i] * B[i, V[O[0]]] * beta_t[i])
    beta_t = p
    return sum(beta_t)
  return hmm_backward(Q, V, A, B, pi, T-1, O, beta_t, T_final)
jpgQ = [1, 2, 3]
V = {'红':0, '白':1}
A = np.array([[0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5]])
B = np.array([[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]])
pi = [0.2, 0.4, 0.4]
T = 3
O = ['红', '白', '红', '白']
beta_t = [1, 1, 1]
T_final = 3
print(hmm_backward_(Q, V, A, B, pi, T, O, beta_t, T_final)) # 0.06009

这里我有个问题不理解,这道题的正确答案应该是0.061328,我计算出的答案和实际有一点偏差,我跟踪了代码的计算过程,发现在第一次循环完成后,计算结果是正确的,第二次循环后的结果就出现了偏差,我怀疑是小数部分的精度造成,希望有人能给出一个更好的解答,如果是代码的问题也欢迎指正。

以上所述是小编给大家介绍的Python实现隐马尔可夫模型的前向后向算法,希望对大家有所帮助!

Python 相关文章推荐
Python实现对一个函数应用多个装饰器的方法示例
Feb 09 Python
Windows系统下PhantomJS的安装和基本用法
Oct 21 Python
python 输出所有大小写字母的方法
Jan 02 Python
用Python实现将一张图片分成9宫格的示例
Jul 05 Python
33个Python爬虫项目实战(推荐)
Jul 08 Python
Django 在iframe里跳转顶层url的例子
Aug 21 Python
pytorch中获取模型input/output shape实例
Dec 30 Python
python3.7通过thrift操作hbase的示例代码
Jan 14 Python
Python接口测试get请求过程详解
Feb 28 Python
python3发送request请求及查看返回结果实例
Apr 30 Python
Keras自定义实现带masking的meanpooling层方式
Jun 16 Python
python中random模块详解
Mar 01 Python
Python面向对象之私有属性和私有方法应用案例分析
Dec 31 #Python
Pycharm最新激活码2019(推荐)
Dec 31 #Python
python ftplib模块使用代码实例
Dec 31 #Python
深入了解如何基于Python读写Kafka
Dec 31 #Python
Python面向对象之继承原理与用法案例分析
Dec 31 #Python
pytorch中nn.Conv1d的用法详解
Dec 31 #Python
Python实现剪刀石头布小游戏(与电脑对战)
Dec 31 #Python
You might like
PHP遍历数组的几种方法
2012/03/22 PHP
启用Csrf后POST数据时出现的400错误
2015/07/05 PHP
些很实用且必用的小脚本代码
2006/06/26 Javascript
解析js如何获取当前url中的参数值并复制给input
2013/06/23 Javascript
基于JQuery的列表拖动排序实现代码
2013/10/01 Javascript
利用js读取动态网站从服务器端返回的数据
2014/02/10 Javascript
jquery xMarquee实现文字水平无缝滚动效果
2014/04/29 Javascript
基于Jquery和CSS3制作数字时钟附源码下载(CSS3篇)
2015/11/24 Javascript
ES6中如何使用Set和WeakSet
2016/03/10 Javascript
JavaScript中关键字 in 的使用方法详解
2016/10/17 Javascript
div实现自适应高度的textarea实现angular双向绑定
2017/01/08 Javascript
聊聊JavaScript如何实现继承及特点
2017/04/07 Javascript
关于Vue.nextTick()的正确使用方法浅析
2017/08/25 Javascript
jQuery自动或手动图片切换效果
2017/10/11 jQuery
使用Vue开发动态刷新Echarts组件的教程详解
2018/03/22 Javascript
解决layui前端框架 form表单,table表等内置控件不显示的问题
2018/08/19 Javascript
vue 中 beforeRouteEnter 死循环的问题
2019/04/23 Javascript
小程序click-scroll组件设计
2019/06/18 Javascript
vue滚动插件better-scroll使用详解
2019/10/18 Javascript
小程序按钮避免多次调用接口和点击方案实现(不用showLoading)
2020/04/15 Javascript
python 字符串格式化代码
2013/03/17 Python
Python实现模拟登录及表单提交的方法
2015/07/25 Python
Python实现按逗号分隔列表的方法
2018/10/23 Python
对Pyhon实现静态变量全局变量的方法详解
2019/01/11 Python
Python空间数据处理之GDAL读写遥感图像
2019/08/01 Python
Python注释、分支结构、循环结构、伪“选择结构”用法实例分析
2020/01/09 Python
opencv-python的RGB与BGR互转方式
2020/06/02 Python
Pharmacy Online中文直邮网站:澳洲大型药房
2020/06/27 全球购物
行政人员工作职责
2013/12/05 职场文书
汽车维修专业自荐书
2014/05/26 职场文书
开发房地产协议书
2014/09/14 职场文书
秋收起义观后感
2015/06/11 职场文书
CSS3实现的3D隧道效果
2021/04/27 HTML / CSS
python四个坐标点对图片区域最小外接矩形进行裁剪
2021/06/04 Python
Python初学者必备的文件读写指南
2021/06/23 Python
详细聊聊vue中组件的props属性
2021/11/02 Vue.js