zoukankan      html  css  js  c++  java
  • 隐马尔可夫模型(三)——隐马尔可夫模型的评估问题(前向算法)(转载)

     隐马模型的评估问题即,在已知一个观察序列O=O1O2...OT,和模型μ=(A,B,π}的条件下,观察序列O的概率,即P(O|μ}

                       

          如果穷尽所有的状态组合,即S1S1...S1, S1S1...S2, S1S1...S3, ..., S3S3...S3。这样的话t1时刻有N个状态,t2时刻有N个状态...tT时刻有N个状态,这样的话一共有N*N*...*N= NT种组合,时间复杂度为O(NT),计算时,就会出现“指数爆炸”,当T很大时,简直无法计算这个值。为解决这一问题,Baum提出了前向算法。

          归纳过程

          首先引入前向变量αt(i):在时间t时刻,HMM输出序列为O1O2...OT,在第t时刻位于状态si的概率。

          当T=1时,输出序列为O1,此时计算概率为P(O1|μ):假设有三个状态(如下图)1、2、3,输出序列为O1,有三种可能一是状态1发出,二是从状态2发出,三是从状态3发出。另外从状态1发出观察值O1得概率为b1(O1),从状态2发出观察值O1得概率为b2(O1),从状态3发出观察值O1得概率为b3(O1)。因此可以算出

         P(O1|μ)= π1*b1(O1)+π2*b2(O1) +  π3*b3(O1)= α1(1) + α1(2) + α1(3)

                                         

          当T=2时,输出序列为O1O2,此时计算概率为P(O1O2|μ):假设有三个状态(如下图)1、2、3,输出序列为O1,有三种可能一是状态1发出,二是从状态2发出,三是从状态3发出。另外从状态1发出观察值O2得概率为b1(O2),从状态2发出观察值O2得概率为b2(O2),从状态3发出观察值O2得概率为b3(O2)。

          要是从状态1发出观察值O2,可能从第一时刻的1、2或3状态装换过来,要是从状态1转换过来,概率为α1(1)*a11*b1(O2),要是从状态2转换过来,概率为α1(2)*a21*b1(O2),要是从状态3转换过来,概率为α1(3)*a31*b1(O2),因此

         P(O1O2,q2=s1|μ)= α1(1)*a11*b1(O2)  + α1(2)*a21*b1(O2) + α1(3)*a31*b1(O2)=α2(1)

                                         

          同理:P(O1O2,q2=s1|μ)= α1(1)*a12*b2(O2)  + α1(2)*a22*b2(O2) + α1(3)*a32*b2(O2)=α2(2)

                   P(O1O2,q2=s1|μ)= α1(1)*a13*b1(O2)  + α1(2)*a23*b3(O2) + α1(3)*a33*b3(O2)=α2(3)

         所以:P(O1O2|μ)=P(O1O2,q2=s1|μ)+ P(O1O2,q2=s1|μ)+ P(O1O2,q2=s1|μ)

                                 =α2(1) + α2(2) + α2(3)

          以此类推。。。

          前向算法

           step1 初始化:α1(i) = πi*bi(O1), 1≤i≤N

           step2 归纳计算:

                               

           step3 终结:

                          P(O|μ)=

          时间复杂度

          计算某时刻的某个状态的前向变量需要看前一时刻的N个状态,此时时间复杂度为O(N),每个时刻有N个状态,此时时间复杂度为N*O(N)=O(N2),又有T个时刻,所以时间复杂度为T*O(N2)=O(N2T)。

          程序例证

           

            前向算法计算P(O|M):

            step1:α1(1) =π1*b1(red)=0.2*0.5=0.1          α1(2)=π2*b2(red)==0.4*0.4= 0.16          α1(3)=π3*b3(red)==0.4*0.7=0.21

            step2:α2(1)=α1(1)*a11*b1(white) + α1(2)*a21*b1(white) + α1(3)*a31*b1(white)

                         ...

            step3:P(O|M) = α3(1)+α3(2)+α3(3)

            程序代码

    复制代码
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main()
    {
            float a[3][3] = {{0.5,0.2,0.3},{0.3,0.5,0.2},{0.2,0.3,0.5}};
            float b[3][2] = {{0.5,0.5},{0.4,0.6},{0.7,0.3}};
            float alpha[4][3];
            int i,j,k, count = 1;
            //output list
            int list[4] = {0,1,0,1};
            //step1:Initialization
            alpha[0][0] = 0.2 * 0.5;
            alpha[0][1] = 0.4 * 0.4;
            alpha[0][2] = 0.4 * 0.7;
            //step2:iteration
            for (i=1; i<=3; i++)
            {
                for(j=0; j<=2; j++)
                {
                    alpha[i][j] = 0;
                    for(k=0; k<=2; k++)
                    {
                       alpha[i][j] += alpha[i-1][k] * a[k][j] * b[j][list[count]];
                    }
                }
                count += 1;
            }
           for (i=0; i<=3; i++)
            {
                for(j=0; j<=2; j++)
                {
                    printf("a[%d][%d]=%f
    ",i+1,j+1,alpha[i][j]);
                }
            }
           //step3:end
           printf("Forward:%f
    ", alpha[3][0]+alpha[3][1]+alpha[3][2]);
           return 0;
    }
    复制代码

         运行结果

                     

  • 相关阅读:
    P1093 奖学金
    华容道
    回文数
    P1654 OSU!
    Noip P1063 能量项链
    Noip 寻宝
    NOIP 2009 普及组 第三题 细胞分裂
    拦截器
    OGNL
    Struts2 配置详解
  • 原文地址:https://www.cnblogs.com/jason-wyf/p/6219105.html
Copyright © 2011-2022 走看看