void mexFunction( int nlhs, mxArray *plhs[] , int nrhs, const mxArray *prhs[] ) { double *PI , *A, *L ; double *alpha, *beta, *gamma, *loglik, *xi_summed; const int *dimsPI , *dimsA , *dimsL ; int K , N , numdimsPI , numdimsA , numdimsL , filter = 2; double *scale, *tmp_xi; /*---------------------------------------------------------------*/ /*---------------------- PARSE INPUT ----------------------------*/ /*---------------------------------------------------------------*/ if( (nrhs < 3) | (nrhs >5)) { mexErrMsgTxt("3 or 4 input are requiered"); } PI = mxGetPr(prhs[0]); numdimsPI = mxGetNumberOfDimensions(prhs[0]); dimsPI = mxGetDimensions(prhs[0]); if ( (numdimsPI != 2) | (dimsPI[1] > dimsPI[0]) ) { mexErrMsgTxt("PI must be (N x 1)"); } A = mxGetPr(prhs[1]); numdimsA = mxGetNumberOfDimensions(prhs[1]); dimsA = mxGetDimensions(prhs[1]); if ( (numdimsA != 3) | (dimsA[1] != dimsA[0]) ) { mexErrMsgTxt("A must be (N x N x K-1)"); } L = mxGetPr(prhs[2]); numdimsL = mxGetNumberOfDimensions(prhs[2]); dimsL = mxGetDimensions(prhs[2]); if ( (numdimsL != 2) | (dimsL[0] != dimsA[0]) ) { mexErrMsgTxt("L must be (N x K)"); } N = dimsL[0]; K = dimsL[1]; if (nrhs == 4) { filter = (int)mxGetScalar(prhs[3]); } /*---------------------------------------------------------------*/ /*---------------------- PARSE OUTPUT ---------------------------*/ /*---------------------------------------------------------------*/ plhs[0] = mxCreateDoubleMatrix(N , K , mxREAL); alpha = mxGetPr(plhs[0]); plhs[1] = mxCreateDoubleMatrix(N , K , mxREAL); gamma = mxGetPr(plhs[1]); plhs[2] = mxCreateDoubleMatrix(1 , 1 , mxREAL); loglik = mxGetPr(plhs[2]); if (filter > 0) { /*calculate beta*/ plhs[3] = mxCreateDoubleMatrix(N , K , mxREAL); beta = mxGetPr(plhs[3]); } if (filter > 1) { /*calculate xi_summed*/ plhs[4] = mxCreateDoubleMatrix(N , N , mxREAL); xi_summed = mxGetPr(plhs[4]); } /*---------------------------------------------------------------*/ /*--------- Internal Tempory vector & matrices ------------------*/ /*---------------------------------------------------------------*/ scale = (double *)mxMalloc(K*sizeof(double)); tmp_xi = (double *)mxMalloc(N*N*sizeof(double)); /*---------------------------------------------------------------*/ /*------------------------ MAIN CALL ----------------------------*/ /*---------------------------------------------------------------*/ ForwardWithScale(N, K, filter, PI, A, L, alpha, gamma, loglik, scale); if (filter > 0) /*calculate both alpha and beta, but xi_summed is not calculated*/ BackwardWithScale(N, K, PI, A, L, beta); if (filter == 1) /*calculate gamma with alpha and beta*/ ComputeGamma(N, K, alpha, beta, gamma); if (filter > 1) /*calculate gamma and xi_summed based on xi*/ ComputeXi(N, K, A, L, alpha, beta, gamma, tmp_xi, xi_summed); /*---------------------------------------------------------------*/ /*------------------------ FREE MEMORY --------------------------*/ /*---------------------------------------------------------------*/ mxFree(scale); mxFree(tmp_xi); }
void BaumWelch(HMM *phmm, int T, int *O, double **alpha, double **beta, double **gamma) { int i, j, k; int t, l = 0; double probf, probb, val, threshold; double numeratorA, denominatorA; double numeratorB, denominatorB; double ***xi, *scale; double delta, deltaprev, probprev; double ratio; deltaprev = 10e-70; xi = AllocXi(T, phmm->N); scale = dvector(1, T); ForwardWithScale(phmm, T, O, alpha, scale, &probf); BackwardWithScale(phmm, T, O, beta, scale, &probb); ComputeGamma(phmm, T, alpha, beta, gamma); ComputeXi(phmm, T, O, alpha, beta, xi); probprev = probf; do { /* reestimate frequency of state i in time t=1 */ for (i = 1; i <= phmm->N; i++) phmm->pi[i] = .001 + .999*gamma[1][i]; /* reestimate transition matrix and symbol prob in each state */ 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, &probf); BackwardWithScale(phmm, T, O, beta, scale, &probb); ComputeGamma(phmm, T, alpha, beta, gamma); ComputeXi(phmm, T, O, alpha, beta, xi); delta = probf - probprev; ratio = delta/deltaprev; probprev = probf; deltaprev = delta; l++; } while (ratio > DELTA); printf("num iterations: %d\n", l); FreeXi(xi, T, phmm->N); free_dvector(scale, 1, T); }
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, threshold; double numeratorA, denominatorA; double numeratorB, denominatorB; double ***xi, *scale; double delta, deltaprev, logprobprev; deltaprev = 10e-70; xi = AllocXi(T, phmm->N); scale = dvector(1, T); ForwardWithScale(phmm, T, O, alpha, scale, &logprobf); *plogprobinit = logprobf; /* log P(O |intial model) */ BackwardWithScale(phmm, T, O, beta, scale, &logprobb); ComputeGamma(phmm, T, alpha, beta, gamma); ComputeXi(phmm, T, O, alpha, beta, xi); logprobprev = logprobf; do { /* reestimate frequency of state i in time t=1 */ for (i = 1; i <= phmm->N; i++) phmm->pi[i] = .001 + .999*gamma[1][i]; /* reestimate transition matrix and symbol prob in each state */ 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); ComputeGamma(phmm, T, alpha, beta, gamma); ComputeXi(phmm, T, O, alpha, beta, xi); /* compute difference between log probability of two iterations */ delta = logprobf - logprobprev; logprobprev = logprobf; l++; } while (delta > DELTA); /* if log probability does not change much, exit */ *pniter = l; *plogprobfinal = logprobf; /* log P(O|estimated model) */ FreeXi(xi, T, phmm->N); free_dvector(scale, 1, T); }
/****************************************************************************** **函数名称: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, deltaprev, logprobprev; deltaprev = 10e-70; xi = AllocXi(T, phmm->N); scale = dvector(1, T); ForwardWithScale(phmm, T, O, alpha, scale, &logprobf); *plogprobinit = logprobf; /* log P(O |初始状态) */ BackwardWithScale(phmm, T, O, beta, scale, &logprobb); ComputeGamma(phmm, T, alpha, beta, gamma); ComputeXi(phmm, T, O, alpha, beta, xi); logprobprev = logprobf; do { /* 重新估计 t=1 时,状态为i 的频率 */ for (i = 1; i <= phmm->N; i++) phmm->pi[i] = .001 + .999*gamma[1][i]; /* 重新估计转移矩阵和观察矩阵 */ 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); ComputeGamma(phmm, T, alpha, beta, gamma); ComputeXi(phmm, T, O, alpha, beta, 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); }