📄 hrec.c
字号:
} } } /* Otherwise match with least likely rtok (creating if possible) */ if (mch==NULL) { if (res->n < pri->nToks) { mch=res->set+res->n++; *mch=rnull; } else mch=res->set+res->n-1; } /* When new rtok beats mch need to replace and re-sort */ if (like > mch->like) { for (mch--;like>mch->like;mch--) {#ifdef SANITY if (mch<=res->set) HError(8590,"TokSetMerge: Tried to shift max token");#endif mch[1]=mch[0]; } mch++; mch->path=cur->path;mch->lm=cur->lm; mch->like=like; } } /* Void lookup information */ for (i=0;i<nw;i++) nodes[i]->aux=0;}/* Caching version of SOutP used when mixPDFs shared */static LogFloat cSOutP(HMMSet *hset, int s, Observation *x, StreamElem *se, int id){ PreComp *pre; LogFloat bx,px,wt,det; int m,vSize; double sum; MixtureElem *me; TMixRec *tr; TMProb *tm; Vector v,tv; switch (hset->hsKind){ case PLAINHS: case SHAREDHS:/*当前执行此分支*/ v=x->fv[s]; me=se->spdf.cpdf+1; if (se->nMix==1){ /*当前执行此分支*//* Single Mixture Case */ if (me->mpdf->mIdx>0 && me->mpdf->mIdx<=pri->psi->nmp)/*当前不执行此分支*/ pre=pri->psi->mPre+me->mpdf->mIdx; else pre=NULL;/*当前执行此分支*/ if (pre==NULL) {/*当前执行此处*/ bx= MOutP(ApplyCompFXForm(me->mpdf,v,inXForm,&det,id),me->mpdf); bx += det; } else if (pre->id!=id) {/*当前不执行此分支*/ bx= MOutP(ApplyCompFXForm(me->mpdf,v,inXForm,&det,id),me->mpdf); bx += det; pre->id=id; pre->outp=bx; } else/*当前此分支不被执行*/ bx=pre->outp; } else {/*当前此分支不被执行*/ bx=LZERO; /* Multi Mixture Case */ for (m=1; m<=se->nMix; m++,me++) { wt = MixLogWeight(hset, me->weight); if (wt>LMINMIX) { if (me->mpdf->mIdx>0 && me->mpdf->mIdx<=pri->psi->nmp) pre=pri->psi->mPre+me->mpdf->mIdx; else pre=NULL; if (pre==NULL) { px= MOutP(ApplyCompFXForm(me->mpdf,v,inXForm,&det,id),me->mpdf); px += det; } else if (pre->id!=id) { px= MOutP(ApplyCompFXForm(me->mpdf,v,inXForm,&det,id),me->mpdf); px += det; pre->id=id; pre->outp=px; } else px=pre->outp; bx=LAdd(bx,wt+px); } }/*以上不被执行*/ } return bx; case TIEDHS: v = x->fv[s]; vSize = VectorSize(v); if (vSize != hset->swidth[s]) HError(7071,"SOutP: incompatible stream widths %d vs %d", vSize,hset->swidth[s]); sum = 0.0; tr = hset->tmRecs+s; tm = tr->probs+1; tv = se->spdf.tpdf; for (m=1; m<=tr->topM; m++,tm++) sum += tm->prob * tv[tm->index]; return (sum>=MINLARG)?log(sum)+tr->maxP:LZERO; default: HError(7071,"SOutP: bad hsKind %d\n",hset->hsKind); } return LZERO; /* to keep compiler happy */ }/* Version of POutP that caches outp values with frame id */static LogFloat cPOutP(PSetInfo *psi,Observation *obs,StateInfo *si,int id){ PreComp *pre; LogFloat outp; StreamElem *se; Vector w; int s,S; if (si->sIdx>0 && si->sIdx<=pri->psi->nsp)/*此分支被执行*/ pre=pri->psi->sPre+si->sIdx; else pre=NULL;/*此分支不被执行*/#ifdef SANITY if (pre==NULL) HError(8520,"cPOutP: State has no PreComp attached");#endif if (pre->id!=id) { /* 执行此分支bodged at the moment - fix !! */ if ((FALSE && psi->mixShared==FALSE) || (psi->hset->hsKind == DISCRETEHS)) {/*此分支不被执行*/ outp=POutP(psi->hset,obs,si); } else {/*当前执行此分支*/ S=obs->swidth[0]; if (S==1 && si->weights==NULL){/*当前执行此分支*/ outp=cSOutP(psi->hset,1,obs,si->pdf+1,id); } else {/*当前不执行此分支*/ outp=0.0; se=si->pdf+1; w=si->weights; for (s=1;s<=S;s++,se++){ outp+=w[s]*cSOutP(psi->hset,s,obs,se,id); } } } pre->outp=outp; pre->id=id; } return(pre->outp);}/* Move align record to (head of) YES referenced list */static void MoveAlignYesRef(Align *align){ align->link->knil=align->knil; align->knil->link=align->link; align->link=pri->aYesRef.link; align->knil=&pri->aYesRef; align->link->knil=align->knil->link=align;}/* Add reference to align record. *//* Moves record to YES referenced list when necessary */static void RefAlign(Align *align){ if (align->usage==0) { MoveAlignYesRef(align);#ifdef SANITY pri->anlen--;pri->aylen++;#endif } align->usage++;}/* Remove reference to align record, moving to */ /* (tail of) NO referenced list when necessary. */static void DeRefAlign(Align *align){#ifdef SANITY if (align->usage<0) HError(8591,"DeRefAlign: Align not referenced");#endif align->usage--; if (align->usage==0) { align->link->knil=align->knil; align->knil->link=align->link; align->knil=pri->aNoTail.knil; align->link=&pri->aNoTail; align->link->knil=align->knil->link=align;#ifdef SANITY pri->anlen++;pri->aylen--;#endif }}/* Allocate new align record and add to NOT referenced list */static Align *NewNRefAlign(NetNode *node,int state,double like, int frame,Align *prev){ Align *align; align=(Align*) New(&pri->alignHeap,0); align->link=pri->aNoRef.link; align->knil=&pri->aNoRef; align->link->knil=align->knil->link=align; align->usage=0; align->used=FALSE; align->node=node; align->state=state; align->like=like; align->frame=frame; if ((align->prev=prev)!=NULL) RefAlign(prev); pri->nalign++;#ifdef SANITY pri->anlen++;#endif return(align);}/* Remove and free align record from NO referenced list */static void UnlinkAlign(Align *align){ align->link->knil=align->knil; align->knil->link=align->link;#ifdef SANITY if (align->usage!=0) HError(8591,"UnlinkAlign: Freeing referenced align record"); align->link=align->knil=NULL; align->node=NULL;align->prev=0; align->usage=0;pri->anlen--;#endif Dispose(&pri->alignHeap,align); pri->nalign--;}static void StepHMM1(NetNode *node) /* Model internal propagation NBEST */{ NetInst *inst; HMMDef *hmm; Token tok,max; TokenSet *res,cmp,*cur; Align *align; int i,j,k,N,endi; LogFloat outp; Matrix trP; short **seIndex; inst=node->inst; max=null_token; hmm=node->info.hmm; N=hmm->numStates; trP=hmm->transP; seIndex=pri->psi->seIndexes[hmm->tIdx];/*hmm->tIdx是转移矩阵索引*/ for (j=2,res=pri->psi->sBuf+2;j<N;j++,res++) { /*res是第j个状态的TokenSet*/ /* Emitting states first */ i=seIndex[j][0]; /*seIndex[j][0]是当前模型中能够转到第j个状态的最小状态标号*/ endi=seIndex[j][1];/*se[j][1]是当前模型中能够转到第j个状态的最大状态标号*/ cur=inst->state+i-1;/*状态i的TokenSet*/ res->tok=cur->tok; res->n=cur->n;/*将第j个状态的TokenSet中似然度最大的tok设置为第i个状态似然度最大的tok,将第j个状态的TokenSet中的合法的识别tok数设置为第i个状态的TokenSet中的合法的识别tok数*/ for (k=0;k<cur->n;k++) res->set[k]=cur->set[k];/*循环将第j个状态NBEST tok 设置为第i个状态NBEST tok*/ res->tok.like+=trP[i][j];/*用第i个状态到第j个状态的转移概率更新第j个状态的TokenSet中似然度最大的tok的似然度*/ for (i++,cur++;i<=endi;i++,cur++) {/*从当前模型中能够转到第j个状态的最小状态标号到最大状态标号做循环*/ cmp.tok=cur->tok;/*取得第i的TokenSet中似然度最大的tok*/ cmp.tok.like+=trP[i][j];/*假设用第i个状态到第j个状态的转移概率更新第j个状态的TokenSet中似然度最大的tok的似然度*/ if (res->n==0) { if (cmp.tok.like > res->tok.like)/*如果大于第j个状态原有tok的似然度*/ res->tok=cmp.tok;/*则更新第j个状态tok的似然度*/ } else/*当前此处不被执行*/ TokSetMerge(res,&cmp.tok,cur); }/*第j个状态似然度最大的tok的计算到此完成,即计算论文:Token Passing: a Simple Conceptual Model for Connected Speech Recogntion Systems 中第4页公式(4),sj(t)=max{si(t-1)+logaij}+logbj(x)中求max部分*/ if (res->tok.like>pri->genThresh) { /* State pruning 状态剪枝*/
outp=cPOutP(pri->psi,pri->obs,hmm->svec[j].info,pri->id); res->tok.like+=outp;/*outp计算了HTKBOOK中公式(1.10)中e的指数部分,用输出概率更新第j个在状态似然度最大的tok*/ /*公式(4),sj(t)=max{si(t-1)+logaij}+logbj(x)计算已完成*/ if (res->tok.like>max.like) max=res->tok; if (pri->states) {/*当前此分支不被执行*/ if (res->tok.align==NULL?TRUE: res->tok.align->state!=j || res->tok.align->node!=node) { align=NewNRefAlign(node,j, res->tok.like-outp-res->tok.lm*pri->scale, pri->frame-1,res->tok.align); res->tok.align=align; } }/*以上部分不被执行*/ } else {/*此分支也有可能不执行*/ res->tok=null_token; res->n=((pri->nToks>1)?1:0); } }/*for (j=2,res=pri->psi->sBuf+2;j<N;j++,res++)循环结束*/ /* Null entry state ready for external propagation 为外部传播准备好空的入口状态*/ /* And copy tokens from buffer to instance 将tokens从缓冲区复制到实例中*/ for (i=1,res=pri->psi->sBuf+1,cur=inst->state; i<N;i++,res++,cur++) { cur->n=res->n; cur->tok=res->tok; for (k=0;k<res->n;k++) cur->set[k]=res->set[k]; } /* Set up pruning limits */ if (max.like>pri->genMaxTok.like) { pri->genMaxTok=max; pri->genMaxNode=node; } inst->max=max.like; i=seIndex[N][0]; /*seIndex[N][0]是当前模型中能够转到第N个状态的最小状态标号*//* Exit state (ignoring tee trP) */ endi=seIndex[N][1];/*seIndex[N][1]是当前模型中能够转到第N个状态的最大状态标号*/ res=inst->exit;/*inst->exit是节点对应网络的出口状态(exit状态)的TokenSet*/ cur=inst->state+i-1;/*inst第i个状态的TokenSet*/ res->n=cur->n;/*获取第i个状态的NBEST Token数*/ res->tok=cur->tok; /*获取第i个状态的似然度最大的tok*/ for (k=0;k<cur->n;k++) res->set[k]=cur->set[k];/*获取第i个状态的TokenSet*/ res->tok.like+=trP[i][N];/*用第i个状态到第N个状态的转移概率更新第N个状态的TokenSet中似然度最大的tok的似然度*/ /*当前i=4;i++=5;endi=4;已经大于endi,故下面的for循环不被执行*/ for (i++,cur++;i<=endi;i++,cur++) { cmp.tok=cur->tok; cmp.tok.like+=trP[i][N]; if (res->n==0) { if (cmp.tok.like > res->tok.like) res->tok=cmp.tok; } else{ TokSetMerge(res,&cmp.tok,cur);} }/*for循环结束*//*printf("\n当前的inst->wdlk=%f\n",inst->wdlk);*/ if (res->tok.like>LSMALL){ tok.like=res->tok.like+inst->wdlk;/*inst->wdlk为Max likelihood of t=0 path to word end node*/ if (tok.like > pri->wordMaxTok.like) { pri->wordMaxTok=tok; pri->wordMaxNode=node; } if (!node_tr0(node) && pri->models) { align=NewNRefAlign(node,-1, res->tok.like-res->tok.lm*pri->scale, pri->frame,res->tok.align); res->tok.align=align; } } else { inst->exit->tok=null_token; inst->exit->n=((pri->nToks>1)?1:0); }}/* Tee transition propagation - may be repeated */static void StepHMM2(NetNode *node) { NetInst *inst; HMMDef *hmm; TokenSet cmp,*res,*cur; Align *align; int N; inst=node->inst; hmm=node->info.hmm; N=hmm->numStates; cur=inst->state; res=inst->exit; cmp.tok=cur->tok; cmp.tok.like+=hmm->transP[1][N];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -