Colin Champion

Summary: this page contains the subroutine slopingbw to estimate the parameters of a sloping loudness model using the Baum-Welch algorithm. The test program illustrates its use.

doc : source : header : test : download & index

slopingbw has a header file which defines a slopingstats structure for the sufficient statistics needed by slopingbw. You may pass the statistics either through a structure as thus defined (recommended) or through several arrays. The prototypes are

double slopingbw(slopingstats s,double *mu,double **zb,double **zw,
                 double *muhat,double **zbhat,double **zwhat,int niter) ;
double slopingbw(int m,int n,double **S,double **ybar,double **ybardash,
                 int *ni,double *mu,double **zb,double **zw,
                 double *muhat,double **zbhat,double **zwhat,int niter) ;

where

If niter>0 then that many iterations will be performed and the return value will correspond to the parameters on entry to the final iteration. If niter=0 then no reestimation will be performed: the log pdf will be computed for the supplied parameters and the ‘hat’ parameters will be ignored (set the corresponding pointers to 0 to avoid confusion). The ‘hat’ parameters may be the same arrays as the initial estimates if you want to overwrite.

For efficiency sort the sequences by length before calling slopingbw (using the sort function in slopingbw.h.

You could perform a Newton-Raphson hillclimb on the log pdf values, but – quite apart from the question of whether Baum-Welch would be faster – you should remember that the optimum mean is easily obtainable analytically from estimated variances, so the hillclimb can be performed on a reduced space.

slopingbw.h provides the following functions.

Call

  s = slopingstats(int m) ;

to construct an empty stats structure for dimension m. (s = slopingstats() ; generates a completely empty structure).

Call

  s.take(double **y,int n) ;

to accumulate information from a single group comprising n m-long observations for which the ith dimension of the tth observation is stored as y[t][i].

Call

  s.sort() ;

to sort the observations in increasing order of group size.

Call

  s.release() ;

to free all space allocated.

See the test program for an example of its use. Note that you need to include ij.h before slopingbw.h.

#include "memory.h" #include <math.h> double logcholesky(double **a,double **b,int n) ; double cholesky(double **a,double **b,int n) ; static double log2pi=log(2*3.141592653589793) ; double slopingbw(int m,int N,double **S,double **ybar,double **ybardash, int *ni,double *mu,double **zb,double **zw, double *muhat,double **zbhat,double **zwhat,int niter) { int i,j,k,t,mdash=m+1,ono,reest,dopdf,iterno,NL,NS,mlim ; double n0,n1,n2,ndot,*edot=vector(m),edotdot,qret,q,logalphadet ; double **E=matrix(mdash,mdash),*ydash=vector(mdash),*a=vector(mdash) ; double **alpha=matrix(mdash,mdash),*muzb=vector(mdash) ; double **e=matrix(m,m),**zbinv=matrix(mdash,mdash),**alphainv=alpha,**Einv=E ; double logzwdet,logzbdet,logzbxxdet,*mux=vector(mdash) ; double **a0=matrix(mdash,mdash),**a1=matrix(mdash,mdash) ; double **zbxxinv,**zbxxhat,*muzbxx,*muxhat ; for(ndot=NL=NS=t=0;t<N;t++) { if(ni[t]==1) NS += 1 ; else NL += 1 ; ndot += ni[t] ; } if(NS>0) { zbxxinv = matrix(m,m) ; zbxxhat = matrix(m,m) ; muzbxx = vector(m) ; muxhat = vector(m) ; } for(iterno=0;iterno<niter||iterno==0;iterno++) { reest = (iterno<niter) ; dopdf = (iterno>=niter-1) ; if(iterno==0) { for(i=0;i<mdash;i++) for(j=0;j<mdash;j++) zbinv[i][j] = zb[i][j] ; for(i=0;i<m;i++) for(j=0;j<m;j++) e[i][j] = zw[i][j] ; } else { for(i=0;i<mdash;i++) for(j=0;j<mdash;j++) zbinv[i][j] = zbhat[i][j] ; for(i=0;i<m;i++) for(j=0;j<m;j++) e[i][j] = zwhat[i][j] ; } logzwdet = logcholesky(e,e,m) ; if(NS>0) // block inversion of zb { logzbxxdet = logcholesky(zbinv,zbxxinv,m) ; for(i=0;i<m;i++) for(a[i]=j=0;j<m;j++) a[i] += zbxxinv[i][j] * zbinv[j][m] ; for(q=zbinv[m][m],i=0;i<m;i++) q -= zbinv[i][m] * a[i] ; logzbdet = logzbxxdet + log(q) ; zbinv[m][m] = q = 1/q ; for(i=0;i<m;i++) for(j=0;j<m;j++) zbinv[i][j] = zbxxinv[i][j] + q*a[i]*a[j] ; for(i=0;i<m;i++) zbinv[i][m] = zbinv[m][i] = -q*a[i] ; } else { logzbdet = logcholesky(zbinv,zbinv,mdash) ; logzbxxdet = 0 ; } /*----------------------------------------------------------------------- */
/*page*/ /*----------------------------------------------------------------------- */ for(i=0;i<m;i++) for(edot[i]=j=0;j<m;j++) edot[i] += e[i][j] ; for(edotdot=i=0;i<m;i++) edotdot += edot[i] ; for(i=0;i<mdash;i++) mux[i] = mu[i] ; if(dopdf) { qret = NL*logzbdet + NS*logzbxxdet + ndot*(logzwdet+m*log2pi) ; for(i=0;i<m;i++) for(j=0;j<m;j++) qret += e[i][j] * S[i][j] ; } if(reest) { for(i=0;i<m;i++) for(j=0;j<m;j++) zwhat[i][j] = S[i][j] ; for(i=0;i<mdash;i++) for(j=0;j<mdash;j++) zbhat[i][j] = 0 ; for(i=0;i<mdash;i++) for(muzb[i]=j=0;j<mdash;j++) muzb[i] += mux[j] * zbinv[i][j] ; for(i=0;i<mdash;i++) muhat[i] = 0 ; // may overwrite mu - beware! if(NS) { for(i=0;i<m;i++) for(muzbxx[i]=j=0;j<m;j++) muzbxx[i] += mux[j] * zbxxinv[i][j] ; for(i=0;i<m;i++) for(j=0;j<m;j++) zbxxhat[i][j] = 0 ; for(i=0;i<m;i++) muxhat[i] = 0 ; } } for(ono=-1,t=0;t<N;ono=ni[t],t++) if(ni[t]>0) { if(ono!=ni[t]&&ni[t]==1) { n0 = 1 ; for(i=0;i<m;i++) for(j=0;j<m;j++) alphainv[i][j] = e[i][j] + zbxxinv[i][j] ; logalphadet = -logcholesky(alphainv,alpha,m) ; if(dopdf) { for(i=0;i<m;i++) for(k=0;k<m;k++) { for(q=j=0;j<m;j++) q += e[i][j] * alpha[j][k] ; a0[i][k] = q ; } for(i=0;i<m;i++) for(k=0;k<m;k++) { for(q=j=0;j<m;j++) q += a0[i][j] * zbxxinv[j][k] ; a1[i][k] = q ; } } } if(ono!=ni[t]&&ni[t]>1) // terms whose cost is cubic in m are shared ... { n0 = ni[t] ; // ... between all groups of the same length n1 = n0*(n0-1)/2 ; n2 = n1*(2*n0-1)/3 ; // compute E for(i=0;i<m;i++) for(j=0;j<m;j++) E[i][j] = n0 * e[i][j] ; for(i=0;i<m;i++) E[i][m] = E[m][i] = n1 * edot[i] ; E[m][m] = n2 * edotdot ; // compute alpha for(i=0;i<mdash;i++) for(j=0;j<mdash;j++) alphainv[i][j] = E[i][j] + zbinv[i][j] ; logalphadet = -logcholesky(alphainv,alpha,mdash) ; if(dopdf) { for(i=0;i<mdash;i++) for(k=0;k<mdash;k++) { for(q=j=0;j<mdash;j++) q += E[i][j] * alpha[j][k] ; a0[i][k] = q ; } for(i=0;i<mdash;i++) for(k=0;k<mdash;k++) { for(q=j=0;j<mdash;j++) q += a0[i][j] * zbinv[j][k] ; a1[i][k] = q ; } cholesky(E,Einv,mdash) ; } } /*--------------------------------------------------------------------- */
/*page*/ /*--------------------------------------------------------------------- */ // compute ydash for(i=0;i<m;i++) for(ydash[i]=j=0;j<m;j++) ydash[i] += n0 * e[i][j] * ybar[t][j] ; if(n0>1) for(ydash[m]=i=0;i<m;i++) ydash[m] += n1 * edot[i] * ybardash[t][i] ; // compute pdf if(dopdf) { qret -= logalphadet ; if(n0==1) { for(i=0;i<m;i++) a[i] = mux[i] - ybar[t][i] ; for(i=0;i<m;i++) for(j=0;j<m;j++) qret += a[i] * a1[i][j] * a[j] ; } else { for(i=0;i<mdash;i++) for(a[i]=mux[i],j=0;j<mdash;j++) a[i] -= ydash[j] * Einv[i][j] ; for(i=0;i<mdash;i++) for(j=0;j<mdash;j++) qret += a[i] * a1[i][j] * a[j] ; for(q=i=0;i<m;i++) q += (ybar[t][i]-ybardash[t][i]) * edot[i] ; qret -= 6*n1*q*q / ((n0+1)*edotdot) ; } } if(reest==0) continue ; // compute a if(n0==1) for(i=0;i<m;i++) for(a[i]=j=0;j<m;j++) a[i] += (ydash[j]+muzbxx[j]) * alpha[i][j] ; else for(i=0;i<mdash;i++) for(a[i]=j=0;j<mdash;j++) a[i] += (ydash[j]+muzb[j]) * alpha[i][j] ; // update zwhat (first step, for all sequence lengths) for(i=0;i<m;i++) for(j=0;j<m;j++) zwhat[i][j] += n0 * ( (a[i]-ybar[t][i])*(a[j]-ybar[t][j]) + alpha[i][j] ) ; // reestimation: update muhat, zbhat if(n0==1) { for(i=0;i<m;i++) muxhat[i] += a[i] ; for(i=0;i<m;i++) for(j=0;j<m;j++) zbxxhat[i][j] += a[i]*a[j] + alpha[i][j] ; } else { for(i=0;i<mdash;i++) muhat[i] += a[i] ; for(i=0;i<mdash;i++) for(j=0;j<mdash;j++) zbhat[i][j] += a[i]*a[j] + alpha[i][j] ; for(i=0;i<m;i++) a[i] = a[m] * ( a[i]-ybardash[t][i] ) ; // update zwhat (second step) for(i=0;i<m;i++) for(j=0;j<m;j++) zwhat[i][j] += n1 * ( a[i] + a[j] + alpha[i][m] + alpha[j][m] ) + n2 * ( a[m]*a[m] + alpha[m][m] ) ; } } /*----------------------------------------------------------------------- */
/*page*/ /*----------------------------------------------------------------------- */ if(reest==0) continue ; // put new estimates together for(i=0;i<m;i++) for(j=0;j<m;j++) zwhat[i][j] /= ndot ; for(i=0;i<mdash;i++) muhat[i] /= NL ; for(i=0;i<mdash;i++) for(j=0;j<mdash;j++) zbhat[i][j] -= NL*muhat[i]*muhat[j] ; if(NS==0) { for(i=0;i<mdash;i++) for(j=0;j<mdash;j++) zbhat[i][j] /= N ; continue ; } for(i=0;i<m;i++) { muxhat[i] /= NS ; a[i] = muxhat[i] - muhat[i] ; } for(i=0;i<m;i++) for(j=0;j<m;j++) zbxxhat[i][j] += NL*NS*a[i]*a[j]/N - NS*muxhat[i]*muxhat[j] ; // zbhat is V, zbxxhat is W cholesky(zbhat,zbinv,m) ; // compute zbinv as 1/Vxx for(i=0;i<m;i++) for(j=0;j<m;j++) // new zetaBhat|xx zbhat[i][j] = (zbhat[i][j]+zbxxhat[i][j]) / N ; for(i=0;i<m;i++) for(a[i]=j=0;j<m;j++) a[i] += zbhat[j][m] * zbinv[i][j] ; // Vsx*(1/Vxx) for(i=0;i<m;i++) // (Vsx/Vxx)*zetaBxxhat { for(q=j=0;j<m;j++) q += a[j] * zbhat[i][j] ; zbhat[i][m] = q ; } for(q=i=0;i<m;i++) for(j=0;j<m;j++) q += a[i] * zbxxhat[i][j] * a[j] ; zbhat[m][m] = zbhat[m][m]/NL + q/N ; for(q=i=0;i<m;i++) q += a[i] * zbhat[m][i] ; //zbhat[m][] is Vsx zbhat[m][m] -= NS*q/(N*(double)NL) ; for(i=0;i<m;i++) zbhat[m][i] = zbhat[i][m] ; // zbhat now contains new estimate of zetab; sort out the mean cholesky(zbhat,zbinv,m) ; // compute zbinv as 1/zetaBxxhat for(i=0;i<m;i++) muhat[i] = (NL*muhat[i]+NS*muxhat[i]) / N ; for(i=0;i<m;i++) for(j=0;j<m;j++) muhat[m] -= NS * (muhat[i]-muxhat[i]) * zbinv[i][j] * zbhat[j][m] / NL ; } // free workspace free(edot,ydash,a,muzb,mux) ; freematrix(e,zbinv,E,alpha,a0,a1) ; if(NS>0) { freematrix(zbxxinv,zbxxhat) ; free(muzbxx,muxhat) ; } return -qret / (2*ndot) ; } /*--------------------------------------------------------------------------- */

• slopingstats     • take     • release     • sort     • slopingbw

double slopingbw(int m,int n,double **S,double **ybar,double **ybardash, int *ni,double *mu,double **zb,double **zw, double *muhat,double **zbhat,double **zwhat,int niter) ; struct slopingstats { int m,N,len,*n ; double **S,**ybar,**ybardash ; slopingstats() { N = len = m = 0 ; n = 0 ; S = ybar = ybardash = 0 ; } slopingstats(int p) { this[0] = slopingstats() ; m = p ; S = matrix(m+1,m+1) ; } void take(double **y,int ni) { if(ni<=0) return ; double q=1.0/ni ; int t,j,k ; if(len==N) { len += 20 + len ; n = ivector(n,len) ; ybar = matrix(ybar,len,m) ; ybardash = matrix(ybardash,len,m) ; for(t=N;t<len;t++) { n[t] = 0 ; for(j=0;j<m;j++) ybar[t][j] = ybardash[t][j] = 0 ; } } for(t=0;t<ni;t++) for(j=0;j<m;j++) ybar[N][j] += q * y[t][j] ; if(ni>1) for(q=2/(ni*(ni-1.0)),t=0;t<ni;t++) for(j=0;j<m;j++) ybardash[N][j] += q * t * y[t][j] ; for(j=0;j<m;j++) for(k=0;k<m;k++) for(t=0;t<ni;t++) S[j][k] += (y[t][j]-ybar[N][j]) * (y[t][k]-ybar[N][k]) ; n[N++] = ni ; } void release() { free(n) ; freematrix(S,ybar,ybardash) ; this[0] = slopingstats() ; } void sort() { int t,j ; double **x=matrix(N,m) ; ij *list = ijvector(n,N) ; ijsort(list,N) ; for(t=0;t<N;t++) for(j=0;j<m;j++) x[t][j] = ybar[list[t].j][j] ; for(t=0;t<N;t++) for(j=0;j<m;j++) ybar[t][j] = ybardash[list[t].j][j] ; for(t=0;t<N;t++) n[t] = list[t].i ; freematrix(ybardash) ; ybardash = ybar ; ybar = x ; free(list) ; } } ; double slopingbw(slopingstats s,double *mu,double **zb,double **zw, double *muhat,double **zbhat,double **zwhat,int niter) { return slopingbw(s.m,s.N,s.S,s.ybar,s.ybardash,s.n,mu,zb,zw, muhat,zbhat,zwhat,niter) ; }

doc : source

slopingtest generates random data under a sloping loudness model and estimates parameters using slopingbw in two different ways: firstly it hillclimbs on the log pdf, the it performs the Baum-Welch algorithm until convergence. The data sizes wired in are small and many of the sequences are singletons, making the test quite demanding. The hillclimb returns a log pdf much greater than is assigned to the true parameters, and the Baum-Welch procedure (in many fewer iterations) does almost as well.

You’re meant to just run it without parameters, but if you insist the calling sequence is

slopingtest m seed

where m is the dimension of the space and seed seeds the random number generator.

Run without parameters you get the following output:

20 groups with avge size = 2.0
3235 function evals
logpdf=3.301902 (10 iterations)
25 Baum-Welch iterations
pdf       : 2.6481
pdf  (ML) : 3.3769
pdf  (BW) : 3.3754

mu:
  -0.203  -1.009   1.156   0.454  -0.491   5.813

mu MLE:
  -0.224  -0.941   1.068   0.393  -0.461  16.136

mu Baum-Welch estimator:
  -0.224  -0.941   1.068   0.393  -0.460  16.116

-----------------------------------------

zeta[W]*1000:
   7.412   0.469  -1.569   1.433   0.118
   0.469   5.678   0.251   0.149   1.220
  -1.569   0.251   6.750   1.445  -0.538
   1.433   0.149   1.445   6.758  -0.704
   0.118   1.220  -0.538  -0.704   5.626

zeta[W] MLE:
   7.840   1.627  -0.485   3.835  -2.312
   1.627   3.998  -0.387  -1.419  -0.441
  -0.485  -0.387   6.988   1.601   1.038
   3.835  -1.419   1.601   9.948   0.004
  -2.312  -0.441   1.038   0.004   2.775

zeta[W] Baum-Welch:
   7.706   1.637  -0.578   3.696  -2.253
   1.637   4.012  -0.510  -1.394  -0.432
  -0.578  -0.510   6.701   1.521   0.885
   3.696  -1.394   1.521   9.789   0.077
  -2.253  -0.432   0.885   0.077   2.756

-----------------------------------------

zeta[B]*10:
   0.250   0.030  -0.163  -0.093   0.042   0.075
   0.030   0.524  -0.369  -0.204   0.309   0.345
  -0.163  -0.369   0.764   0.362  -0.336  -0.459
  -0.093  -0.204   0.362   0.370  -0.255  -0.280
   0.042   0.309  -0.336  -0.255   0.334   0.301
   0.075   0.345  -0.459  -0.280   0.301   0.413

zeta[B] MLE:
   0.103   0.088  -0.082  -0.080   0.079   0.154
   0.088   0.312  -0.123   0.018   0.117   0.203
  -0.082  -0.123   0.648   0.461  -0.205  -0.403
  -0.080   0.018   0.461   0.532  -0.140  -0.378
   0.079   0.117  -0.205  -0.140   0.146   0.251
   0.154   0.203  -0.403  -0.378   0.251   0.516

zeta[B] Baum-Welch:
   0.102   0.087  -0.082  -0.080   0.077   0.154
   0.087   0.311  -0.123   0.016   0.117   0.204
  -0.082  -0.123   0.649   0.458  -0.203  -0.402
  -0.080   0.016   0.458   0.531  -0.143  -0.375
   0.077   0.117  -0.203  -0.143   0.147   0.250
   0.154   0.204  -0.402  -0.375   0.250   0.514

doc : source

• ranvec     • vmatrix     • vvector     • f     • main

#include "memory.h" #include <math.h> #include "random.h" #include "ij.h" #include "slopingbw.h" double uoamax(double (*func)(double*),double *x,int n, double xinc,double tol,int maxiter) ; int uoacond() ; double cholsqrt(double **a,double **b,int n) ; static slopingstats stats ; static int ncall ; /*--------------------------------------------------------------------------- */ static void ranvec(double *x,int m,double *sigma,double **rot,double *mu) { int i,j ; double q ; for(i=0;i<m;i++) x[i] = mu[i] ; for(i=0;i<m;i++) { q = sigma[i] * gaussv() ; for(j=0;j<m;j++) x[j] += q * rot[i][j] ; } } /*--------------------------------------------------------------------------- */ static int vmatrix(double *v,double **z0,int m) { int i,j,k,t ; double q,**z=matrix(m,m) ; for(t=i=0;i<m;i++) for(j=0;j<=i;j++,t++) z[i][j] = v[t] ; for(i=0;i<m;i++) for(k=0;k<=i;k++) { for(q=j=0;j<=k;j++) q += z[i][j] * z[k][j] ; z0[i][k] = z0[k][i] = q ; } freematrix(z) ; return t ; } static void vvector(double *mu,double **zb,double **zw,int m,double *v) { int i,j,t,mdash=m+1 ; double **z=matrix(m,m) ; for(t=0;t<mdash;t++) v[t] = mu[t] ; cholsqrt(zw,z,m) ; for(j=0;j<m;j++) for(i=0;i<=j;i++) v[t++] = z[i][j] ; freematrix(z) ; z = matrix(mdash,mdash) ; cholsqrt(zb,z,mdash) ; for(j=0;j<mdash;j++) for(i=0;i<=j;i++) v[t++] = z[i][j] ; } /*--------------------------------------------------------------------------- */
/*page*/ /*--------------------------------------------------------------------------- */ static double f(double *v) { int i,t,m=stats.m,mdash=m+1 ; double q,*mu=vector(mdash),**zw=matrix(m,m),**zb=matrix(mdash,mdash) ; for(t=0;t<mdash;t++) mu[t] = v[t] ; t += vmatrix(v+t,zw,m) ; t += vmatrix(v+t,zb,mdash) ; q = slopingbw(stats,mu,zb,zw,0,0,0,0) ; free(mu) ; freematrix(zw,zb) ; ncall += 1 ; return q ; } /*--------------------------------------------------------------------------- */ int main(int argc,char **argv) { if(argc>2) ranset(atoi(argv[2])) ; int m=argc>1?atoi(argv[1]):5,mdash=m+1,ndash=20 ; int groupno,i,j,k,t,nneg,iter,targ,ndot,cond,*ni=ivector(ndash) ; ; int vlen = mdash + (mdash*(mdash+1))/2 + (m*(m+1))/2 ; double ***y=(double ***) cjcalloc(ndash,sizeof(double**)) ; double q,q0,*eb=vector(mdash),*ew=vector(m),**xs=matrix(ndash,mdash),scale ; double **rotw=matrix(m,m),**rotb=matrix(mdash,mdash),*mu=vector(mdash) ; double *mubw=vector(mdash),**zbbw=matrix(mdash,mdash),**zwbw=matrix(m,m) ; double *muml=vector(mdash),**zbml=matrix(mdash,mdash),**zwml=matrix(m,m) ; double *v=vector(vlen),**zw=matrix(m,m),**zb=matrix(mdash,mdash) ; double *a=vector(m),qpdf,qmlpdf,q0pdf,qbwpdf ; stats = slopingstats(m) ; // generate group sizes for(ndot=t=0;t<ndash/2;t++) ndot += ( ni[t] = 1 ) ; for(;t<ndash;t++) ndot += ( ni[t] = 3 ) ; isort(ni,ndash) ; scale = ndot / ndash ; // avge group size printf("%d groups with avge size = %.1f\n",ndash,scale) ; // generate random global parameters ranrot(rotw,m) ; for(i=0;i<m;i++) ew[i] = 1/(20*sqrt(ranf())) ; for(i=0;i<m;i++) for(k=0;k<m;k++) for(zw[i][k]=j=0;j<m;j++) zw[i][k] += rotw[j][i] * rotw[j][k] * ew[j] * ew[j] ; for(i=0;i<mdash;i++) mu[i] = gaussv() ; ranrot(rotb,mdash) ; for(i=0;i<mdash;i++) eb[i] = 1/(20*sqrt(ranf()/scale)) ; for(i=0;i<mdash;i++) for(k=0;k<mdash;k++) for(zb[i][k]=j=0;j<mdash;j++) zb[i][k] += rotb[j][i] * rotb[j][k] * eb[j] * eb[j] ; /*------------------------------------------------------------------------- */
/*page*/ /*------------------------------------------------------------------------- */ // generate group (x,s) vectors and observations for(groupno=0;groupno<ndash;groupno++) { ranvec(xs[groupno],mdash,eb,rotb,mu) ; xs[groupno][m] /= scale ; y[groupno] = matrix(ni[groupno],m) ; for(t=0;t<ni[groupno];t++) { for(i=0;i<m;i++) a[i] = xs[groupno][i] + t*xs[groupno][m] ; ranvec(y[groupno][t],m,ew,rotw,a) ; } stats.take(y[groupno],ni[groupno]) ; } free(ni) ; stats.sort() ; mu[m] /= scale ; for(i=0;i<mdash;i++) { zb[i][m] /= scale ; zb[m][i] /= scale ; } qpdf = slopingbw(stats,mu,zb,zw,0,0,0,0) ; /*----------------------------------- ML ---------------------------------- */ for(i=0;i<m;i++) for(j=0;j<m;j++) zwml[i][j] = 0 ; for(i=0;i<m;i++) { muml[i] = 0 ; zwml[i][i] = 1 ; } for(i=0;i<mdash;i++) for(j=0;j<mdash;j++) zbml[i][j] = 0 ; for(i=0;i<mdash;i++) zbml[i][i] = 1 ; vvector(muml,zbml,zwml,m,v) ; ncall = 0 ; qmlpdf = uoamax(f,v,vlen,0.1,1e-4,500000) ; cond = uoacond() ; if(cond!=0) printf("*** cond=%d ***: ",cond) ; printf("%d function evals\n",ncall) ; for(t=0;t<mdash;t++) muml[t] = v[t] ; t += vmatrix(v+t,zwml,m) ; t += vmatrix(v+t,zbml,mdash) ; /*------------------------------- Baum Welch ------------------------------ */ for(i=0;i<mdash;i++) for(j=0;j<mdash;j++) zbbw[i][j] = 0 ; for(i=0;i<mdash;i++) { mubw[i] = 0 ; zbbw[i][i] = 1 ; } for(i=0;i<m;i++) for(j=0;j<m;j++) zwbw[i][j] = 0 ; for(i=0;i<m;i++) zwbw[i][i] = 1 ; for(targ=10,iter=5;iter<1000;q=qbwpdf,iter+=5) { qbwpdf = slopingbw(stats,mubw,zbbw,zwbw,mubw,zbbw,zwbw,5) ; if(iter==targ) { printf("logpdf=%.6f (%d iterations)\n",qbwpdf,iter) ; targ *= 10 ; } if(iter==5||qbwpdf-q>q0) q0 = qbwpdf - q ; if(iter>1&&qbwpdf-q<q0/1000) break ; } printf("%d Baum-Welch iterations\n",iter) ; stats.release() ; /*---------------------------- print estimates ---------------------------- */ printf("pdf : %.4f\n",qpdf) ; printf("pdf (ML) : %.4f\n",qmlpdf) ; printf("pdf (BW) : %.4f\n\n",qbwpdf) ; printf("mu:\n") ; for(i=0;i<m;i++) printf("%8.3f",mu[i]) ; printf("%8.3f\n\n",100*mu[m]) ; printf("mu MLE:\n") ; for(i=0;i<m;i++) printf("%8.3f",muml[i]) ; printf("%8.3f\n\n",100*muml[m]) ; printf("mu Baum-Welch estimator:\n") ; for(i=0;i<m;i++) printf("%8.3f",mubw[i]) ; printf("%8.3f\n",100*mubw[m]) ; printf("\n-----------------------------------------\n\n") ; printf("zeta[W]*1000:\n") ; for(i=0;i<m;i++) { for(j=0;j<m;j++) printf("%8.3f",1000*zw[i][j]) ; printf("\n") ; } printf("\n") ; printf("zeta[W] MLE:\n") ; for(i=0;i<m;i++) { for(j=0;j<m;j++) printf("%8.3f",1000*zwml[i][j]) ; printf("\n") ; } printf("\n") ; printf("zeta[W] Baum-Welch:\n") ; for(i=0;i<m;i++) { for(j=0;j<m;j++) printf("%8.3f",1000*zwbw[i][j]) ; printf("\n") ; } printf("\n-----------------------------------------\n\n") ; printf("zeta[B]*10:\n") ; for(i=0;i<mdash;i++) { for(j=0;j<mdash;j++) printf("%8.3f",10*zb[i][j]) ; printf("\n") ; } printf("\n") ; printf("zeta[B] MLE:\n") ; for(i=0;i<mdash;i++) { for(j=0;j<mdash;j++) printf("%8.3f",10*zbml[i][j]) ; printf("\n") ; } printf("\n") ; printf("zeta[B] Baum-Welch:\n") ; for(i=0;i<mdash;i++) { for(j=0;j<mdash;j++) printf("%8.3f",10*zbbw[i][j]) ; printf("\n") ; } printf("\n") ; }

doc : source

This download procedure works under Firefox (so long as you enable popup windows for the site) but probably not under any other browser.

slopingbw.c slopingbw.h slopingtest.c       # this file
utils: memory.h ij.h random.h ranf.c cholesky.c qr.c ranrot.c
optim: newuoa.c
---
g++ -o slopingtest -O2 -g (*.c) ; slopingtest