机器学习笔记之隐马尔科夫模型(四)

预测算法

1.1 近似算法

近似算法的想法是,在每个时刻 t 选择在该时刻最有可能出现的状态 it, 从而得到一个状态序列 I=(i1,i2,,iT) ,将它作为预测的结果.

给定隐马尔科夫模型 λ 和观测序列 O ,在时刻 t 处于状态 qi 的概率 γt(i) 是:

γt(i)=αt(i)βt(i)P(O|λ)=αt(i)βt(i)Nj=1αt(j)βt(j)

在每一时刻 t 最有可能的状态 it

it=argmax1iN[γt(i)],t=1,2,,T

从而得到状态序列 I=(i1,i2,,iT)

近似算法的优点是计算简单,其缺点是不能保障预测的状态序列整体是最有可能的状态序列,因为预测的状态序列可能有实际不发生的部分。事实上,上述方法得到的状态序列有可能存在转移概率为 0 的相邻状态,即对某些 i,j,aij=0 时,尽管如此,近似算法仍然是有用的。

1.2 维特比算法(Viterbi algorithm)

维特比算法实际是用动态规划解隐马尔科夫模型预测问题,即用动态规划求概率最大路径,这时一条路径对应着一个状态序列。

最优路径有这样的特性:如果最优路径在时刻 t 通过结点 it, 那么这一条路径从结点 it 到终点 iT 的部分路径,对于从 it iT 的所有可能的部分路径来说,必须是最优的。因为如果不是这样的话,那么就会存在另外一条比当前更优的路径,这样的话,和之前定义的最优路径相矛盾了。
根据动态规划的原理,我们只需从时刻 t=1 开始,递推地计算在时刻 t 状态为 i 的各部分路径的最大概率,直至得到时刻 t=T 状态为 i 的各条路径的最大概率。时刻 t=T 的最大概率即为最优路径的概率 P , 最优路径的终结点 iT 也同时得到。之后,为了找出最优路径的各个结点,从终结点 iT 开始,由后向前逐步求得 iT1,,i1 ,就得到了最优路径 I ,这就是维特比算法的思想

首先,导入两个变量 δ ψ , 定义在时刻 t 状态为 i 的所有单个路径 (i1,i2,,iT) 中概率的最大值为:

δt+1(i)=maxi1,i2,,iTP(it=i,it1,,i1,ot,,o1|λ)

由定义知:
δt+1(i)=max1jN[δt(j)aji]bi(ot+1)

定义在时刻 t 状态为 i的所有单个路径 (i1,i2,,it1,i) 中概率最大的路径的第 t1 个结点为:

ψt(i)=argmax1jN[δt1(j)aji],i=1,2,,N

具体过程为:

输入: 模型 λ=(A,B,π) 和观测 O=(o1,o2,,oT)
输出: 最优路径 I=(i1,,iT)

  1. 初始化:

    δ1(i)=πibi(o1),i=1,2,,N

    ψ1(i)=0,i=1,2,,N

  2. 递推,对 t=2,3,,T

δt(i)=maxijN[δt1aji]bi(ot),i=1,2,,N

ψt(i)=argmax1jN[δt1(j)aji],i=1,2,,N

  1. 终止

    P=max1iNδT(i)

    iT=argmax1iN[δT(i)]

  2. 最优路径的回溯,对 t=T1,T2,,1

it=ψt+1(it+1)

参考《统计学方法》上面的例题,写了一个代码如下

#include<iostream>
#include<cmath>
#include<vector>
#include<string>
#include<sstream>
#include<cstring>
#include<algorithm>


using namespace std;


int main()
{

  double A[3][3] = {0.5,0.2,0.3,0.3,0.5,0.2,0.2,0.3,0.5};

  double B[3][2] = {0.5,0.5,0.4,0.6,0.7,0.3};

  double pi[3] = {0.2,0.4,0.4};

  double sigma[3][3];

  int psi[3][3];

  int O[3] = {0,1,0};

  int T = 3;

  for (int i = 0; i < 3; ++i) {
    sigma[0][i] = pi[i]*B[i][O[0]];
  }

  vector<int>path;
  int best = 0;
  for (int t = 1; t < T; ++t) {
    for (int i = 0; i < 3; ++i) {
      for (int j = 0; j < 3; ++j) {
         if (sigma[t][i] < sigma[t-1][j]*A[j][i]*B[i][O[t]]) {
              sigma[t][i] = sigma[t-1][j] * A[j][i] * B[i][O[t]];
              psi[t][i] = j;
              best = j;
         }
      }
    }
  }

  for (int i = 2; i >= 0; --i) {
    cout<<best+1<<' ';
    best = psi[i][best];
  }
  cout<<endl;
  cout<<"**********"<<endl;

  for (int i = 0; i < 3; ++i) {
    for (int j = 0; j < 3; ++j)
      cout<<sigma[i][j]<<' ';
    cout<<endl;
  }




  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值