📄 beam.c
字号:
/** * @file beam.c * * <JA> * @brief フレ〖ム票袋ビ〖ム玫瑚の悸乖∈妈1パス∷ * * 妈1パスのフレ〖ム票袋ビ〖ム玫瑚を悸狠に悸乖する簇眶凡です. * 千急借妄インスタンスごとに悸乖されます. * 介袋步·1フレ〖ムの千急借妄·姜位借妄·妈1パスの冯蔡疯年·セグメント * 姜位の浮梦などの借妄が崔まれています. * * アルゴリズムについては·帽胳旺悟夺击は 1-best 夺击がデフォルトです * が·帽胳滦夺击も蝗脱材墙です. 帽胳N-gram では帽胳粗の儡鲁扩腆は 1-gram * factoring (2-gram factoring も联买材)を脱いて纷换されます. 矢恕の * 眷圭·腾菇陇步辑今は矢恕のカテゴリ帽疤で侯喇され·帽胳粗の儡鲁(帽胳 * 滦扩腆)は帽胳粗莲败で努脱されます. 帽胳千急モ〖ドでは帽胳粗儡鲁は * 雇胃されません. * </JA> * * <EN> * @brief Frame-synchronous beam search for the 1st pass * * These are core functions of frame-synchronous beam search using a * static lexicon tree, as the first pass of Julius. These functions * will be called from pass1.c, to execute for each recognition * process instance in turn. Functions for initialization, frame-wise * recognition processing, end procedure, finding best path, detecting * end of segment on short-pause segmentation mode, are defined here. * * About algorithm: 1-best approximation will be performed for word * context approximation, but normal word-pair approximation is also * supported. With word/class N-gram, Julius computes the language * score using 1-gram factoring (can be changed to 2-gram factoring if * you want). With DFA grammar, Julius can compute the connection * constraint of words using the category-pair constraint on the * beginning of the words, since Julian makes a per-category tree * lexicon. On isolated word recognition mode, the cross-word transitions * are ignored. * * </EN> * * @author Akinobu LEE * @date Tue Feb 22 17:00:45 2005 * * $Revision: 1.11 $ * *//* * Copyright (c) 1991-2007 Kawahara Lab., Kyoto University * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology * Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology * All rights reserved */#include <julius/julius.h>#undef DEBUG/* ---------------------------------------------------------- *//* 妈1パスの冯蔡借妄 *//* end procedure to get result of 1st pass *//* ---------------------------------------------------------- */#ifdef WORD_GRAPH/** * <JA> * @brief 千急冯蔡の帽胳トレリスから帽胳グラフを藐叫する * * (WORD_GRAPH 回年箕) * この簇眶は妈1パスの冯蔡の帽胳トレリスを姜眉からバックトレ〖スし· * パス惧にあるトレリス帽胳を帽胳グラフとして藐叫する. 悸狠には· * 帽胳トレリス惧でグラフ惧に荒るもののみにマ〖クを烧け· * 妈2パスでは·マ〖クのついた帽胳のみを鸥倡する. * * グラフは r->result.wg1 に呈羌される. * * @param frame [in] 帽胳トレリス惧で帽胳琐眉を浮瑚するフレ〖ム * @param r [i/o] 千急借妄インスタンス * </JA> * <EN> * @brief Extract word graph from the resulting word trellis * * If WORD_GRAPH is defined, this function trace back through the * word trellis from the end point, to extract the trellis words on * the path as a word graph. Actually, this function only marks * which trellis words are included in the word graph. On the 2nd pass, * only the words in the word graph will be expanded. * * The generated word graph will be stored to r->result.wg1. * * @param frame [in] frame to lookup for word ends in the word trellis * @param r [i/o] recognition process instance * </EN> */static voidgenerate_lattice(int frame, RecogProcess *r){ BACKTRELLIS *bt; WORD_INFO *winfo; TRELLIS_ATOM *ta; int i, j; LOGPROB l; WordGraph *new; bt = r->backtrellis; winfo = r->lm->winfo; if (frame >= 0) { for (i=0;i<bt->num[frame];i++) { ta = bt->rw[frame][i]; /* words will be saved as a part of graph only if any of its following word has been survived in a beam */ if (! ta->within_context) continue; /* not a candidate */ if (ta->within_wordgraph) continue; /* already marked */ /* mark */ ta->within_wordgraph = TRUE; new = (WordGraph *)mymalloc(sizeof(WordGraph)); new->wid = ta->wid; new->lefttime = ta->begintime; new->righttime = ta->endtime; new->fscore_head = ta->backscore; new->fscore_tail = 0.0; new->gscore_head = 0.0; new->gscore_tail = 0.0; new->lscore_tmp = ta->lscore;#ifdef CM_SEARCH new->cmscore = 0.0;#endif new->forward_score = new->backward_score = 0.0; new->headphone = winfo->wseq[ta->wid][0]; new->tailphone = winfo->wseq[ta->wid][winfo->wlen[ta->wid]-1]; new->leftwordmaxnum = FANOUTSTEP; new->leftword = (WordGraph **)mymalloc(sizeof(WordGraph *) * new->leftwordmaxnum); new->left_lscore = (LOGPROB *)mymalloc(sizeof(LOGPROB) * new->leftwordmaxnum); new->leftwordnum = 0; new->rightwordmaxnum = FANOUTSTEP; new->rightword = (WordGraph **)mymalloc(sizeof(WordGraph *) * new->rightwordmaxnum); new->right_lscore = (LOGPROB *)mymalloc(sizeof(LOGPROB) * new->rightwordmaxnum); new->rightwordnum = 0; l = ta->backscore; if (ta->last_tre->wid != WORD_INVALID) { l -= ta->last_tre->backscore; } l -= ta->lscore; new->amavg = l / (float)(ta->endtime - ta->begintime + 1);#ifdef GRAPHOUT_DYNAMIC new->purged = FALSE;#endif new->saved = FALSE; new->graph_cm = 0.0; new->mark = FALSE; new->next = r->result.wg1; r->result.wg1 = new; /* recursive call */ generate_lattice(ta->last_tre->endtime, r); } }}/** * <EN> * Link all words in 1st pass word graph extracted by * generate_lattice() by their boundary frame. All words with the * same boundary frame will be connected. * * </EN> * <JA> * generate_lattice() で栏喇した妈1パスグラフ面の帽胳どうしを董肠箕粗 * に骄って息冯する. 票じ董肠箕粗を积つすべての帽胳が儡鲁される. * * </JA> * * @param root [in] pointer to the root of lattice words. * */static voidlink_lattice_by_time(WordGraph *root){ WordGraph *wg; WordGraph *wtmp; int lefttime, righttime; for(wg=root;wg;wg=wg->next) { for(wtmp=root;wtmp;wtmp=wtmp->next) { if (wg->righttime + 1 == wtmp->lefttime) { wordgraph_check_and_add_leftword(wtmp, wg, wtmp->lscore_tmp); wordgraph_check_and_add_rightword(wg, wtmp, wtmp->lscore_tmp); } if (wtmp->righttime + 1 == wg->lefttime) { wordgraph_check_and_add_leftword(wg, wtmp, wg->lscore_tmp); wordgraph_check_and_add_rightword(wtmp, wg, wg->lscore_tmp); } } }}/** * <EN> * re-compute 2-gram prob for all link in 1st pass word graph mode. * </EN> * <JA> * 妈1パスで帽胳グラフを栏喇するモ〖ドにおいて·栏喇稿に帽胳グラフ惧の * 赖澄な2-gram咐胳澄惟を浩纷换する. * </JA> * * @param root [in] pointer to root node of word graph * @param wchmm [in] tree lexicon used for the word graph generation * */static voidre_compute_lattice_lm(WordGraph *root, WCHMM_INFO *wchmm){ int i; for(wg=root;wg;wg=wg->next) { for(i=0;i<wg->leftwordnum;i++) { wg->left_lscore[i] = (*(wchmm->ngram->bigram_prob))(wchmm->ngram, wchmm->winfo->wton[wg->leftword[i]->wid], wchmm->winfo->wton[wg->wid]); } for(i=0;i<wg->rightwordnum;i++) { wg->right_lscore[i] = (*(wchmm->ngram->bigram_prob))(wchmm->ngram, wchmm->winfo->wton[wg->wid], wchmm->winfo->wton[wg->rightword[i]->wid]); } }}#endif/** * <JA> * あるトレリス帽胳の攫鼠をテキストで叫蜗 (デバッグ脱) * * @param atom [in] 叫蜗するトレリス帽胳 * @param winfo [in] 帽胳辑今 * </JA> * <EN> * Output a trellis word information in text (for debug) * * @param atom [in] trellis word to output * @param winfo [in] word dictionary * </EN> */static voidput_atom(TRELLIS_ATOM *atom, WORD_INFO *winfo){ int i; jlog("DEBUG: %3d,%3d %f %16s (id=%5d)", atom->begintime, atom->endtime, atom->backscore, winfo->wname[atom->wid], atom->wid); for (i=0;i<winfo->wlen[atom->wid]; i++) { jlog(" %s",winfo->wseq[atom->wid][i]->name); } jlog("\n");}/** * <JA> * @brief 千急冯蔡の帽胳トレリス惧の呵锑帽胳废误を滇める * * 涂えられたトレリス帽胳から掐蜗幌眉に羹かって帽胳トレリス惧を * トレ〖スバックし, その呵锑帽胳废误铬输およびその咐胳スコアを手す. * 弹爬となる呵介のトレリス帽胳が涂えられる涩妥がある. * * @param wordseq_rt [out] 冯蔡の呵锑帽胳废误が呈羌されるバッファ * @param rt_wordlen [out] @a wordseq_rt の墓さ * @param atom [in] バックトレ〖スの弹爬となるトレリス帽胳 * @param winfo [in] 帽胳辑今 * * @return 评られた呵锑帽胳废误の咐胳スコア. * </JA> * <EN> * @brief Find the best word sequence in the word trellis * * This function trace back through the word trellis to the beginning * of input, to find the best word sequence. The traceback starting point * should be specified as a trellis word. * * @param wordseq_rt [out] buffer to store the best word sequence as result * @param rt_wordlen [out] length of @a wordseq_rt * @param atom [in] a trellis word as the starting point of the traceback * @param winfo [in] word dictionary * * @return the total N-gram language score of the word sequence. * </EN> */static LOGPROBtrace_backptr(WORD_ID wordseq_rt[MAXSEQNUM], int *rt_wordlen, TRELLIS_ATOM *atom, WORD_INFO *winfo){ int wordlen = 0; /* word length of best sentence hypothesis */ TRELLIS_ATOM *tretmp; LOGPROB langscore = 0.0; WORD_ID wordseq[MAXSEQNUM]; /* temporal: in reverse order */ int i; /* initialize */ wordseq[0] = atom->wid; /* start from specified atom */ wordlen = 1; tretmp = atom; langscore += tretmp->lscore; if (debug2_flag) { put_atom(tretmp, winfo); } /* trace the backtrellis */ while (tretmp->begintime > 0) {/* until beginning of input */ tretmp = tretmp->last_tre;/* t = tretmp->boundtime - 1; tretmp = bt_binsearch_atom(backtrellis, tretmp->boundtime-1, tretmp->last_wid);*/ if (tretmp == NULL) { /* should not happen */ j_internal_error("trace_backptr: last trellis missing while backtracking"); } langscore += tretmp->lscore; wordseq[wordlen] = tretmp->wid; wordlen++; if (debug2_flag) { put_atom(tretmp, winfo); } if (wordlen >= MAXSEQNUM) { j_internal_error("trace_backptr: sentence length exceeded ( > %d)\n",MAXSEQNUM); } } *rt_wordlen = wordlen; /* reverse order -> normal order */ for(i=0;i<wordlen;i++) wordseq_rt[i] = wordseq[wordlen-i-1]; return(langscore);}/** * <JA> * @brief 妈1パスの千急借妄冯蔡から千急冯蔡を冉年し·呵锑帽胳废误を斧つける. * * 妈1パスの纷换冯蔡である帽胳トレリスから·妈1パスでの呵锑铬输を滇 * め·インスタンス柒の result.pass1 に瘦赂する. 铬输が评られない眷圭 * はエラ〖∈玫瑚疙り¨コ〖ド -1∷となる. * * ショ〖トポ〖ズセグメンテ〖ション箕は·千急冯蔡が痰不帽胳のみからなる眷圭· * エラ〖∈デコ〖ダによる逮笛¨コ〖ド -4∷となる. * * また·WORD_GRAPH 年盗箕は·この簇眶柒でさらに generate_lattice() を * 钙び叫し·帽胳グラフの藐叫を乖う. * * @param framelen [in] 妈1パスで借妄が毗茫したフレ〖ム眶 * @param r [in] 千急借妄インスタンス * * </JA> * <EN> * @brief Find best path from the first pass result and set result status. * * This function find the best word sequence from the resulting word * trellis of the 1st pass, and store them to result.pass1 in the * recognition process instance. If no candidate was found, it sets * error code -1 (recognition failure) and exit. * * On short-pause segmentation, it sets error code -4 (decoder rejection) * if the found best path consists of only silence words. * * Also, if WORD_GRAPH is defined, this function also calls * generate_lattice() to extract word graph from the word trellis. * * @param framelen [in] frame length that has been processed * @param r [in] recognition process instance * </EN> */static voidfind_1pass_result(int framelen, RecogProcess *r){ BACKTRELLIS *backtrellis; WORD_INFO *winfo; WORD_ID wordseq[MAXSEQNUM]; int wordlen; int i; TRELLIS_ATOM *best; int last_time; LOGPROB total_lscore; LOGPROB maxscore; TRELLIS_ATOM *tmp;#ifdef SPSEGMENT_NAIST boolean ok_p;#endif backtrellis = r->backtrellis; winfo = r->lm->winfo; /* look for the last trellis word */ if (r->lmtype == LM_PROB) { for (last_time = framelen - 1; last_time >= 0; last_time--) { maxscore = LOG_ZERO; for (i=0;i<backtrellis->num[last_time];i++) { tmp = backtrellis->rw[last_time][i];#ifdef WORD_GRAPH /* treat only words on a graph path */ if (!tmp->within_context) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -