/* FloorDProbs: apply floor to given discrete prob set */ static void FloorDProbs(ShortVec mixes, int M, float floor) { float sum,fsum,scale,fltWt; int m; sum = fsum = 0.0; for (m=1; m<=M; m++) { fltWt = Short2DProb(mixes[m]); if (fltWt>floor) sum += fltWt; else { fsum += floor; mixes[m] = DProb2Short(floor); } } if (fsum>1.0) HError(2327,"FloorDProbs: Floor sum too large (%f)",fsum); if (fsum == 0.0) return; if (sum == 0.0) HError(2328,"FloorDProbs: No probabilities above floor"); scale = (1.0-fsum)/sum; for (m=1; m<=M; m++){ fltWt = Short2DProb(mixes[m]); if (fltWt>floor) mixes[m] = DProb2Short(fltWt*scale); } }
/* UpdateWeights: use acc values to calc new estimate of mix weights */ void UpdateWeights(HLink hmm) { int i,s,m,M=0,N; float x,occi; WALink wa; StateElem *se; StreamElem *ste; MLink q; q=FindMacroStruct(&hset,'h',hmm); N = hmm->numStates; se = hmm->svec+2; for (i=2; i<N; i++,se++){ ste = se->info->pdf+1; for (s=1;s<=nStreams; s++,ste++){ wa = (WALink)ste->hook; if (wa != NULL) { switch(hsKind){ case TIEDHS: M = hset.tmRecs[s].nMix; break; case DISCRETEHS: M = ste->nMix; break; } occi = wa->occ; if (occi>0) { for (m=1; m<=M; m++){ x = wa->c[m]/occi; if (x>1.0){ if (x>1.001) HError(-2490,"UpdateWeights: Model [%s]: mix too big in %d.%d.%d",q->id->name,i,s,m); x = 1.0; } switch (hsKind){ case TIEDHS: ste->spdf.tpdf[m] = (x>MINMIX) ? x : 0; break; case DISCRETEHS: ste->spdf.dpdf[m] = (x>MINMIX) ? DProb2Short(x) :DLOGZERO; break; } } if (mixWeightFloor>0.0){ switch (hsKind){ case DISCRETEHS: FloorDProbs(ste->spdf.dpdf,M,mixWeightFloor); break; case TIEDHS: FloorTMMixes(ste->spdf.tpdf,M,mixWeightFloor); break; } } }else HError(-2427,"UpdateWeights: Model [%s]: no use of mixtures in %d.%d",q->id->name,i,s); ste->hook = NULL; } } } }
/* UpDProbs: update given mixture weights */ void UpDProbs(int i, int s, int M, WtAcc *wa, ShortVec dw) { int m; float x,sum=0.0; if (wa->occ == 0.0) HError(2127,"UpDProbs: zero occ i=%d/s=%d",i,s); for (m=1; m<=M; m++){ sum += wa->c[m]; x = wa->c[m] / wa->occ; if (x<mixWeightFloor) x = mixWeightFloor; dw[m] = DProb2Short(x); } if (fabs(sum-wa->occ)/sum > 0.001) HError(2190,"UpDProbs: dprob weight sum error"); }
/* UniformSegment: and cluster within each state/segment */ void UniformSegment(void) { Sequence **seqMat; /* Matrix [2..numStates-1][1..numStreams]*/ Sequence seq; int count,size,i,s,n,m,M,j,k; long int vqidx; ClusterSet *cset; Cluster *c; StreamElem *ste; Covariance cov; CovKind ck; MixPDF *mp; TMixRec *tmRec = NULL; ShortVec dw; float x,z; Vector floor; if (trace & T_UNI) printf(" Uniform Segmentation\n"); seqMat = CreateSeqMat(); cov.var = NULL; /* dummy */ UCollectData(seqMat); if (trace&T_UNI) ShowSeqMat(seqMat); /* Cluster Each State/Stream and Init HMM Parms */ for (n=2; n<nStates; n++) { if (trace&T_UNI) printf(" state %d ",n); for (s=1; s<=nStreams; s++){ size = hset.swidth[s]; floor = vFloor[s]; ste = hmmLink->svec[n].info->pdf+s; if (hset.hsKind == TIEDHS){ tmRec = &(hset.tmRecs[s]); M = tmRec->nMix; tmRec->topM = tmRec->nMix; } else M = ste->nMix; if (trace&T_UNI) printf(" stream %d\n",s); seq = seqMat[n][s]; switch (hset.hsKind){ case PLAINHS: case SHAREDHS: ck = ste->spdf.cpdf[1].mpdf->ckind; cset = FlatCluster(&clustSetStack,seq,M,NULLC,ck,cov); if (trace&T_UNI) ShowClusterSet(cset); for (m=1; m<=M; m++){ mp = ste->spdf.cpdf[m].mpdf; if (mp->ckind != ck) HError(2123,"UniformSegment: different covkind within a mix\n"); c = cset->cl+m; if (uFlags&UPMIXES) ste->spdf.cpdf[m].weight = (float)c->csize/(float)seq->nItems; if (uFlags&UPMEANS) CopyVector(c->vCtr,mp->mean); if (uFlags&UPVARS) switch(ck){ case DIAGC: for (j=1; j<=size; j++){ z= c->cov.var[j]; mp->cov.var[j] = (z<floor[j])?floor[j]:z; } break; case FULLC: for (j=1; j<=size; j++){ for (k=1; k<j; k++) { mp->cov.inv[j][k] = c->cov.inv[j][k]; } z = c->cov.inv[j][j]; mp->cov.inv[j][j] = (z<floor[j])?floor[j]:z; } break; default: HError(2124,"UniformSegment: bad cov kind %d\n",ck); } } break; case DISCRETEHS: count = 0; dw = ste->spdf.dpdf; ZeroShortVec(dw); for (i=1; i<=seq->nItems; i++){ vqidx = (long int)GetItem(seq,i); if (vqidx<1 || vqidx>M) HError(2170,"UniformSegment: vqidx out of range[%ld]",vqidx); ++dw[vqidx]; ++count; } for (m=1; m<=M; m++){ x = (float)dw[m]/(float)count; if (x<mixWeightFloor) x = mixWeightFloor; dw[m] = DProb2Short(x); } break; case TIEDHS: ck = tmRec->mixes[1]->ckind; cset = FlatCluster(&clustSetStack,seq,M,NULLC,ck,cov); if (trace&T_UNI) ShowClusterSet(cset); for (m=1; m<=M; m++){ mp = tmRec->mixes[m]; if (mp->ckind != ck) HError(2123,"UniformSegment: different covkind within a mix\n"); c = cset->cl+m; if (uFlags&UPMIXES) ste->spdf.tpdf[m] = (float)c->csize/(float)seq->nItems; if (uFlags&UPMEANS) CopyVector(c->vCtr,mp->mean); if (uFlags&UPVARS) switch(ck){ case DIAGC: for (j=1; j<=size; j++){ z= c->cov.var[j]; mp->cov.var[j] = (z<floor[j])?floor[j]:z; } break; case FULLC: for (j=1; j<=size; j++){ for (k=1; k<j; k++) { mp->cov.inv[j][k] = c->cov.inv[j][k]; } z = c->cov.inv[j][j]; mp->cov.inv[j][j] = (z<floor[j])?floor[j]:z; } break; default: HError(2124,"UniformSegment: bad cov kind %d\n",ck); } } break; } ResetHeap(&clustSetStack); } if ((hset.hsKind == PLAINHS) || (hset.hsKind == SHAREDHS)) FixGConsts(hmmLink); } ResetHeap(&sequenceStack); }
/* UpdateWeights: use acc values to calc new estimate of mix weights */ static void UpdateWeights(HMMSet *hset, int px, HLink hmm) { int i,s,m,M=0,N,vSize; float x,occi,denom,tmp; WtAcc *wa; StateElem *se; StreamElem *ste; MixtureElem *me; N = hmm->numStates; se = hmm->svec+2; for (i=2; i<N; i++,se++){ ste = se->info->pdf+1; for (s=1;s<=S; s++,ste++){ wa = (WtAcc *)ste->info->hook; switch (hset->hsKind){ case TIEDHS: M=hset->tmRecs[s].nMix; break; case DISCRETEHS: case PLAINHS: case SHAREDHS: M=ste->info->nMix; break; } if (wa != NULL) { occi = wa->occ; if (occi>0) { me = ste->info->spdf.cpdf + 1; denom=0; for (m=1; m<=M; m++,me++){ vSize = VectorSize(me->mpdf->mean); tmp = me->weight*vSize*mapTau -1; if (tmp<0) tmp = 0; denom += tmp; } me = ste->info->spdf.cpdf + 1; for (m=1; m<=M; m++,me++){ vSize = VectorSize(me->mpdf->mean); tmp = me->weight*vSize*mapTau -1; if (tmp<0) tmp = 0; x = (tmp + wa->c[m])/(denom + occi); if (x>1.0){ if (x>1.001) HError(2393,"UpdateWeights: Model %d[%s]: mix too big in %d.%d.%d %5.5f", px,HMMPhysName(hset,hmm),i,s,m,x); x = 1.0; } switch (hset->hsKind){ case TIEDHS: ste->info->spdf.tpdf[m] = x; break; case DISCRETEHS: ste->info->spdf.dpdf[m]=DProb2Short(x); break; case PLAINHS: case SHAREDHS: me=ste->info->spdf.cpdf+m; me->weight = x; break; } } if (mixWeightFloor>0.0){ FloorMixtures(hset->hsKind,ste->info,M,mixWeightFloor); } /* Force a normalisation becomes of weird zeroing .... */ if ((hset->hsKind == PLAINHS) || (hset->hsKind == SHAREDHS)) { me = ste->info->spdf.cpdf + 1; x=0; for (m=1; m<=M; m++,me++) x += me->weight; if (x>1.001) HError(-1,"Updating Weights, sum too large (%f)\n",x); me = ste->info->spdf.cpdf + 1; for (m=1; m<=M; m++,me++) me->weight /= x; } } ste->info->hook = NULL; } } } }
case 'l': maxSpUtt = GetChkedInt(0,0100000,s); break; case 'E': if (NextArg()!=STRINGARG) HError(2319,"HERest: parent transform directory expected"); xfInfo.usePaXForm = TRUE; xfInfo.paXFormDir = GetStrArg(); if (NextArg()==STRINGARG) xfInfo.paXFormExt = GetStrArg(); if (NextArg() != SWITCHARG) HError(2319,"HERest: cannot have -E as the last option"); break; case 'J': if (NextArg()!=STRINGARG) HError(2319,"HERest: input transform directory expected"); AddInXFormDir(&hset,GetStrArg()); if (NextArg()==STRINGARG) { if (xfInfo.inXFormExt == NULL) xfInfo.inXFormExt = GetStrArg(); else HError(2319,"HERest: only one input transform extension may be specified"); } if (NextArg() != SWITCHARG) HError(2319,"HERest: cannot have -J as the last option"); break; case 'K': if (NextArg()!=STRINGARG) HError(2319,"HERest: output transform directory expected"); xfInfo.outXFormDir = GetStrArg(); if (NextArg()==STRINGARG) xfInfo.outXFormExt = GetStrArg(); if (NextArg() != SWITCHARG) HError(2319,"HERest: cannot have -K as the last option"); break; case 'z': if (NextArg() != STRINGARG) HError(2319,"HERest: output TMF file expected");