Julius 4.2
libsent/src/phmm/gprune_beam.c
説明を見る。
00001 
00046 /*
00047  * Copyright (c) 1991-2011 Kawahara Lab., Kyoto University
00048  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
00049  * Copyright (c) 2005-2011 Julius project team, Nagoya Institute of Technology
00050  * All rights reserved
00051  */
00052 
00053 #include <sent/stddefs.h>
00054 #include <sent/htk_hmm.h>
00055 #include <sent/htk_param.h>
00056 #include <sent/hmm.h>
00057 #include <sent/hmm_calc.h>
00058 
00059 #define TEST2
00060 
00061 /*
00062 
00063   best_mixtures_on_last_frame[]
00064   
00065   dim:  0 1 2 3 4 .... veclen-1    -> sum up
00066  ================================
00067   thres
00068  --------------------------------
00069   mix1  | |
00070   mix2  | |
00071   mix3  v v
00072   ...
00073   mixN  
00074  ================================
00075          \_\_ vecprob[0],vecprob[1]
00076 
00077   algorithm 1:
00078          
00079   foreach dim {
00080      foreach all_mixtures in best_mixtures_on_last_frame {
00081         compute score
00082      }
00083      threshold = the current lowest score + beam_width?
00084      foreach rest_mixtures {
00085         if (already marked as pruned at previous dim) {
00086            skip
00087         }
00088         compute score
00089         if (score < threshold) {
00090            mark as pruned
00091            skip
00092         }
00093         if (score > threshold) {
00094            update threshold
00095         }
00096      }
00097   }
00098 
00099   algorithm 2:
00100 
00101   foreach all_mixtures in best_mixtures_on_last_frame {
00102      foreach dim {
00103        compute score
00104        if (threshold[dim] < score) update
00105      }
00106      threshold[dim] += beam_width
00107   }
00108   foreach rest_mixtures {
00109      foreach dim {
00110         compute score
00111         if (score < threshold[dim]) skip this mixture
00112         update thres
00113      }
00114   }
00115      
00116 */
00117 
00124 static void
00125 clear_dimthres(HMMWork *wrk)
00126 {
00127   int i;
00128   for(i=0;i<wrk->dimthres_num;i++) wrk->dimthres[i] = 0.0;
00129 }
00130 
00138 static void
00139 set_dimthres(HMMWork *wrk)
00140 {
00141   int i;
00142   for(i=0;i<wrk->dimthres_num;i++) wrk->dimthres[i] += TMBEAMWIDTH;
00143 }
00144 
00158 static LOGPROB
00159 compute_g_beam_updating(HMMWork *wrk, HTK_HMM_Dens *binfo)
00160 {
00161   VECT tmp, x;
00162   VECT *mean;
00163   VECT *var;
00164   VECT *th = wrk->dimthres;
00165   VECT *vec = wrk->OP_vec;
00166   short veclen = wrk->OP_veclen;
00167 
00168 #ifndef TEST2
00169   if (binfo == NULL) return(LOG_ZERO);
00170 #endif
00171 
00172   mean = binfo->mean;
00173   var = binfo->var->vec;
00174 
00175   tmp = 0.0;
00176   for (; veclen > 0; veclen--) {
00177     x = *(vec++) - *(mean++);
00178     tmp += x * x * *(var++);
00179     if ( *th < tmp) *th = tmp;
00180     th++;
00181   }
00182   return((tmp + binfo->gconst) * -0.5);
00183 }
00184 
00198 static LOGPROB
00199 compute_g_beam_pruning(HMMWork *wrk, HTK_HMM_Dens *binfo)
00200 {
00201   VECT tmp, x;
00202   VECT *mean;
00203   VECT *var;
00204   VECT *th = wrk->dimthres;
00205   VECT *vec = wrk->OP_vec;
00206   short veclen = wrk->OP_veclen;
00207 
00208 #ifndef TEST2
00209   if (binfo == NULL) return(LOG_ZERO);
00210 #endif
00211   mean = binfo->mean;
00212   var = binfo->var->vec;
00213 
00214   tmp = 0.0;
00215   for (; veclen > 0; veclen--) {
00216     x = *(vec++) - *(mean++);
00217     tmp += x * x * *(var++);
00218     if ( tmp > *(th++)) {
00219       return LOG_ZERO;
00220     }
00221   }
00222   return((tmp + binfo->gconst) * -0.5);
00223 }
00224 
00225 
00233 boolean
00234 gprune_beam_init(HMMWork *wrk)
00235 {
00236   int i;
00237 
00238   /* maximum Gaussian set size = maximum mixture size * nstream */
00239   wrk->OP_calced_maxnum = wrk->OP_hmminfo->maxmixturenum * wrk->OP_nstream;
00240   wrk->OP_calced_score = (LOGPROB *)mymalloc(sizeof(LOGPROB) * wrk->OP_calced_maxnum);
00241   wrk->OP_calced_id = (int *)mymalloc(sizeof(int) * wrk->OP_calced_maxnum);
00242   wrk->mixcalced = (boolean *)mymalloc(sizeof(int) * wrk->OP_calced_maxnum);
00243   for(i=0;i<wrk->OP_calced_maxnum;i++) wrk->mixcalced[i] = FALSE;
00244   wrk->dimthres_num = wrk->OP_hmminfo->opt.vec_size;
00245   wrk->dimthres = (LOGPROB *)mymalloc(sizeof(LOGPROB) * wrk->dimthres_num);
00246 
00247   return TRUE;
00248 }
00249 
00256 void
00257 gprune_beam_free(HMMWork *wrk)
00258 {
00259   free(wrk->OP_calced_score);
00260   free(wrk->OP_calced_id);
00261   free(wrk->mixcalced);
00262   free(wrk->dimthres);
00263 }
00264 
00290 void
00291 gprune_beam(HMMWork *wrk, HTK_HMM_Dens **g, int gnum, int *last_id, int lnum)
00292 {
00293   int i, j, num = 0;
00294   LOGPROB score, thres;
00295 
00296   if (last_id != NULL) {        /* compute them first to form thresholds */
00297     /* 1. clear dimthres */
00298     clear_dimthres(wrk);
00299     /* 2. calculate first $OP_gprune_num and set initial thresholds */
00300     for (j=0; j<lnum; j++) {
00301       i = last_id[j];
00302 #ifdef TEST2
00303       if (!g[i]) {
00304         score = LOG_ZERO;
00305       } else {
00306         score = compute_g_beam_updating(wrk, g[i]);
00307       }
00308       num = cache_push(wrk, i, score, num);
00309 #else
00310       score = compute_g_beam_updating(wrk, g[i]);
00311       num = cache_push(wrk, i, score, num);
00312 #endif
00313       wrk->mixcalced[i] = TRUE;      /* mark them as calculated */
00314     }
00315     /* 3. set pruning thresholds for each dimension */
00316     set_dimthres(wrk);
00317 
00318     /* 4. calculate the rest with pruning*/
00319     for (i = 0; i < gnum; i++) {
00320       /* skip calced ones in 1. */
00321       if (wrk->mixcalced[i]) {
00322         wrk->mixcalced[i] = FALSE;
00323         continue;
00324       }
00325 #ifdef TEST2
00326       /* compute with safe pruning */
00327       if (!g[i]) continue;
00328       score = compute_g_beam_pruning(wrk, g[i]);
00329       if (score > LOG_ZERO) {
00330         num = cache_push(wrk, i, score, num);
00331       }
00332 #else
00333       /* compute with safe pruning */
00334       score = compute_g_beam_pruning(wrk, g[i]);
00335       if (score > LOG_ZERO) {
00336         num = cache_push(wrk, i, score, num);
00337       }
00338 #endif
00339     }
00340   } else {                      /* in case the last_id not available */
00341     /* at the first 0 frame */
00342     /* calculate with safe pruning */
00343     thres = LOG_ZERO;
00344     for (i = 0; i < gnum; i++) {
00345       if (num < wrk->OP_gprune_num) {
00346         score = compute_g_base(wrk, g[i]);
00347       } else {
00348         score = compute_g_safe(wrk, g[i], thres);
00349         if (score <= thres) continue;
00350       }
00351       num = cache_push(wrk, i, score, num);
00352       thres = wrk->OP_calced_score[num-1];
00353     }
00354   }
00355   wrk->OP_calced_num = num;
00356 }