隐马尔可夫模型问题有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"/* 函数参数说明:<br> *phmm:已知的HMM模型;T:观察符号序列长度;*O:观察序列;<br>*/<br>
double alpha[length][NN]; //前向算法局部概率变量<br><br>double Forward(HMM *phmm,int T,int *O)<br>{<br> int i, j; /* 状态索引 */<br> int t; /* 时间索引 */<br> double sum; /*求局部概率时的中间值 */ <br> double pprob;//返回的值<br><br> /* 1. 初始化:计算t=0时刻所有状态的局部概率alpha: */<br> for (i = 0; i <= (phmm->N)-1; i++)<br> alpha[0][i] = phmm->pi[i]* phmm->B[i][O[0]];<br><br> /* 2. 归纳:递归计算每个时间点,t=2,… ,T时的局部概率 */<br><br> for (t = 0; t < T-1; t++) //这循环里算T-1次,前面初始化算了1次,共T次<br> {<br> for (j = 0; j <= (phmm->N)-1; j++) //在给定的时刻,所有状态分别到其他所有状态的转移概率之和<br> {<br> sum = 0.0;<br> for (i = 0; i <= (phmm->N)-1; i++)//在给定的时刻和给定状态,其他所有状态到给定状态的转移概率之和<br> {<br> sum += alpha[t][i]* (phmm->A[i][j]);<br> } <br> alpha[t+1][j] = sum*(phmm->B[j][O[t+1]]);//计算t+1时刻看到观察序号O[t+1]的所有状态的局部概率alpha<br> }<br> }<br><br> /* 3. 终止:观察序列的概率等于T时刻所有局部概率之和*/<br> pprob = 0.0;<br> for (i = 0; i <= (phmm->N)-1; i++)<br> pprob += alpha[T-1][i];<br> return pprob;<br>}
main.c文件
#include <stdio.h><br>#include <stdlib.h><br>#include "hmm.h"<br><br>double A[NN][NN]={ <br> {0.500,0.375,0.125},<br> {0.250,0.125,0.625},<br> {0.250,0.375,0.375}<br> };<br>double B[NN][MM]={ <br> {0.60,0.20,0.15,0.05},<br> {0.25,0.25,0.25,0.25},<br> {0.05,0.10,0.35,0.50}<br> };<br>double pi[NN]={0.63,0.17,0.20};<br><br>HMM hmm1={NN,MM,A,B,pi};<br><br>int Seq[length]={0,2,3};<br><br>int main(int argc, char *argv[])<br>{ <br> double pprob=0.0;<br> pprob = Forward(&hmm1, length, Seq); <br> printf("the probabilty of observing a sequence given a HMM model parameter:\n");<br> printf("%.12f\n",pprob);<br>}
运行结果如下:
the probabilty of observing a sequence given a HMM model parameter:
0.026901406250