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实现简单的获取图片爬虫功能示例
Jul 12 Python
详解Python中 sys.argv[]的用法简明解释
Dec 20 Python
使用Python实现跳一跳自动跳跃功能
Jul 10 Python
Python 实例方法、类方法、静态方法的区别与作用
Aug 14 Python
Python字符串中删除特定字符的方法
Jan 15 Python
python环境下安装opencv库的方法
Mar 05 Python
Python如何使用ElementTree解析xml
Oct 12 Python
Django实现简单的分页功能
Feb 22 Python
golang特有程序结构入门教程
Jun 02 Python
python 中yaml文件用法大全
Jul 04 Python
python​格式化字符串
Apr 20 Python
深入理解pytorch库的dockerfile
Jun 10 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制作简单的内容采集器的代码
2007/11/28 PHP
如何获知PHP程序占用多少内存(memory_get_usage)
2012/09/23 PHP
神盾加密解密教程(三)PHP 神盾解密工具
2014/06/08 PHP
php判断文件上传类型及过滤不安全数据的方法
2014/12/17 PHP
深入理解PHP中的Streams工具
2015/07/03 PHP
Zend Framework生成验证码并实现验证码验证功能(附demo源码下载)
2016/03/22 PHP
不错的JS中变量相关的细节分析
2007/08/13 Javascript
Domino中运用jQuery读取视图内容的方法
2009/10/21 Javascript
关于jQuery UI 使用心得及技巧
2012/10/10 Javascript
网页中返回顶部代码(多种方法)另附注释说明
2013/04/24 Javascript
文本框文本自动补全效果示例分享
2014/01/19 Javascript
浅谈setTimeout 与 setInterval
2015/06/23 Javascript
Javascript字符串常用方法详解
2016/07/21 Javascript
Mac系统下Webstorm快捷键整理大全
2017/05/28 Javascript
js学使用setTimeout实现轮循动画
2017/07/17 Javascript
es7学习教程之Decorators(修饰器)详解
2017/07/21 Javascript
详解Vue.js使用Swiper.js在iOS
2018/09/10 Javascript
详解Angular5/Angular6项目如何添加热更新(HMR)功能
2018/10/10 Javascript
mockjs+vue页面直接展示数据的方法
2018/12/19 Javascript
Vue的路由及路由钩子函数的实现
2019/07/02 Javascript
JavaScript ECMA-262-3 深入解析(二):变量对象实例详解
2020/04/25 Javascript
[14:21]VICI vs EG (BO3)
2018/06/07 DOTA
python encode和decode的妙用
2009/09/02 Python
CentOS 6.X系统下升级Python2.6到Python2.7 的方法
2016/10/12 Python
Python金融数据可视化汇总
2017/11/17 Python
Python实现针对json中某个关键字段进行排序操作示例
2018/12/25 Python
django ModelForm修改显示缩略图 imagefield类型的实例
2019/07/28 Python
对python中arange()和linspace()的区别说明
2020/05/03 Python
详解Django自定义图片和文件上传路径(upload_to)的2种方式
2020/12/01 Python
外贸公司实习自我鉴定
2013/09/24 职场文书
法院反腐倡廉心得体会
2014/09/09 职场文书
社会体育专业大学生职业生涯规划书
2014/09/17 职场文书
2014民事授权委托书范本
2014/09/29 职场文书
2015迎新晚会开场白
2015/05/29 职场文书
处罚决定书范文
2015/06/24 职场文书
Python数组变形的几种实现方法
2022/05/30 Python