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合并两个字典的常用方法与效率比较
Jun 17 Python
Python实现信用卡系统(支持购物、转账、存取钱)
Jun 24 Python
python 打印出所有的对象/模块的属性(实例代码)
Sep 11 Python
python opencv之SURF算法示例
Feb 24 Python
分分钟入门python语言
Mar 20 Python
Python实现基于TCP UDP协议的IPv4 IPv6模式客户端和服务端功能示例
Mar 22 Python
基于pandas数据样本行列选取的方法
Apr 20 Python
Python读取stdin方法实例
May 24 Python
Python实现动态给类和对象添加属性和方法操作示例
Feb 29 Python
Python3.7 读取音频根据文件名生成脚本的代码
Apr 07 Python
python使用nibabel和sitk读取保存nii.gz文件实例
Jul 01 Python
python 基于opencv实现高斯平滑
Dec 18 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
15种PHP Encoder的比较
2007/03/06 PHP
php面向对象的方法重载两种版本比较
2008/09/08 PHP
php empty()与isset()区别的详细介绍
2013/06/17 PHP
PHP+redis实现的购物车单例类示例
2019/02/02 PHP
PHP中quotemeta()函数的用法讲解
2019/04/04 PHP
HTML页面如何象ASP一样接受参数
2007/02/07 Javascript
跟我学习javascript的全局变量
2015/11/16 Javascript
jQuery模仿单选按钮选中效果
2016/06/24 Javascript
AngularJS过滤器filter用法总结
2016/12/13 Javascript
jquery+html仿翻页相册功能
2016/12/20 Javascript
浅谈Angular.js中使用$watch监听模型变化
2017/01/10 Javascript
浅谈Vue.js
2017/03/02 Javascript
解决JavaScript layui 下拉框不显示的问题
2018/08/14 Javascript
node.js 模块和其下载资源的镜像设置的方法
2018/09/06 Javascript
Javascript 模拟mvc实现点餐程序案例详解
2020/12/24 Javascript
[38:23]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第一场
2014/05/24 DOTA
[45:18]完美世界DOTA2联赛循环赛 PXG vs IO 第二场 11.06
2020/11/09 DOTA
[52:02]DOTA2-DPC中国联赛 正赛 Phoenix vs Dragon BO3 第二场 2月26日
2021/03/11 DOTA
Python运用于数据分析的简单教程
2015/03/27 Python
Python实现的微信公众号群发图片与文本消息功能实例详解
2017/06/30 Python
使用python实现链表操作
2018/01/26 Python
Python随机函数random()使用方法小结
2018/04/29 Python
Python Selenium参数配置方法解析
2020/01/19 Python
python轮询机制控制led实例
2020/05/03 Python
python转化excel数字日期为标准日期操作
2020/07/14 Python
李宁官方网店:中国运动品牌
2017/11/02 全球购物
巴西香水和化妆品购物网站:The Beauty Box
2019/09/03 全球购物
ParcelABC西班牙:包裹运送和快递服务
2019/12/24 全球购物
澳大利亚人信任的清洁平台,您的私人管家:Jarvis
2020/12/25 全球购物
什么是数组名
2012/05/10 面试题
求职信内容怎么写
2014/05/26 职场文书
保险公司开门红口号
2014/06/21 职场文书
努力学习保证书
2015/02/26 职场文书
加薪通知
2015/04/25 职场文书
如何用PHP实现分布算法之一致性哈希算法
2021/05/26 PHP
Python 中的单分派泛函数你真的了解吗
2021/06/22 Python