ghmm_viterbi.cpp
来自「General Hidden Markov Model Library 一个通用」· C++ 代码 · 共 447 行
CPP
447 行
#include <float.h>#include <math.h>#include <assert.h>#include <ghmm/matrix.h>#include <ghmm/sdmodel.h>#include <ghmm++/GHMM_Computation.h>#include <iostream>#ifdef HAVE_NAMESPACESusing namespace std;#endifstatic double **mat_d_alloc(int n, int m){ int i,j; double** matout = new double*[n]; for (i=0;i<n;i++) { matout[i] = new double[m]; } return matout;}static void mat_d_free(double ***mat, int n){ int i; for (i=0;i<n;i++) { delete [] (*mat)[i]; } delete *mat;}static int **mat_i_alloc(int n, int m){ int i,j; int** matout = new int*[n]; for (i=0;i<n;i++) { matout[i] = new int[m]; } return matout;}static void mat_i_free(int ***mat, int n){ int i; for (i=0;i<n;i++) { delete [] (*mat)[i]; } delete *mat;}Viterbi::Viterbi( sdmodel *mo, int len) /** double ***log_in_a; double **log_b; double *phi; double *phi_new; int **psi;*/{ int i,j,t,k; /* Allocate the log_in_a's -> individal lenghts */ log_in_a = new double**[mo->N]; for(i = 0; i < mo->N; i++) { log_in_a[i] = mat_d_alloc(mo->cos, mo->s[i].in_states); assert(log_in_a[i]); } log_b = mat_d_alloc(mo->N, len); psi = mat_i_alloc(len, mo->N); assert(log_in_a); assert(log_b); assert(psi); phi = new double[mo->N]; phi_new = new double[mo->N]; for(i = 0; i < mo->N; i++) phi[i] = 0.0; for(i = 0; i < mo->N; i++) phi_new[i] = 0.0;}Viterbi::~Viterbi(){ delete [] log_in_a; delete [] log_b; delete psi; delete [] phi; delete [] phi_new;}void Viterbi::DFSVisit(sdmodel *mo, int j, int &counter){ colors[j] = VISITED; for(int i = 0; i < mo->s[j].out_states; i++) { if (colors[mo->s[j].out_id[i]] == NOTVISITED) /* looping back taken care of */ DFSVisit(mo,mo->s[j].out_id[i],counter); } colors[j] = DONE; doneTime[j] = ++counter; if ( mo->silent[j] ) topo_order.push_back(j);}void Viterbi::DFS(sdmodel *mo){ int i; colors = new DFSFLAG[mo->N]; doneTime = new int[mo->N]; for(i=0; i < mo->N; i++) { colors[i] = NOTVISITED; } int counter = 0; for(i=0; i < mo->N; i++) { if (colors[i] == NOTVISITED) DFSVisit(mo, i, counter); } vector<int>::iterator it; for( it = topo_order.end() - 1; it != topo_order.begin(); it-- ) cout << *it << " , "; cout << endl;}void Viterbi::Viterbi_precompute( sdmodel *mo, int *o, int len ){ int i, j, k, t, osc; double log_p = +1; /* Precomputing the log(a_ij) */ //for (j = 0; j < mo->N; j++) // for (i = 0; i < mo->s[j].in_states; i++) // if ( mo->s[j].in_a[i] == 0.0 ) /* DBL_EPSILON ? */ //log_in_a[j][i] = +1; /* Not used any further in the calculations */ // else //log_in_a[j][i] = log( mo->s[j].in_a[i] ); /* Collecting emitting states */ for(j = 0; j < mo->N; j++) { if (!mo->silent[j]) stateind.push_back(j); } for(j = 0; j < mo->N; j++) { for(k = 0; k < mo->cos; k++) for(i = 0; i < mo->s[j].in_states; i++) if ( mo->s[j].in_a[k][i] == 0.0 ) /* DBL_EPSILON ? */ log_in_a[j][k][i] = +1; /* Not used any further in the calculations */ else log_in_a[j][k][i] = log( mo->s[j].in_a[k][i] ); } /* Precomputing the log(bj(ot)) */ for (j = 0; j < mo->N; j++) for (t = 0; t < len; t++) if ( mo->s[j].b[o[t]] == 0.0 ) /* DBL_EPSILON ? */ log_b[j][t] = +1; else log_b[j][t] = log( mo->s[j].b[o[t]] );}/* viterbi_precompute *//** Return the log score of the sequence */double Viterbi::Viterbi_runme ( sdmodel *mo, int *o, int len){ int t, j, i; int last_osc = -1; double value, max_value; double log_p, sum, osum = 0.0; double dummy = 0.0; /* Allocate the matrices log_in_a, log_b,Vektor phi, phi_new, Matrix psi */ // Done in the constructor Viterbi /* Precomputing the log(a_ij) and log(bj(ot)) */ Viterbi_precompute(mo, o, len); // The Viterbi path state_seq = new int[len]; /* Initialization, that is t = 0 */ for (j = 0; j < mo->N; j++) { if ( mo->s[j].pi == 0.0 || log_b[j][0] == +1 ) /* instead of 0, DBL_EPS.? */ phi[j] = +1; else phi[j] = log(mo->s[j].pi) + log_b[j][0]; printf("phi[%d],%f\n", j, phi[j]); } /* psi[0][i] = 0, also unneccessary here */ /* Recursion step */ for (t = 1; t < len; t++) { int osc = mo->get_class(&dummy,t,&osum); for (j = 0; j < mo->N; j++) { /* Determine the maximum */ /* max_phi = phi[i] + log_in_a[j][i] ... */ max_value = -DBL_MAX; psi[t][j] = -1; for (i = 0; i < mo->s[j].in_states; i++) { if ( last_osc != -1 && last_osc != osc ) { /* just switch class */ if ( phi[ mo->s[j].in_id[i] ] != +1 ) { if ( phi[ mo->s[j].in_id[i] ] > max_value ) { max_value = phi[ mo->s[j].in_id[i] ]; psi[t][j] = mo->s[j].in_id[i]; } } } else { if ( phi[ mo->s[j].in_id[i] ] != +1 && log_in_a[j][osc][i] != +1) { value = phi[ mo->s[j].in_id[i] ] + log_in_a[j][osc][i]; if (value > max_value) { max_value = value; psi[t][j] = mo->s[j].in_id[i]; } } else fprintf(stderr, " %d --> %d = %f, \n", i,j,log_in_a[j][osc][i]); } } last_osc = osc; /* save last transition class */ /* No maximum found (that is, state never reached) or the output O[t] = 0.0: */ if (max_value == -DBL_MAX || /* and then also: (v->psi[t][j] == -1) */ log_b[j][t] == +1 ) { phi_new[j] = +1; fprintf(stderr, "b[%d][%d]=0.0, \n", j, t); } else phi_new[j] = max_value + log_b[j][t]; } /* complete time step */ /* First now replace the old phi with the new phi */ for (j = 0; j < mo->N; j++) { phi[j] = phi_new[j]; printf("\npsi[%d],%d, phi, %f\n", t, psi[t][j], phi[j]); } } /* Termination */ max_value = -DBL_MAX; state_seq[len-1] = -1; for (j = 0; j < mo->N; j++) if ( phi[j] != +1 && phi[j] > max_value) { max_value = phi[j]; state_seq[len-1] = j; } if (max_value == -DBL_MAX) { /* Sequence can't be generated from the model! */ log_p = +1; /* Backtracing doesn't work, because state_seq[*] allocated with -1 */ for (t = len - 2; t >= 0; t--) state_seq[t] = -1; } else { log_p = max_value; /* Backtracing */ for (t = len - 2; t >= 0; t--) state_seq[t] = psi[t+1][state_seq[t+1]]; } return log_p;} /* viterbi *//** Return the log score of the sequence */double Viterbi::Viterbi_runme_silent ( sdmodel *mo, int *o, int len){ int t, k, i, j; int last_osc = -1; double value, max_value; double log_p, sum, osum = 0.0; double dummy = 0.0; /* Allocate the matrices log_in_a, log_b,Vektor phi, phi_new, Matrix psi */ // Done in the constructor Viterbi /* Precomputing the log(a_ij) and log(bj(ot)) */ Viterbi_precompute(mo, o, len); // The Viterbi path vector<int> seq_local; state_seq = new int[len]; /* Initialization for all states (emitting and non-silent), that is t = 0 */ for (j = 0; j < mo->N; j++) { if ( mo->s[j].pi == 0.0 || log_b[j][0] == +1 ) /* instead of 0, DBL_EPS.? */ phi[j] = +1; else phi[j] = log(mo->s[j].pi) + log_b[j][0]; printf("phi[%d],%f\n", j, phi[j]); } /* psi[0][i] = 0, also unneccessary here */ /* Recursion step */ for (t = 1; t < len; t++) { int osc = mo->get_class(&dummy,t,&osum); int St; for (k = 0; k < stateind.size(); k++) { /* Determine the maximum */ /* max_phi = phi[i] + log_in_a[j][i] ... */ St = stateind[k]; max_value = -DBL_MAX; psi[t][St] = -1; for (i = 0; i < mo->s[St].in_states; i++) { if ( last_osc != -1 && last_osc != osc ) { /* just switch class */ if ( phi[ mo->s[St].in_id[i] ] != +1 ) { if ( phi[ mo->s[St].in_id[i] ] > max_value ) { max_value = phi[ mo->s[St].in_id[i] ]; psi[t][St] = mo->s[St].in_id[i]; } } } else { if ( phi[ mo->s[St].in_id[i] ] != +1 && log_in_a[St][osc][i] != +1) { value = phi[ mo->s[St].in_id[i] ] + log_in_a[St][osc][i]; if (value > max_value) { max_value = value; psi[St][j] = mo->s[St].in_id[i]; } } else fprintf(stderr, " %d --> %d = %f, \n", i,St,log_in_a[St][osc][i]); } } last_osc = osc; /* save the last transition class */ /* No maximum found (that is, state never reached) or the output O[t] = 0.0: */ if (max_value == -DBL_MAX || /* and then also: (v->psi[t][j] == -1) */ log_b[St][t] == +1 ) { phi_new[St] = +1; fprintf(stderr, "b[%d][%d]=0.0, \n", j, t); } else phi_new[St] = max_value + log_b[St][t]; } /* complete time step for emitting states */ // // Silent states, visited in topological order // /* first compute only in-coming from emitting states, then non-silent */ for ( k = 0; k < mo->N; k++) { if ( mo->silent[k] ) /* Silent states */ { /* Determine the maximum */ /* max_phi = phi[i] + log_in_a[j][i] ... */ max_value = -DBL_MAX; psi[t][k] = -1; for (i = 0; i < mo->s[k].in_states; i++) { if ( phi[ mo->s[k].in_id[i] ] != +1 && log_in_a[k][osc][i] != +1) { value = phi[ mo->s[k].in_id[i] ] + log_in_a[k][osc][i]; if (value > max_value) { max_value = value; psi[k][j] = mo->s[k].in_id[i]; } } } /* No maximum found (that is, state never reached) or the output O[t] = 0.0: */ if (max_value == -DBL_MAX) { phi_new[k] = +1; fprintf(stderr, "b[%d][%d]=0.0, \n", j, t); } else phi_new[k] = max_value; } } /* complete time step for silent states */ /* First now replace the old phi with the new phi */ for (k = 0; k < mo->N; k++) { phi[k] = phi_new[k]; printf("\npsi[%d],%d, phi, %f\n", t, psi[t][k], phi[k]); } } /* Termination */ max_value = -DBL_MAX; state_seq[len-1] = -1; for (j = 0; j < mo->N; j++) if ( phi[j] != +1 && phi[j] > max_value) { max_value = phi[j]; state_seq[len-1] = j; } if (max_value == -DBL_MAX) { /* Sequence can't be generated from the model! */ log_p = +1; /* Backtracing doesn't work, because state_seq[*] allocated with -1 */ for (t = len - 2; t >= 0; t--) state_seq[t] = -1; } else { log_p = max_value; /* Backtracing */ for (t = len - 2; t >= 0; t--) state_seq[t] = psi[t+1][state_seq[t+1]]; } return log_p;} /* viterbi */void Viterbi::print_path(int T, char *ts){ printf("%s{ ", ts); for(int i=0; i < T; i++) { printf(" %d, ", state_seq[i] ); } printf("%s} ", ts);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?