/* HMM_combined 11 Aug 2008 I've written this program to run Baum-Welch algorithm for HMM, based on the class notes for ECE 534. The alphas and betas are normalized at each step to avoid really small numbers. The log likekihood is tracked. For more than about 1000 observations there were overflow problems, so in this version the alphas and betas are renormaized after each step. The log10 normalizations are saved so that the log10 likelihood can still be reported. -B. Hajek */ #include #include double pi[10],a[10][10],b[10][10]; /* Parameters of the HMM */ double old; int init_state(),next_state(),observation(); int print_parameter(); char input[100001]="0110100000000110010010000010100000001000001101111110001100000000010000111111111000001000100111001000"; int y[100001]; double alpha[10][100001], beta[10][100001], Gamma[10][100001], xi[10][10][100001]; /* Sorry--lower case gammma is a math function */ int N_s,N_o,T; double drand48(void); /* MAIN PROGRAM */ int main(void) { int i,j, l,t; int iter,num_iter; double numerator,denominator,temp; double alpha_log_norm, beta_log_norm, factor; T=100000; printf("T=%i data= ", T); N_s=2; N_o=2; /* Following statement enters the observations from the string input[] */ /* for (t=1;t<=T;t++) {sscanf(input+t-1, "%1i", &y[t]); printf("%1i",y[t]); } */ /* The following enters observations by random generation, first the values of the parameters pi, A, B are read in */ printf("\n Parameters used to generate the observations:"); pi[0]=0.5; pi[1]=0.5; a[0][0]=0.8; a[0][1]=0.2; a[1][0]=0.4; a[1][1]=0.6; b[0][0]=0.8; b[0][1]=0.2; b[1][0]=0.3; b[1][1]=0.7; print_parameter(); i=init_state(); for (t=1;t<=T;t++) { y[t]=observation(i); /* printf("%1i", i); */ /* printf("%i %i\n", i,y[t]); */ i=next_state(i); } printf("\nFirst min(T,100) observations:"); for (t=1;(t<=100)&(t<=T);t++) printf("%1i",y[t]); printf("\n"); /* Now we are ready to run the EM algorithm. We enter the intial parmater values (which may not be the same as the parmeters used to generated the observations */ printf("\n Initial value of parameters for EM algorithm:"); pi[0]=0.5; pi[1]=0.5; a[0][0]=0.8; a[0][1]=0.2; a[1][0]=0.1; a[1][1]=0.9; b[0][0]=0.6; b[0][1]=0.4; b[1][0]=0.4; b[1][1]=0.6; /* a[0][0]=0.8; a[0][1]=0.2; a[1][0]=0.4; a[1][1]=0.6; b[0][0]=0.9; b[0][1]=0.1; b[1][0]=0.1; b[1][1]=0.9; */ num_iter=500; for (iter=1;iter<=num_iter;iter++) { old=a[0][0]; print_parameter(); /* initialize alpha and beta */ for (i=0;i1;t--) { for (i=0;i sum ) { i++; sum+=pi[i]; } return(i); } /* eo init_state */ /* next_state(i) for a state i returns a (pseudo) random next state distributed according to the ith row of A */ int next_state(i) int i; {int j; double u,sum; /* printf("Hello\n"); */ sum=a[i][0]; j=0; u=drand48(); while (u > sum ) { j++; sum+=a[i][j]; } return(j); } /* eo next_state */ /* observation(i) for a state i returns a (pseudo) random observation distributed according to the ith row of B */ int observation(i) int i; {int l; double u,sum; sum=b[i][0]; l=0; u=drand48(); while (u > sum ) { l++; sum+=b[i][l]; } return(l); } /* eo observation */