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 19 Python
python3.5 + PyQt5 +Eric6 实现的一个计算器代码
Mar 11 Python
Python实现的中国剩余定理算法示例
Aug 05 Python
Python通过future处理并发问题
Oct 17 Python
用Python写脚本,实现完全备份和增量备份的示例
Apr 29 Python
Python面向对象程序设计类的多态用法详解
Apr 12 Python
Django后端接收嵌套Json数据及解析详解
Jul 17 Python
python 单线程和异步协程工作方式解析
Sep 28 Python
python3 实现调用串口功能
Dec 26 Python
Python通过VGG16模型实现图像风格转换操作详解
Jan 16 Python
python实现扫雷游戏
Mar 03 Python
python中count函数知识点浅析
Dec 17 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大文件切割上传并带进度条功能示例
2019/07/01 PHP
Mootools 1.2教程 滑动效果(Slide)
2009/09/15 Javascript
jQeury淡入淡出需要注意的问题
2010/09/08 Javascript
IE与FireFox中的childNodes区别
2011/10/20 Javascript
javascript模拟select,jselect的方法实现
2012/11/08 Javascript
jQuery焦点控制图层展示延迟隐藏的方法
2015/03/09 Javascript
浅谈JavaScript正则表达式分组匹配
2015/04/10 Javascript
iframe中子父类窗口调用JS的方法及注意事项
2015/08/25 Javascript
fastclick插件导致日期(input[type="date"])控件无法被触发该如何解决
2015/11/09 Javascript
AngularJS深入探讨scope,继承结构,事件系统和生命周期
2016/11/02 Javascript
jQuery实现的无缝广告图片左右滚动功能详解
2016/12/24 Javascript
jQuery html表格排序插件tablesorter使用方法详解
2017/02/10 Javascript
求js数组的最大值和最小值的四种方法
2017/03/03 Javascript
解决Vue不能检测数组或对象变动的问题
2018/02/24 Javascript
vue 中动态绑定class 和 style的方法代码详解
2018/06/01 Javascript
node app 打包工具pkg的具体使用
2019/01/17 Javascript
vue props对象validator自定义函数实例
2019/11/13 Javascript
原生js实现点击轮播切换图片
2020/02/11 Javascript
vue 实现锚点功能操作
2020/08/10 Javascript
详解Vue的组件中data选项为什么必须是函数
2020/08/17 Javascript
详解React的回调渲染模式
2020/09/10 Javascript
Vue中ref和$refs的介绍以及使用方法示例
2021/01/11 Vue.js
[01:01]青春无憾,一战成名——DOTA2全国高校联赛开启
2018/02/25 DOTA
python中精确输出JSON浮点数的方法
2014/04/18 Python
python中前缀运算符 *和 **的用法示例详解
2020/05/28 Python
pyspark对Mysql数据库进行读写的实现
2020/12/30 Python
实例讲解CSS3中的border-radius属性
2015/08/18 HTML / CSS
html5 canvas绘制网络字体的常用方法
2019/08/26 HTML / CSS
德国EGOIST网店:销售畅销的设计师品牌
2017/04/18 全球购物
戴森台湾线上商城:Dyson Taiwan
2018/05/21 全球购物
经济学人订阅:The Economist
2018/07/19 全球购物
日语专业毕业生自荐书
2014/06/18 职场文书
毕业论文致谢范文
2015/05/14 职场文书
2016父亲节感恩话语
2015/12/09 职场文书
大学生暑期实践报告之企业经营管理
2019/08/08 职场文书
各国货币符号大全
2022/02/17 杂记