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连接MySQL、MongoDB、Redis、memcache等数据库的方法
Nov 15 Python
python中matplotlib的颜色及线条控制的示例
Mar 16 Python
Python用csv写入文件_消除空余行的方法
Jul 06 Python
Tensorflow加载预训练模型和保存模型的实例
Jul 27 Python
numpy和pandas中数组的合并、拉直和重塑实例
Jun 28 Python
详解将Pandas中的DataFrame类型转换成Numpy中array类型的三种方法
Jul 06 Python
python 的 scapy库,实现网卡收发包的例子
Jul 23 Python
多版本python的pip 升级后, pip2 pip3 与python版本失配解决方法
Sep 11 Python
python 监测内存和cpu的使用率实例
Nov 28 Python
python爬虫开发之使用Python爬虫库requests多线程抓取猫眼电影TOP100实例
Mar 10 Python
Python调用高德API实现批量地址转经纬度并写入表格的功能
Jan 12 Python
Python 数据结构之十大经典排序算法一文通关
Oct 16 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
利用ThinkPHP内置的ThinkAjax实现异步传输技术的实现方法
2011/12/19 PHP
简述php环境搭建与配置
2016/12/05 PHP
php readfile下载大文件失败的解决方法
2017/05/22 PHP
Laravel 中创建 Zip 压缩文件并提供下载的实现方法
2019/04/02 PHP
PHP使用POP3读取邮箱接收邮件的示例代码
2020/07/08 PHP
JS正则中的RegExp对象对象
2012/11/07 Javascript
js限制文本框输入长度两种限制方式(长度、字节数)
2012/12/19 Javascript
JavaScript分析、压缩工具JavaScript Analyser
2014/12/31 Javascript
JavaScript实现删除,移动和复制文件的方法
2015/08/05 Javascript
使用InstantClick.js让页面提前加载200ms
2017/09/12 Javascript
解决antd 表单设置默认值initialValue后验证失效的问题
2020/11/02 Javascript
[44:40]KG vs LGD 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
详解Python中的__init__和__new__
2014/03/12 Python
Python编写登陆接口的方法
2017/07/10 Python
详解Python判定IP地址合法性的三种方法
2018/03/06 Python
Python3.5.3下配置opencv3.2.0的操作方法
2018/04/02 Python
使用Python实现在Windows下安装Django
2018/10/17 Python
python 五子棋如何获得鼠标点击坐标
2019/11/04 Python
基于MSELoss()与CrossEntropyLoss()的区别详解
2020/01/02 Python
解决python图像处理图像赋值后变为白色的问题
2020/06/04 Python
Python基于pyjnius库实现访问java类
2020/07/31 Python
python 中的命名空间,你真的了解吗?
2020/08/19 Python
详解CSS3 Media Queries中媒体属性的使用
2016/02/29 HTML / CSS
沙龙级头发造型工具:FOXYBAE
2018/07/01 全球购物
Public Desire美国/加拿大:全球性的在线鞋类品牌
2018/12/17 全球购物
zooplus德国:便宜地订购动物用品、动物饲料、动物食品
2020/05/06 全球购物
经典优秀毕业生求职信范文分享
2013/12/18 职场文书
建筑文秘专业个人求职信范文
2013/12/28 职场文书
和平主题的演讲稿
2014/01/12 职场文书
个人求职自荐信范文
2014/06/20 职场文书
捐书倡议书
2014/08/29 职场文书
使用Django实现商城验证码模块的方法
2021/06/01 Python
小程序实现文字循环滚动动画
2021/06/14 Javascript
Nginx缓存设置案例详解
2021/09/15 Servers
Java版 简易五子棋小游戏
2022/05/04 Java/Android
JavaScript架构localStorage特殊场景下二次封装操作
2022/06/21 Javascript