⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 baum.cpp

📁 HMM模型的C语言实现
💻 CPP
字号:
/*
**      File:   baumwelch.cpp**      功能:根据给定的观察序列,用BaumWelch算法估计HMM模型参数*/
#include "StdAfx.h"#include <stdio.h> #include "nrutil.h"#include "hmm.h"#include <math.h>#define DELTA 0.001

/******************************************************************************
**函数名称:BaumWelch
**功能:BaumWelch算法
**参数:phmm:HMM模型指针
**      T:观察序列长度
**      O:观察序列
**      alpha,beta,gamma,pniter均为中间变量
**      plogprobinit:初始概率
**      plogprobfinal 最终概率
**/ void BaumWelch(HMM *phmm, int T, int *O, double **alpha, double **beta,
	double **gamma, int *pniter, double *plogprobinit, double *plogprobfinal)
{
	int	i, j, k;
	int	t, l = 0;

	double	logprobf, logprobb;
	double	numeratorA, denominatorA;
	double	numeratorB, denominatorB;	double ***xi, *scale;	double delta, logprobprev;    double	deltaprev = 10e-70;	xi = AllocXi(T, phmm->N);//	scale = dvector(1, T); //申请一个1*T双精度实数数组	ForwardWithScale(phmm, T, O, alpha, scale, &logprobf);
//	Forward( phmm, T, O, alpha,&logprobf );	*plogprobinit =logprobf; /* log P(O |初始状态) */
    *plogprobinit=pow(10,*plogprobinit);//	BackwardWithScale(phmm, T, O, beta, scale, &logprobb);
	Backward(phmm,  T, O, beta,&logprobb);
    double test=logprobb;   //临时加的值,用于测试	ComputeXi(phmm, T, O, alpha, beta, xi);//非用户接口函数
	ComputeGamma(phmm, T,gamma,xi);//非用户接口函数
	logprobprev = logprobf;
	do  {	

		/* 重新估计 t=1 时,状态为i 的频率 */
		for (i = 1; i <= phmm->N; i++) 
		  phmm->pi[i] = .001 + .999*gamma[1][i];    //pi的初始化

		/* 重新估计转移矩阵和观察矩阵 */
		for (i = 1; i <= phmm->N; i++) 
		{ 			denominatorA = 0.0;			for (t = 1; t <= T - 1; t++) 
				denominatorA += gamma[t][i];
			for (j = 1; j <= phmm->N; j++) 
			{				numeratorA = 0.0;				for (t = 1; t <= T - 1; t++) 					numeratorA += xi[t][i][j];				phmm->A[i][j] = .001 + .999*numeratorA/denominatorA;			}			denominatorB = denominatorA + gamma[T][i]; 			for (k = 1; k <= phmm->M; k++) 
			{				numeratorB = 0.0;				for (t = 1; t <= T; t++) 
				{					if (O[t] == k) 						numeratorB += gamma[t][i];				}				phmm->B[i][k] = .001 +						.999*numeratorB/denominatorB;			}		}		ForwardWithScale(phmm, T, O, alpha, scale, &logprobf);		BackwardWithScale(phmm, T, O, beta, scale, &logprobb);
		ComputeXi(phmm, T, O, alpha, beta, xi);		ComputeGamma(phmm, T,gamma,xi);			/* 计算两次直接的概率差 */		delta = logprobf - logprobprev; 		logprobprev = logprobf;		l++;	}	while (delta < DELTA); /* 如果差的不太大,表明收敛,退出 */  	*pniter = l;	*plogprobfinal = logprobf; /* log P(O|estimated model) */	FreeXi(xi, T, phmm->N);	free_dvector(scale, 1, T);}

/************************************************************************
**计算Gamma
***********************************************************************/
void ComputeGamma(HMM *phmm, int T,double **gamma,double ***xi){	int i, j;	int	t;	double	denominator;
	for(t= 1; t <= T; t++)
		for(i = 1;i <= phmm->N; i++)
			gamma[t][i]=0;	for (t = 1; t <= T; t++) 
	{	denominator = 0.0;	for (i = 1;i <= phmm->N; i++) 
		{for(j=1;j<phmm->N;j++)
		    gamma[t][i]+=xi[t][i][j];
		 denominator+=gamma[t][i];				}
	for (i = 1; i <= phmm->N; i++) 			gamma[t][i] = gamma[t][i]/denominator;	}}
/************************************************************************
**计算Xi
**/
void ComputeXi(HMM* phmm, int T, int *O, double **alpha, double **beta, 
	double ***xi)
{
	int i, j;
	int t;
	double sum;

	for (t = 1; t <= T - 1; t++) {
		sum = 0.0;	
		for (i = 1; i <= phmm->N; i++) 
			for (j = 1; j <= phmm->N; j++) 
			{
				xi[t][i][j] = alpha[t][i]*beta[t+1][j]
					*(phmm->A[i][j])
					*(phmm->B[j][O[t+1]]);
				sum += xi[t][i][j];
			}

		for (i = 1; i <= phmm->N; i++) 
			for (j = 1; j <= phmm->N; j++) 
				xi[t][i][j]  /= sum;
	}
}
/************************************************************************
**非用户接口函数
**/double *** AllocXi(int T, int N){	int t;	double ***xi;	xi = (double ***) malloc(T*sizeof(double **));	xi --;	for (t = 1; t <= T; t++)		xi[t] = dmatrix(1, N, 1, N);//xi[t]为N*N矩阵(二维数组)	return xi;}
/************************************************************************
**非用户接口函数
**/void FreeXi(double *** xi, int T, int N){	int t;	for (t = 1; t <= T; t++)		free_dmatrix(xi[t], 1, N, 1, N);	xi ++;	free(xi);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -