⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hrec.c

📁 实现HMM算法
💻 C
📖 第 1 页 / 共 5 页
字号:
            }         }      }      /* 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 + -