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笔记(2)
Oct 24 Python
python 回调函数和回调方法的实现分析
Mar 23 Python
Windows 7下Python Web环境搭建图文教程
Mar 20 Python
Python使用cx_Oracle模块操作Oracle数据库详解
May 07 Python
PyQt5通信机制 信号与槽详解
Aug 07 Python
使用Python生成200个激活码的实现方法
Nov 22 Python
Python HTMLTestRunner可视化报告实现过程解析
Apr 10 Python
Mac PyCharm中的.gitignore 安装设置教程
Apr 16 Python
Keras 加载已经训练好的模型进行预测操作
Jun 17 Python
python实现单机五子棋
Aug 28 Python
在pyCharm中下载第三方库的方法
Apr 18 Python
Python帮你解决手机qq微信内存占用太多问题
Feb 15 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 按指定元素值去除数组元素的实现方法
2011/11/04 PHP
PHP实现手机号码中间四位用星号(*)隐藏的自定义函数分享
2014/09/27 PHP
PHP 匿名函数与注意事项详细介绍
2016/11/26 PHP
五个jQuery图片画廊插件 推荐
2011/05/12 Javascript
在jquery boxy中添加百度地图坐标拾取注意流程
2014/04/03 Javascript
js弹出对话框方式小结
2015/11/17 Javascript
jQuery拖动元素并对元素进行重新排序
2015/12/30 Javascript
js获取所有checkbox的值的简单实例
2016/05/30 Javascript
jQuery购物车插件jsorder用法(支持后台处理程序直接转换成DataTable处理)
2016/06/08 Javascript
BootStrapTable服务器分页实例解析
2016/12/20 Javascript
完美解决input[type=number]无法显示非数字字符的问题
2017/02/28 Javascript
jQuery+pjax简单示例汇总
2017/04/21 jQuery
详谈AngularJs 控制器、数据绑定、作用域
2017/07/09 Javascript
在Vue组件中使用 TypeScript的方法
2018/02/28 Javascript
vue.js 使用axios实现下载功能的示例
2018/03/05 Javascript
webpack多入口多出口的实现方法
2018/08/17 Javascript
6行代码实现微信小程序页面返回顶部效果
2018/12/28 Javascript
微信小程序封装的HTTP请求示例【附升级版】
2019/05/11 Javascript
Python中文编码那些事
2014/06/25 Python
PyQt5 QSerialPort子线程操作的实现
2018/04/21 Python
Python get获取页面cookie代码实例
2018/09/12 Python
pycharm执行python时,填写参数的方法
2018/10/29 Python
pygame游戏之旅 载入小车图片、更新窗口
2018/11/20 Python
Python3.5面向对象与继承图文实例详解
2019/04/24 Python
Python django框架应用中实现获取访问者ip地址示例
2019/05/17 Python
Django中使用CORS实现跨域请求过程解析
2019/08/05 Python
python网络编程 使用UDP、TCP协议收发信息详解
2019/08/29 Python
如何在mac环境中用python处理protobuf
2019/12/25 Python
如何使用Pytorch搭建模型
2020/10/26 Python
查询优化的一般准则有哪些
2015/03/08 面试题
求职信格式要求
2014/05/23 职场文书
本科应届生自荐信
2014/06/29 职场文书
学习焦裕禄同志为人民服务思想汇报
2014/09/10 职场文书
小学班主任事迹材料
2014/12/17 职场文书
项目投资意向书范本
2015/05/09 职场文书
2015年教务处干事工作总结
2015/07/22 职场文书