📄 approx_cont_mgau.c
字号:
} } /* E_INFO("The dynamic beam %d\n",fastgmm->gmms->dyn_ci_pbeam);*/ return fastgmm->gmms->dyn_ci_pbeam;}/** In this function, 1, It only compute the ci-phones score. 2, The score is not normalize, this routine is supposed to be used before approx_cont_mgau_frame_eval, The best score is determined by the later function. */void approx_cont_mgau_ci_eval (kbcore_t *kbc, fast_gmm_t *fg, mdef_t *mdef, float32 *feat,int32 *ci_senscr){ int32 s; s3senid_t *cd2cisen; int32 best_cid; gs_t* gs; subvq_t* svq; mgau_model_t *g; int32 svq_beam; int32 n_cig; int32 n_cis; n_cis=0; n_cig=0; cd2cisen=mdef_cd2cisen(mdef); svq_beam=fg->gaus->subvqbeam; gs=kbcore_gs(kbc); svq=kbcore_svq(kbc); g=kbcore_mgau(kbc); /*#ifdef APPROX_CONT_MGAU*/ /*Always turn on, so users can be the one who decide how fast/slow the recognizer can be */ best_cid=-1;#if 1 if(gs) best_cid=gc_compute_closest_cw(gs,feat); if(svq) subvq_gautbl_eval_logs3 (svq, feat); for (s = 0; mdef_is_cisenone(mdef,s); s++) { n_cig+=approx_mgau_eval (gs,svq,g,fg,s,ci_senscr,feat,best_cid,svq_beam); n_cis++; }#else for (s = 0; mdef_is_cisenone(mdef,s); s++) { ci_senscr[s] = mgau_eval (g, s, NULL, feat); n_cig+=mgau_n_comp(g,s); n_cis++; }#endif g->frm_ci_sen_eval=n_cis; g->frm_ci_gau_eval=n_cig;}/** approx_con_mgau_frame_eval encapsulates all approximations in the Gaussian computation. This assumes programmers NOT to initialize the senone scores at every frame (FIX me!) before using this function. This layer of code controls the optimization performance in Frame Leval and GMM Level. Frame Level: ^^^^^^^^^^^^ We select to compute the scores only if it is not similar to the most recently computed frames. There are multiple ways to configures this. Naive down-sampling : Skip the computation one every other n-frames Conditional down-sampling : Skip the computation only if the current frame doesn't belong to the same neighborhood of the same frame. This neighborhood corresponds to the codeword which the feature vector found to be the closest. No matter which down-sampling was used, the following problem will appear in the computation. Active senones of frame which supposed to be skipped in computation were not computed in the most recently computed frame. In those case, we chose to compute those senones GMM Level: ^^^^^^^^^^ In the implementation of CI-based GMM selection makes use of the fact that in s3.3 , CI models are always placed before all CD models. Hence the following logic is implemented: if(it is CI senone) compute score else if (it is CD senone) if the ci-phone beam was not set compute score else if the CD senone's parent has a score within the beam compute_score else CD senone's parent has a score out of the beam back-off using the parent senone score. About renormalization ^^^^^^^^^^^^^^^^^^^^^ Sphinx 3.4 generally renormalize the score using the best score. Notice that this introduce extra complication to the implementation. I have separated the logic of computing or not computing the scores. This will clarify the code a bit. Accounting of senone and gaussian computation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This function assumes approx_cont_mgau_ci_eval was run before it, hence at the end the score was added on top of the it. Design ^^^^^^ The whole idea of this function is based on my paper on "4-level categorization of GMM computation " which basically describe how different techniques of fast GMM computation should interact with each others. The current implementation was there to make the code to be as short as possible. I hope that no one will try to make the code to be longer than 500 lines. */int32 approx_cont_mgau_frame_eval (kbcore_t *kbc, fast_gmm_t *fastgmm, float32 *feat, int32 frame, int32 *sen_active, int32 *rec_sen_active, int32 *senscr, int32 *cache_ci_senscr, ptmr_t *tm_ovrhd){ int32 s; int32 t; int32 best, ns, ng, n_cis,n_cig; int32 best_cid; int32 is_skip; int32 is_compute; int32 pbest; int32 is_ciphone; int32 svq_beam; int32* ci_occ; mdef_t* mdef; s3senid_t *cd2cisen; gs_t* gs; subvq_t* svq; mgau_model_t *g; int32 total; int32 dyn_ci_pbeam; best = MAX_NEG_INT32; pbest = MAX_NEG_INT32; ns = 0; n_cis=0; n_cig=0; ng = 0; total=0; best_cid=-1; gs=kbcore_gs(kbc); svq=kbcore_svq(kbc); g=kbcore_mgau(kbc); svq_beam=fastgmm->gaus->subvqbeam; mdef=kbc->mdef; ci_occ=fastgmm->gmms->ci_occu; cd2cisen=mdef_cd2cisen(mdef); ptmr_start(tm_ovrhd); if(gs) best_cid=gc_compute_closest_cw(gs,feat); if(svq) subvq_gautbl_eval_logs3 (svq, feat); if(fastgmm->gmms->max_cd < mdef->n_sen-mdef->n_ci_sen) dyn_ci_pbeam=approx_compute_dyn_ci_pbeam(mdef,fastgmm,g, ci_occ,sen_active,cache_ci_senscr,cd2cisen); else dyn_ci_pbeam=fastgmm->gmms->ci_pbeam; ptmr_stop(tm_ovrhd); is_skip=approx_isskip(frame,fastgmm,best_cid); fastgmm->gaus->rec_bstcid=best_cid; /* Use the original */ for (s = 0; s < g->n_mgau; s++) { is_compute = !sen_active || sen_active[s]; is_ciphone = mdef_is_cisenone(mdef,s);#if _DEBUG_GSCORE_ E_INFO("Sen active %d, rec_sen_active %d, sen id %d \n",sen_active[s],rec_sen_active[s],s);#endif if(!is_skip){ /* Loop handling main computation*/ /* Compute the score of the CI phone even if it is not active. */ if(is_ciphone){ /*Just copied from the cache, we just do accouting here */ /*E_INFO("At senone %d, CI phoneme score %d \n",s,cache_ci_senscr[s]);*/ senscr[s]=cache_ci_senscr[s]; if (pbest < senscr[s]) pbest = senscr[s]; if (best < senscr[s]) best = senscr[s]; sen_active[s]=1; /*n_cig+=mgau_n_comp(g,s); *//*Assume all CIs are computed fully*/ /*n_cis++;*/ }else{ if(is_compute) { if((senscr[cd2cisen[s]] >= pbest + dyn_ci_pbeam )){ ng+=approx_mgau_eval (gs,svq,g,fastgmm,s,senscr,feat,best_cid,svq_beam); ns++; }else { senscr[s]=senscr[cd2cisen[s]]; /* backoff to CI score, not gaussians computed */ } if (best < senscr[s]) best = senscr[s]; } } /*Make a copy to the most recent active list */ rec_sen_active[s]=sen_active[s]; }else{ /* Loop handling no computation*/ /* All complexity of the skipping loop will be coded here */ if(is_compute){ if(rec_sen_active[s]) senscr[s]=senscr[s]; /*Yes. No change to the score */ else{ rec_sen_active[s]=1; ng+=approx_mgau_eval (gs,svq,g,fastgmm,s,senscr,feat,best_cid,svq_beam); ns++; if(senscr[s]>fastgmm->rec_bst_senscr){ /* Rescore everything if we are better best scores*/ E_INFO("Re-normalizing the previous score\n"); /*Every thing except the new score are recomputed*/ for (t = 0; t < g->n_mgau; t++) { if(rec_sen_active[t]&& t!=s ){ senscr[t]-=(senscr[s]-fastgmm->rec_bst_senscr); } } /*Update the best senone score*/ fastgmm->rec_bst_senscr=senscr[s]; } /*Update the new senone score*/ senscr[s]-=fastgmm->rec_bst_senscr; } } } } if(!is_skip){ for (s = 0; s < g->n_mgau; s++){ if(sen_active[s]) senscr[s]-=best; } }else{ #if 0 E_INFO("Best score %d\n",fastgmm->rec_bst_senscr); for(s=0 ;s < g-> n_mgau; s++){ if(sen_active[s]){ E_INFO("At the end: Senone %d has scores %d\n",s,senscr[s]); if(senscr[s]>0){ E_FATAL("Something wrong, senone score > 0\n",s,senscr[s]); } } }#endif } /*Don't delete this line, it is very useful in analysing the performance*/#if APPROX_ANALYSE E_INFO("time: %d , cisen %d, sen: %d, gau: %d\n",frame, n_cis, ns, ng);#endif g->frm_sen_eval = ns; g->frm_gau_eval = ng; ci_occ=NULL; return best;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -