📄 hhed.c
字号:
/* SplitMix: split given mix mi into two */void SplitMix(MixtureElem *mi,MixtureElem *m01,MixtureElem *m02,int vSize){ const float pertDepth = 0.2; int k,splitcount; float x; TriMat mat=NULL; splitcount = (int) mi->mpdf->hook + 1; m01->mpdf = CloneMixPDF(hset,mi->mpdf,FALSE); m02->mpdf = CloneMixPDF(hset,mi->mpdf,FALSE); m01->weight = m02->weight = mi->weight/2.0; m01->mpdf->hook = m02->mpdf->hook = (void *)splitcount; if (mi->mpdf->ckind==FULLC || mi->mpdf->ckind==LLTC) { mat = CreateTriMat(&tmpHeap,vSize); CovInvert(mi->mpdf->cov.inv,mat); } for (k=1;k<=vSize;k++) { /* perturb them */ if (mi->mpdf->ckind == FULLC || mi->mpdf->ckind==LLTC) x = sqrt(mat[k][k])*pertDepth; else x = sqrt(mi->mpdf->cov.var[k])*pertDepth; m01->mpdf->mean[k] += x; m02->mpdf->mean[k] -= x; } if (mat!=NULL) FreeTriMat(&tmpHeap,mat);}/* FixWeights: Fix the weights of me using the old stream info */void FixWeights(MixtureElem *me, HMMDef *owner, StreamElem *ste){ MixtureElem *sme; double w,p,wSum,fSum,maxW,floor,lFloor; int i=0,m,sm; if (trace & T_DET) printf(" For %-12s ",HMMPhysName(hset,owner)); maxW = LZERO; for (m=1;m<=joinSize;m++) { /* set weights to SOutP(owner) */ w=LZERO; for (sm=1,sme=ste->spdf.cpdf+1;sm<=ste->nMix;sm++,sme++) { Untouch(&me[m].mpdf->nUse); p = MOutP(me[m].mpdf->mean,sme->mpdf); w = LAdd(w,log(sme->weight)+p); } me[m].weight = w; if (w > maxW) maxW = w; } wSum = 0.0; fSum = 0.0; floor = joinFloor*MINMIX; lFloor = log(floor*joinSize); for (m=1;m<=joinSize;m++) { /* make all weights > floor */ w = me[m].weight-maxW; if (w < lFloor) { me[m].weight = floor; fSum += floor; } else { w = exp(w); me[m].weight = w; wSum += w; } } if (fSum>=0.9) HError(2634,"FixWeights: Join Floor too high"); if (wSum==0.0) HError(2691,"FixWeights: No positive weights"); wSum /= (1-fSum); /* finally normalise */ for (m=1;m<=joinSize;m++) { w = me[m].weight; if (w>floor) { w /= wSum; me[m].weight = w; if (trace & T_DET) { if ((++i%4)==0) printf("\n "); printf(" %3d == %7.4e",m,w); } } } if (trace & T_DET) { printf("\n"); fflush(stdout); }}/* Create macros for each mix in joinSet & reset nUse */void CreateJMacros(LabId rootMacId){ int m; char buf[255]; MixPDF *mp; for (m=1;m<=joinSize;m++) { sprintf(buf,"%s%d",rootMacId->name,m); mp = joinSet[m].mpdf; mp->nUse = 0; NewMacro(hset,fidx,'m',GetLabId(buf,TRUE),mp); if (trace & (T_DET | T_MAC)) { printf(" Join Macro: ~m:%s created\n",buf); fflush(stdout); } }}/* TiePDF: join mixtures for set of 'joinSize' tied pdfs in ilist This is standard 'tied mixture' case. Min mix weight is joinFloor * MINMIX */void TiePDF(ILink ilist, LabId macId){ ILink i; int m,nSplit,vs,vSize=0; StreamElem *ste; MixtureElem *me, mix,mix1,mix2; if (badGC) { FixAllGConsts(hset); /* in case any bad gConsts around */ badGC=FALSE; } if (joinSize==0) HError(2634,"TiePDF: Join size and floor not set - use JO command"); nJoins = 0; joinSet = CreateJMixSet(); for (i=ilist; i!=NULL; i=i->next) { ste = (StreamElem *) i->item; vs = VectorSize(ste->spdf.cpdf[1].mpdf->mean); if (vSize==0) vSize = vs; else if (vs != vSize) HError(2630,"TiePDF: incompatible vector sizes %d vs %d",vs,vSize); for (m=1;m<=ste->nMix;m++) { me = ste->spdf.cpdf+m; if (IsSeen(me->mpdf->nUse)) continue; Touch(&me->mpdf->nUse); /* Make sure we don't add twice */ AddJMix(me); } } if (trace & T_BID) { printf(" Joined %d mixtures.",nJoins); if (nJoins==joinSize) printf(" [Full set]\n"); else printf(" [%d more needed]\n",joinSize-nJoins); fflush(stdout); } nSplit=0; while (nJoins<joinSize) { /* split best mixes if needed */ mix = RemTop(); SplitMix(&mix,&mix1,&mix2,vSize); AddJMix(&mix1); AddJMix(&mix2); ++nSplit; } CreateJMacros(macId); for (i=ilist; i!=NULL; i=i->next) { /* replace pdfs */ ste = (StreamElem *) i->item; if (IsSeen(ste->nMix)) continue; me = CreateJMixSet(); for (m=1;m<=joinSize;m++) { me[m].mpdf = joinSet[m].mpdf; ++(joinSet[m].mpdf->nUse); } FixWeights(me,i->owner,ste); ste->spdf.cpdf = me; ste->nMix = joinSize; Touch(&ste->nMix); } for (i=ilist; i!=NULL; i=i->next) { /* reset nMix flags */ ste = (StreamElem *) i->item; Untouch(&ste->nMix); } if (joinSize>maxMixes) maxMixes=joinSize;}/* TieHMMs: tie all hmms in ilist to 1st */void TieHMMs(ILink ilist,LabId macId){ ILink i; HLink hmm,cur; MLink q; int h,c,j; char type; hmm=ilist->owner; /* get first in list */ q=FindMacroStruct(hset,'h',hmm); DeleteMacro(hset,q); NewMacro(hset,fidx,'h',macId,hmm); for (i=ilist->next,c=1; i!=NULL; i=i->next,c++) i->owner->owner=NULL; hmm->owner=hset; /* In case of duplicates in ilist */ for (h=0,j=0; h<MACHASHSIZE; h++) for (q=hset->mtab[h]; q!=NULL; q=q->next) { if (q->type!='h' && q->type!='l') continue; cur = (HLink) q->structure; if (cur->owner==NULL) { type = q->type; DeleteMacro(hset,q); if (type=='l') NewMacro(hset,fidx,'l',q->id,hmm); hmm->nUse++; j++; } }}/* ApplyTie: tie all structures in list of give type */void ApplyTie(ILink ilist, char *macName, char type){ LabId macId; int use; if (ilist == NULL) { HError(-2631,"ApplyTie: Macro %s has nothing to tie of type %c", macName,type); return; } macId = GetLabId(macName,TRUE); switch (type) { case 's': TieState(ilist,macId); break; case 't': TieTrans(ilist,macId); break; case 'm': TieMix(ilist,macId); break; case 'u': TieMean(ilist,macId); break; case 'v': TieVar(ilist,macId); break; case 'i': TieInv(ilist,macId); break; case 'x': TieXform(ilist,macId); break; case 'p': TiePDF(ilist,macId); break; case 'w': TieWeights(ilist,macId); break; case 'd': TieDur(ilist,macId); break; case 'h': TieHMMs(ilist,macId); break; } if ((trace & (T_DET | T_MAC)) && type!='p') { use=GetMacroUse(FindMacroName(hset,type,macId)); printf(" Macro: ~%c:%s created for %d/%d items\n", type,macName,use,NumItems(ilist)); fflush(stdout); }}/* ------------------ Untying Operations --------------------- *//* UntieState: untie (ie clone) all items in ilist */void UntieState(ILink ilist){ ILink i; StateElem *se; StateInfo *si; int nu; for (i=ilist; i!=NULL; i=i->next) { se = (StateElem *)i->item; si = se->info; nu = si->nUse; si->nUse = 0; if (nu==1) DeleteMacroStruct(hset,'s',si); else if (nu>1) { se->info = CloneState(hset,si,FALSE); si->nUse = nu-1; } }}/* UntieMix: untie (ie clone) all items in ilist */void UntieMix(ILink ilist){ ILink i; MixtureElem *me; MixPDF *mp; int nu,vSize; for (i=ilist; i!=NULL; i=i->next) { me = (MixtureElem *)i->item; if (me->weight > MINMIX) { mp = me->mpdf; vSize = VectorSize(mp->mean); nu = mp->nUse; mp->nUse = 0; if (nu==1) DeleteMacroStruct(hset,'m',mp); else if (nu>1) { me->mpdf = CloneMixPDF(hset,mp,FALSE); mp->nUse = nu-1; } } }}/* UntieMean: untie (ie clone) all items in ilist */void UntieMean(ILink ilist){ ILink i; MixPDF *mp; Vector v; int nu; for (i=ilist; i!=NULL; i=i->next) { mp = (MixPDF *)i->item; v = mp->mean; nu = GetUse(v); SetUse(v,0); if (nu==1) DeleteMacroStruct(hset,'u',v); else if (nu>1) { mp->mean = CloneSVector(hset->hmem,v,FALSE); SetUse(v,nu-1); } }}/* UntieVar: untie (ie clone) all items in ilist */void UntieVar(ILink ilist){ ILink i; MixPDF *mp; Vector v; int nu; for (i=ilist; i!=NULL; i=i->next) { mp = (MixPDF *)i->item; v = mp->cov.var; nu = GetUse(v); SetUse(v,0); if (nu==1) DeleteMacroStruct(hset,'v',v); else if (nu>1) { mp->cov.var = CloneSVector(hset->hmem,v,FALSE); SetUse(v,nu-1); } }}/* UntieInv: untie (ie clone) all items in ilist */void UntieInv(ILink ilist){ ILink i; MixPDF *mp; SMatrix m; int nu; for (i=ilist; i!=NULL; i=i->next) { mp = (MixPDF *)i->item; m = mp->cov.inv; nu = GetUse(m); SetUse(m,0); if (nu==1) DeleteMacroStruct(hset,'i',m); else if (nu>1) { mp->cov.inv = CloneSTriMat(hset->hmem,m,FALSE); SetUse(m,nu-1); } }}/* UntieXform: untie (ie clone) all items in ilist */void UntieXform(ILink ilist){ ILink i; MixPDF *mp; SMatrix m; int nu; for (i=ilist; i!=NULL; i=i->next) { mp = (MixPDF *)i->item; m = mp->cov.xform; nu = GetUse(m); SetUse(m,0); if (nu==1) DeleteMacroStruct(hset,'x',m); else if (nu>0) { mp->cov.xform = CloneSMatrix(hset->hmem,m,FALSE); SetUse(m,nu-1); } }}/* UntieTrans: untie (ie clone) all items in ilist */void UntieTrans(ILink ilist){ ILink i; HMMDef *hmm; SMatrix m; int nu; for (i=ilist; i!=NULL; i=i->next) { hmm = (HMMDef *)i->item; m = hmm->transP; nu = GetUse(m); SetUse(m,0); if (nu==1) DeleteMacroStruct(hset,'t',m); else if (nu>0) { hmm->transP = CloneSMatrix(hset->hmem,m,FALSE); SetUse(m,nu-1); } }}/* -------------------- Cluster Operations --------------------- */typedef struct _CRec *CLink;typedef struct _CRec{ ILink item; /* a single item in this cluster (group) */ int idx; /* index of this item */ Boolean ans; /* answer to current question */ short state; /* state of clink */ CLink next; /* next item in group */}CRec;/* TDistance: return mean sq diff between Tied Mix weights */float TDistance(StreamElem *s1, StreamElem *s2){ int m,M; float *mw1,*mw2; float x,sum=0.0; mw1 = s1->spdf.tpdf+1; mw2 = s2->spdf.tpdf+1; M = s1->nMix; for (m=1; m<=M; m++, mw1++, mw2++) { x = (*mw1 - *mw2); sum += x*x; } return sqrt(sum/M);}/* DDistance: return mean sq log diff between Discrete Probabilities */float DDistance(StreamElem *s1, StreamElem *s2){ int m,M; short *mw1,*mw2; float x,sum=0.0; mw1 = s1->spdf.dpdf+1; mw2 = s2->spdf.dpdf+1; M = s1->nMix; for (m=1; m<=M; m++, mw1++, mw2++) { x = (*mw1 - *mw2); sum += x*x; } return sqrt(sum/M);}/* Divergence: return divergence between two Gaussians */float Divergence(StreamElem *s1, StreamElem *s2){ int k,V; MixPDF *m1,*m2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -