隐马尔可夫模型问题有3个,即评估、解码、学习。其中评估问题描述为给定一个隐马尔可夫模型参数和一个观察序列,求该观察序列的概率。我们使用前向算法(forward algorith)来解决这个问题。其c代码如下:

hmm.h文件


#ifndef _HMM_H_

#define _HMM_H_


//宏定义

#define NN 3

#define MM 4

#define length 3


typedef struct {

int N;  /* 隐藏状态数目;Q={0,1,2,…,N-1} */

int M; /* 观察符号数目; V={0,1,2,…,M-1}*/


/* 状态转移矩阵A[0..NN-1][0..NN-1]. a[i][j] 是从t时刻状态i到t+1时刻状态j的转移概率 */

double(*A)[NN] ;  


/* 混淆矩阵B[0..N-1][0..M-1]. b[j][k]在状态j时观察到符合k的概率。*/

double(*B)[MM];


/* 初始向量pi[0..N-1],pi[i] 是初始状态概率分布 */

double*pi;

} HMM;


double Forward(HMM *phmm,int T,int *O);


#endif



hmm.c文件

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
#include "hmm.h"

/*
 函数参数说明:
 *phmm:已知的HMM模型;T:观察符号序列长度;*O:观察序列;
*/
double alpha[length][NN];     //前向算法局部概率变量

double Forward(HMM *phmm,int T,int *O)
{
       int     i, j;     /* 状态索引 */
       int     t;        /* 时间索引 */
double sum;     /*求局部概率时的中间值 */  
double pprob;//返回的值

 /* 1. 初始化:计算t=0时刻所有状态的局部概率alpha: */
       for (i = 0; i <= (phmm->N)-1; i++)
               alpha[0][i] = phmm->pi[i]* phmm->B[i][O[0]];

         /* 2. 归纳:递归计算每个时间点,t=2,… ,T时的局部概率 */

       for (t = 0; t < T-1; t++) //这循环里算T-1次,前面初始化算了1次,共T次
{
               for (j = 0; j <= (phmm->N)-1; j++) //在给定的时刻,所有状态分别到其他所有状态的转移概率之和
{
                       sum = 0.0;
                       for (i = 0; i <= (phmm->N)-1; i++)//在给定的时刻和给定状态,其他所有状态到给定状态的转移概率之和
{
sum += alpha[t][i]* (phmm->A[i][j]);
}                                
                       alpha[t+1][j] = sum*(phmm->B[j][O[t+1]]);//计算t+1时刻看到观察序号O[t+1]的所有状态的局部概率alpha
               }
       }

        /* 3. 终止:观察序列的概率等于T时刻所有局部概率之和*/
       pprob = 0.0;
       for (i = 0; i <= (phmm->N)-1; i++)
               pprob += alpha[T-1][i];
return pprob;
}

main.c文件

#include <stdio.h>
#include <stdlib.h>
#include "hmm.h"

double A[NN][NN]={              
                {0.500,0.375,0.125},
    {0.250,0.125,0.625},
    {0.250,0.375,0.375}
              };
double B[NN][MM]={              
                  {0.60,0.20,0.15,0.05},
          {0.25,0.25,0.25,0.25},
          {0.05,0.10,0.35,0.50}
               };
double pi[NN]={0.63,0.17,0.20};

HMM hmm1={NN,MM,A,B,pi};

int Seq[length]={0,2,3};

int main(int argc, char *argv[])
{  
 double pprob=0.0;
     pprob = Forward(&hmm1, length, Seq);
 printf("the probabilty of observing a sequence given a HMM model parameter:\n");
 printf("%.12f\n",pprob);
}


运行结果如下:

the probabilty of observing a sequence given a HMM model parameter:

0.026901406250

请按任意键继续...