annotate hmm/hmm.c @ 241:a98dd8ec96f8

* Move dsp/maths to maths ; bring PCA and HMM across from Soundbite
author Chris Cannam <c.cannam@qmul.ac.uk>
date Wed, 09 Jan 2008 10:31:29 +0000
parents
children
rev   line source
c@241 1 /*
c@241 2 * hmm.c
c@241 3 * soundbite
c@241 4 *
c@241 5 * Created by Mark Levy on 12/02/2006.
c@241 6 * Copyright 2006 Centre for Digital Music, Queen Mary, University of London. All rights reserved.
c@241 7 *
c@241 8 */
c@241 9
c@241 10 #include <stdio.h>
c@241 11 #include <math.h>
c@241 12 #include <stdlib.h>
c@241 13 #include <float.h>
c@241 14 #include <time.h> /* to seed random number generator */
c@241 15 #include "clapack.h" /* LAPACK for matrix inversion */
c@241 16 #ifdef _MAC_OS_X
c@241 17 #include <vecLib/cblas.h>
c@241 18 #else
c@241 19 #include <cblas.h> /* BLAS for matrix multiplication */
c@241 20 #endif
c@241 21
c@241 22 #include "hmm.h"
c@241 23
c@241 24 model_t* hmm_init(double** x, int T, int L, int N)
c@241 25 {
c@241 26 int i, j, d, e, t;
c@241 27 double s, ss;
c@241 28
c@241 29 model_t* model;
c@241 30 model = (model_t*) malloc(sizeof(model_t));
c@241 31 model->N = N;
c@241 32 model->L = L;
c@241 33 model->p0 = (double*) malloc(N*sizeof(double));
c@241 34 model->a = (double**) malloc(N*sizeof(double*));
c@241 35 model->mu = (double**) malloc(N*sizeof(double*));
c@241 36 for (i = 0; i < N; i++)
c@241 37 {
c@241 38 model->a[i] = (double*) malloc(N*sizeof(double));
c@241 39 model->mu[i] = (double*) malloc(L*sizeof(double));
c@241 40 }
c@241 41 model->cov = (double**) malloc(L*sizeof(double*));
c@241 42 for (i = 0; i < L; i++)
c@241 43 model->cov[i] = (double*) malloc(L*sizeof(double));
c@241 44
c@241 45 srand(time(0));
c@241 46 double* global_mean = (double*) malloc(L*sizeof(double));
c@241 47
c@241 48 /* find global mean */
c@241 49 for (d = 0; d < L; d++)
c@241 50 {
c@241 51 global_mean[d] = 0;
c@241 52 for (t = 0; t < T; t++)
c@241 53 global_mean[d] += x[t][d];
c@241 54 global_mean[d] /= T;
c@241 55 }
c@241 56
c@241 57 /* calculate global diagonal covariance */
c@241 58 for (d = 0; d < L; d++)
c@241 59 {
c@241 60 for (e = 0; e < L; e++)
c@241 61 model->cov[d][e] = 0;
c@241 62 for (t = 0; t < T; t++)
c@241 63 model->cov[d][d] += (x[t][d] - global_mean[d]) * (x[t][d] - global_mean[d]);
c@241 64 model->cov[d][d] /= T-1;
c@241 65 }
c@241 66
c@241 67 /* set all means close to global mean */
c@241 68 for (i = 0; i < N; i++)
c@241 69 {
c@241 70 for (d = 0; d < L; d++)
c@241 71 {
c@241 72 /* add some random noise related to covariance */
c@241 73 /* ideally the random number would be Gaussian(0,1), as a hack we make it uniform on [-0.25,0.25] */
c@241 74 model->mu[i][d] = global_mean[d] + (0.5 * rand() / (double) RAND_MAX - 0.25) * sqrt(model->cov[d][d]);
c@241 75 }
c@241 76 }
c@241 77
c@241 78 /* random intial and transition probs */
c@241 79 s = 0;
c@241 80 for (i = 0; i < N; i++)
c@241 81 {
c@241 82 model->p0[i] = 1 + rand() / (double) RAND_MAX;
c@241 83 s += model->p0[i];
c@241 84 ss = 0;
c@241 85 for (j = 0; j < N; j++)
c@241 86 {
c@241 87 model->a[i][j] = 1 + rand() / (double) RAND_MAX;
c@241 88 ss += model->a[i][j];
c@241 89 }
c@241 90 for (j = 0; j < N; j++)
c@241 91 {
c@241 92 model->a[i][j] /= ss;
c@241 93 }
c@241 94 }
c@241 95 for (i = 0; i < N; i++)
c@241 96 model->p0[i] /= s;
c@241 97
c@241 98 free(global_mean);
c@241 99
c@241 100 return model;
c@241 101 }
c@241 102
c@241 103 void hmm_close(model_t* model)
c@241 104 {
c@241 105 int i;
c@241 106
c@241 107 for (i = 0; i < model->N; i++)
c@241 108 {
c@241 109 free(model->a[i]);
c@241 110 free(model->mu[i]);
c@241 111 }
c@241 112 free(model->a);
c@241 113 free(model->mu);
c@241 114 for (i = 0; i < model->L; i++)
c@241 115 free(model->cov[i]);
c@241 116 free(model->cov);
c@241 117 free(model);
c@241 118 }
c@241 119
c@241 120 void hmm_train(double** x, int T, model_t* model)
c@241 121 {
c@241 122 int i, t;
c@241 123 double loglik; /* overall log-likelihood at each iteration */
c@241 124
c@241 125 int N = model->N;
c@241 126 int L = model->L;
c@241 127 double* p0 = model->p0;
c@241 128 double** a = model->a;
c@241 129 double** mu = model->mu;
c@241 130 double** cov = model->cov;
c@241 131
c@241 132 /* allocate memory */
c@241 133 double** gamma = (double**) malloc(T*sizeof(double*));
c@241 134 double*** xi = (double***) malloc(T*sizeof(double**));
c@241 135 for (t = 0; t < T; t++)
c@241 136 {
c@241 137 gamma[t] = (double*) malloc(N*sizeof(double));
c@241 138 xi[t] = (double**) malloc(N*sizeof(double*));
c@241 139 for (i = 0; i < N; i++)
c@241 140 xi[t][i] = (double*) malloc(N*sizeof(double));
c@241 141 }
c@241 142
c@241 143 /* temporary memory */
c@241 144 double* gauss_y = (double*) malloc(L*sizeof(double));
c@241 145 double* gauss_z = (double*) malloc(L*sizeof(double));
c@241 146
c@241 147 /* obs probs P(j|{x}) */
c@241 148 double** b = (double**) malloc(T*sizeof(double*));
c@241 149 for (t = 0; t < T; t++)
c@241 150 b[t] = (double*) malloc(N*sizeof(double));
c@241 151
c@241 152 /* inverse covariance and its determinant */
c@241 153 double** icov = (double**) malloc(L*sizeof(double*));
c@241 154 for (i = 0; i < L; i++)
c@241 155 icov[i] = (double*) malloc(L*sizeof(double));
c@241 156 double detcov;
c@241 157
c@241 158 double thresh = 0.0001;
c@241 159 int niter = 50;
c@241 160 int iter = 0;
c@241 161 double loglik1, loglik2;
c@241 162 while(iter < niter && !(iter > 1 && (loglik - loglik1) < thresh * (loglik1 - loglik2)))
c@241 163 {
c@241 164 ++iter;
c@241 165
c@241 166 fprintf(stderr, "calculating obsprobs...\n");
c@241 167 fflush(stderr);
c@241 168
c@241 169 /* precalculate obs probs */
c@241 170 invert(cov, L, icov, &detcov);
c@241 171
c@241 172 for (t = 0; t < T; t++)
c@241 173 {
c@241 174 //int allzero = 1;
c@241 175 for (i = 0; i < N; i++)
c@241 176 {
c@241 177 b[t][i] = exp(loggauss(x[t], L, mu[i], icov, detcov, gauss_y, gauss_z));
c@241 178
c@241 179 //if (b[t][i] != 0)
c@241 180 // allzero = 0;
c@241 181 }
c@241 182 /*
c@241 183 if (allzero)
c@241 184 {
c@241 185 printf("all the b[t][i] were zero for t = %d, correcting...\n", t);
c@241 186 for (i = 0; i < N; i++)
c@241 187 {
c@241 188 b[t][i] = 0.00001;
c@241 189 }
c@241 190 }
c@241 191 */
c@241 192 }
c@241 193
c@241 194 fprintf(stderr, "forwards-backwards...\n");
c@241 195 fflush(stderr);
c@241 196
c@241 197 forward_backwards(xi, gamma, &loglik, &loglik1, &loglik2, iter, N, T, p0, a, b);
c@241 198
c@241 199 fprintf(stderr, "iteration %d: loglik = %f\n", iter, loglik);
c@241 200 fprintf(stderr, "re-estimation...\n");
c@241 201 fflush(stderr);
c@241 202
c@241 203 baum_welch(p0, a, mu, cov, N, T, L, x, xi, gamma);
c@241 204
c@241 205 /*
c@241 206 printf("a:\n");
c@241 207 for (i = 0; i < model->N; i++)
c@241 208 {
c@241 209 for (j = 0; j < model->N; j++)
c@241 210 printf("%f ", model->a[i][j]);
c@241 211 printf("\n");
c@241 212 }
c@241 213 printf("\n\n");
c@241 214 */
c@241 215 //hmm_print(model);
c@241 216 }
c@241 217
c@241 218 /* deallocate memory */
c@241 219 for (t = 0; t < T; t++)
c@241 220 {
c@241 221 free(gamma[t]);
c@241 222 free(b[t]);
c@241 223 for (i = 0; i < N; i++)
c@241 224 free(xi[t][i]);
c@241 225 free(xi[t]);
c@241 226 }
c@241 227 free(gamma);
c@241 228 free(xi);
c@241 229 free(b);
c@241 230
c@241 231 for (i = 0; i < L; i++)
c@241 232 free(icov[i]);
c@241 233 free(icov);
c@241 234
c@241 235 free(gauss_y);
c@241 236 free(gauss_z);
c@241 237 }
c@241 238
c@241 239 void mlss_reestimate(double* p0, double** a, double** mu, double** cov, int N, int T, int L, int* q, double** x)
c@241 240 {
c@241 241 /* fit a single Gaussian to observations in each state */
c@241 242
c@241 243 /* calculate the mean observation in each state */
c@241 244
c@241 245 /* calculate the overall covariance */
c@241 246
c@241 247 /* count transitions */
c@241 248
c@241 249 /* estimate initial probs from transitions (???) */
c@241 250 }
c@241 251
c@241 252 void baum_welch(double* p0, double** a, double** mu, double** cov, int N, int T, int L, double** x, double*** xi, double** gamma)
c@241 253 {
c@241 254 int i, j, t;
c@241 255
c@241 256 double* sum_gamma = (double*) malloc(N*sizeof(double));
c@241 257
c@241 258 /* temporary memory */
c@241 259 double* u = (double*) malloc(L*L*sizeof(double));
c@241 260 double* yy = (double*) malloc(T*L*sizeof(double));
c@241 261 double* yy2 = (double*) malloc(T*L*sizeof(double));
c@241 262
c@241 263 /* re-estimate transition probs */
c@241 264 for (i = 0; i < N; i++)
c@241 265 {
c@241 266 sum_gamma[i] = 0;
c@241 267 for (t = 0; t < T-1; t++)
c@241 268 sum_gamma[i] += gamma[t][i];
c@241 269 }
c@241 270
c@241 271 for (i = 0; i < N; i++)
c@241 272 {
c@241 273 if (sum_gamma[i] == 0)
c@241 274 {
c@241 275 fprintf(stderr, "sum_gamma[%d] was zero...\n", i);
c@241 276 }
c@241 277 //double s = 0;
c@241 278 for (j = 0; j < N; j++)
c@241 279 {
c@241 280 a[i][j] = 0;
c@241 281 for (t = 0; t < T-1; t++)
c@241 282 a[i][j] += xi[t][i][j];
c@241 283 //s += a[i][j];
c@241 284 a[i][j] /= sum_gamma[i];
c@241 285 }
c@241 286 /*
c@241 287 for (j = 0; j < N; j++)
c@241 288 {
c@241 289 a[i][j] /= s;
c@241 290 }
c@241 291 */
c@241 292 }
c@241 293
c@241 294 /* NB: now we need to sum gamma over all t */
c@241 295 for (i = 0; i < N; i++)
c@241 296 sum_gamma[i] += gamma[T-1][i];
c@241 297
c@241 298 /* re-estimate initial probs */
c@241 299 for (i = 0; i < N; i++)
c@241 300 p0[i] = gamma[0][i];
c@241 301
c@241 302 /* re-estimate covariance */
c@241 303 int d, e;
c@241 304 double sum_sum_gamma = 0;
c@241 305 for (i = 0; i < N; i++)
c@241 306 sum_sum_gamma += sum_gamma[i];
c@241 307
c@241 308 /*
c@241 309 for (d = 0; d < L; d++)
c@241 310 {
c@241 311 for (e = d; e < L; e++)
c@241 312 {
c@241 313 cov[d][e] = 0;
c@241 314 for (t = 0; t < T; t++)
c@241 315 for (j = 0; j < N; j++)
c@241 316 cov[d][e] += gamma[t][j] * (x[t][d] - mu[j][d]) * (x[t][e] - mu[j][e]);
c@241 317
c@241 318 cov[d][e] /= sum_sum_gamma;
c@241 319
c@241 320 if (isnan(cov[d][e]))
c@241 321 {
c@241 322 printf("cov[%d][%d] was nan\n", d, e);
c@241 323 for (j = 0; j < N; j++)
c@241 324 for (i = 0; i < L; i++)
c@241 325 if (isnan(mu[j][i]))
c@241 326 printf("mu[%d][%d] was nan\n", j, i);
c@241 327 for (t = 0; t < T; t++)
c@241 328 for (j = 0; j < N; j++)
c@241 329 if (isnan(gamma[t][j]))
c@241 330 printf("gamma[%d][%d] was nan\n", t, j);
c@241 331 exit(-1);
c@241 332 }
c@241 333 }
c@241 334 }
c@241 335 for (d = 0; d < L; d++)
c@241 336 for (e = 0; e < d; e++)
c@241 337 cov[d][e] = cov[e][d];
c@241 338 */
c@241 339
c@241 340 /* using BLAS */
c@241 341 for (d = 0; d < L; d++)
c@241 342 for (e = 0; e < L; e++)
c@241 343 cov[d][e] = 0;
c@241 344
c@241 345 for (j = 0; j < N; j++)
c@241 346 {
c@241 347 for (d = 0; d < L; d++)
c@241 348 for (t = 0; t < T; t++)
c@241 349 {
c@241 350 yy[d*T+t] = x[t][d] - mu[j][d];
c@241 351 yy2[d*T+t] = gamma[t][j] * (x[t][d] - mu[j][d]);
c@241 352 }
c@241 353
c@241 354 cblas_dgemm(CblasColMajor, CblasTrans, CblasNoTrans, L, L, T, 1.0, yy, T, yy2, T, 0, u, L);
c@241 355
c@241 356 for (e = 0; e < L; e++)
c@241 357 for (d = 0; d < L; d++)
c@241 358 cov[d][e] += u[e*L+d];
c@241 359 }
c@241 360
c@241 361 for (d = 0; d < L; d++)
c@241 362 for (e = 0; e < L; e++)
c@241 363 cov[d][e] /= T; /* sum_sum_gamma; */
c@241 364
c@241 365 //printf("sum_sum_gamma = %f\n", sum_sum_gamma); /* fine, = T IS THIS ALWAYS TRUE with pooled cov?? */
c@241 366
c@241 367 /* re-estimate means */
c@241 368 for (j = 0; j < N; j++)
c@241 369 {
c@241 370 for (d = 0; d < L; d++)
c@241 371 {
c@241 372 mu[j][d] = 0;
c@241 373 for (t = 0; t < T; t++)
c@241 374 mu[j][d] += gamma[t][j] * x[t][d];
c@241 375 mu[j][d] /= sum_gamma[j];
c@241 376 }
c@241 377 }
c@241 378
c@241 379 /* deallocate memory */
c@241 380 free(sum_gamma);
c@241 381 free(yy);
c@241 382 free(yy2);
c@241 383 free(u);
c@241 384 }
c@241 385
c@241 386 void forward_backwards(double*** xi, double** gamma, double* loglik, double* loglik1, double* loglik2, int iter, int N, int T, double* p0, double** a, double** b)
c@241 387 {
c@241 388 /* forwards-backwards with scaling */
c@241 389 int i, j, t;
c@241 390
c@241 391 double** alpha = (double**) malloc(T*sizeof(double*));
c@241 392 double** beta = (double**) malloc(T*sizeof(double*));
c@241 393 for (t = 0; t < T; t++)
c@241 394 {
c@241 395 alpha[t] = (double*) malloc(N*sizeof(double));
c@241 396 beta[t] = (double*) malloc(N*sizeof(double));
c@241 397 }
c@241 398
c@241 399 /* scaling coefficients */
c@241 400 double* c = (double*) malloc(T*sizeof(double));
c@241 401
c@241 402 /* calculate forward probs and scale coefficients */
c@241 403 c[0] = 0;
c@241 404 for (i = 0; i < N; i++)
c@241 405 {
c@241 406 alpha[0][i] = p0[i] * b[0][i];
c@241 407 c[0] += alpha[0][i];
c@241 408
c@241 409 //printf("p0[%d] = %f, b[0][%d] = %f\n", i, p0[i], i, b[0][i]);
c@241 410 }
c@241 411 c[0] = 1 / c[0];
c@241 412 for (i = 0; i < N; i++)
c@241 413 {
c@241 414 alpha[0][i] *= c[0];
c@241 415
c@241 416 //printf("alpha[0][%d] = %f\n", i, alpha[0][i]); /* OK agrees with Matlab */
c@241 417 }
c@241 418
c@241 419 *loglik1 = *loglik;
c@241 420 *loglik = -log(c[0]);
c@241 421 if (iter == 2)
c@241 422 *loglik2 = *loglik;
c@241 423
c@241 424 for (t = 1; t < T; t++)
c@241 425 {
c@241 426 c[t] = 0;
c@241 427 for (j = 0; j < N; j++)
c@241 428 {
c@241 429 alpha[t][j] = 0;
c@241 430 for (i = 0; i < N; i++)
c@241 431 alpha[t][j] += alpha[t-1][i] * a[i][j];
c@241 432 alpha[t][j] *= b[t][j];
c@241 433
c@241 434 c[t] += alpha[t][j];
c@241 435 }
c@241 436
c@241 437 /*
c@241 438 if (c[t] == 0)
c@241 439 {
c@241 440 printf("c[%d] = 0, going to blow up so exiting\n", t);
c@241 441 for (i = 0; i < N; i++)
c@241 442 if (b[t][i] == 0)
c@241 443 fprintf(stderr, "b[%d][%d] was zero\n", t, i);
c@241 444 fprintf(stderr, "x[t] was \n");
c@241 445 for (i = 0; i < L; i++)
c@241 446 fprintf(stderr, "%f ", x[t][i]);
c@241 447 fprintf(stderr, "\n\n");
c@241 448 exit(-1);
c@241 449 }
c@241 450 */
c@241 451
c@241 452 c[t] = 1 / c[t];
c@241 453 for (j = 0; j < N; j++)
c@241 454 alpha[t][j] *= c[t];
c@241 455
c@241 456 //printf("c[%d] = %e\n", t, c[t]);
c@241 457
c@241 458 *loglik -= log(c[t]);
c@241 459 }
c@241 460
c@241 461 /* calculate backwards probs using same coefficients */
c@241 462 for (i = 0; i < N; i++)
c@241 463 beta[T-1][i] = 1;
c@241 464 t = T - 1;
c@241 465 while (1)
c@241 466 {
c@241 467 for (i = 0; i < N; i++)
c@241 468 beta[t][i] *= c[t];
c@241 469
c@241 470 if (t == 0)
c@241 471 break;
c@241 472
c@241 473 for (i = 0; i < N; i++)
c@241 474 {
c@241 475 beta[t-1][i] = 0;
c@241 476 for (j = 0; j < N; j++)
c@241 477 beta[t-1][i] += a[i][j] * b[t][j] * beta[t][j];
c@241 478 }
c@241 479
c@241 480 t--;
c@241 481 }
c@241 482
c@241 483 /*
c@241 484 printf("alpha:\n");
c@241 485 for (t = 0; t < T; t++)
c@241 486 {
c@241 487 for (i = 0; i < N; i++)
c@241 488 printf("%4.4e\t\t", alpha[t][i]);
c@241 489 printf("\n");
c@241 490 }
c@241 491 printf("\n\n");printf("beta:\n");
c@241 492 for (t = 0; t < T; t++)
c@241 493 {
c@241 494 for (i = 0; i < N; i++)
c@241 495 printf("%4.4e\t\t", beta[t][i]);
c@241 496 printf("\n");
c@241 497 }
c@241 498 printf("\n\n");
c@241 499 */
c@241 500
c@241 501 /* calculate posterior probs */
c@241 502 double tot;
c@241 503 for (t = 0; t < T; t++)
c@241 504 {
c@241 505 tot = 0;
c@241 506 for (i = 0; i < N; i++)
c@241 507 {
c@241 508 gamma[t][i] = alpha[t][i] * beta[t][i];
c@241 509 tot += gamma[t][i];
c@241 510 }
c@241 511 for (i = 0; i < N; i++)
c@241 512 {
c@241 513 gamma[t][i] /= tot;
c@241 514
c@241 515 //printf("gamma[%d][%d] = %f\n", t, i, gamma[t][i]);
c@241 516 }
c@241 517 }
c@241 518
c@241 519 for (t = 0; t < T-1; t++)
c@241 520 {
c@241 521 tot = 0;
c@241 522 for (i = 0; i < N; i++)
c@241 523 {
c@241 524 for (j = 0; j < N; j++)
c@241 525 {
c@241 526 xi[t][i][j] = alpha[t][i] * a[i][j] * b[t+1][j] * beta[t+1][j];
c@241 527 tot += xi[t][i][j];
c@241 528 }
c@241 529 }
c@241 530 for (i = 0; i < N; i++)
c@241 531 for (j = 0; j < N; j++)
c@241 532 xi[t][i][j] /= tot;
c@241 533 }
c@241 534
c@241 535 /*
c@241 536 // CHECK - fine
c@241 537 // gamma[t][i] = \sum_j{xi[t][i][j]}
c@241 538 tot = 0;
c@241 539 for (j = 0; j < N; j++)
c@241 540 tot += xi[3][1][j];
c@241 541 printf("gamma[3][1] = %f, sum_j(xi[3][1][j]) = %f\n", gamma[3][1], tot);
c@241 542 */
c@241 543
c@241 544 for (t = 0; t < T; t++)
c@241 545 {
c@241 546 free(alpha[t]);
c@241 547 free(beta[t]);
c@241 548 }
c@241 549 free(alpha);
c@241 550 free(beta);
c@241 551 free(c);
c@241 552 }
c@241 553
c@241 554 void viterbi_decode(double** x, int T, model_t* model, int* q)
c@241 555 {
c@241 556 int i, j, t;
c@241 557 double max;
c@241 558
c@241 559 int N = model->N;
c@241 560 int L = model->L;
c@241 561 double* p0 = model->p0;
c@241 562 double** a = model->a;
c@241 563 double** mu = model->mu;
c@241 564 double** cov = model->cov;
c@241 565
c@241 566 /* inverse covariance and its determinant */
c@241 567 double** icov = (double**) malloc(L*sizeof(double*));
c@241 568 for (i = 0; i < L; i++)
c@241 569 icov[i] = (double*) malloc(L*sizeof(double));
c@241 570 double detcov;
c@241 571
c@241 572 double** logb = (double**) malloc(T*sizeof(double*));
c@241 573 double** phi = (double**) malloc(T*sizeof(double*));
c@241 574 int** psi = (int**) malloc(T*sizeof(int*));
c@241 575 for (t = 0; t < T; t++)
c@241 576 {
c@241 577 logb[t] = (double*) malloc(N*sizeof(double));
c@241 578 phi[t] = (double*) malloc(N*sizeof(double));
c@241 579 psi[t] = (int*) malloc(N*sizeof(int));
c@241 580 }
c@241 581
c@241 582 /* temporary memory */
c@241 583 double* gauss_y = (double*) malloc(L*sizeof(double));
c@241 584 double* gauss_z = (double*) malloc(L*sizeof(double));
c@241 585
c@241 586 /* calculate observation logprobs */
c@241 587 invert(cov, L, icov, &detcov);
c@241 588 for (t = 0; t < T; t++)
c@241 589 for (i = 0; i < N; i++)
c@241 590 logb[t][i] = loggauss(x[t], L, mu[i], icov, detcov, gauss_y, gauss_z);
c@241 591
c@241 592 /* initialise */
c@241 593 for (i = 0; i < N; i++)
c@241 594 {
c@241 595 phi[0][i] = log(p0[i]) + logb[0][i];
c@241 596 psi[0][i] = 0;
c@241 597 }
c@241 598
c@241 599 for (t = 1; t < T; t++)
c@241 600 {
c@241 601 for (j = 0; j < N; j++)
c@241 602 {
c@241 603 max = -1000000; // TODO: what should this be?? = smallest possible sumlogprob
c@241 604 psi[t][j] = 0;
c@241 605 for (i = 0; i < N; i++)
c@241 606 {
c@241 607 if (phi[t-1][i] + log(a[i][j]) > max)
c@241 608 {
c@241 609 max = phi[t-1][i] + log(a[i][j]);
c@241 610 phi[t][j] = max + logb[t][j];
c@241 611 psi[t][j] = i;
c@241 612 }
c@241 613 }
c@241 614 }
c@241 615 }
c@241 616
c@241 617 /* find maximising state at time T-1 */
c@241 618 max = phi[T-1][0];
c@241 619 q[T-1] = 0;
c@241 620 for (i = 1; i < N; i++)
c@241 621 {
c@241 622 if (phi[T-1][i] > max)
c@241 623 {
c@241 624 max = phi[T-1][i];
c@241 625 q[T-1] = i;
c@241 626 }
c@241 627 }
c@241 628
c@241 629
c@241 630 /* track back */
c@241 631 t = T - 2;
c@241 632 while (t >= 0)
c@241 633 {
c@241 634 q[t] = psi[t+1][q[t+1]];
c@241 635 t--;
c@241 636 }
c@241 637
c@241 638 /* de-allocate memory */
c@241 639 for (i = 0; i < L; i++)
c@241 640 free(icov[i]);
c@241 641 free(icov);
c@241 642 for (t = 0; t < T; t++)
c@241 643 {
c@241 644 free(logb[t]);
c@241 645 free(phi[t]);
c@241 646 free(psi[t]);
c@241 647 }
c@241 648 free(logb);
c@241 649 free(phi);
c@241 650 free(psi);
c@241 651
c@241 652 free(gauss_y);
c@241 653 free(gauss_z);
c@241 654 }
c@241 655
c@241 656 /* invert matrix and calculate determinant using LAPACK */
c@241 657 void invert(double** cov, int L, double** icov, double* detcov)
c@241 658 {
c@241 659 /* copy square matrix into a vector in column-major order */
c@241 660 double* a = (double*) malloc(L*L*sizeof(double));
c@241 661 int i, j;
c@241 662 for(j=0; j < L; j++)
c@241 663 for (i=0; i < L; i++)
c@241 664 a[j*L+i] = cov[i][j];
c@241 665
c@241 666 long M = (long) L;
c@241 667 long* ipiv = (long*) malloc(L*L*sizeof(int));
c@241 668 long ret;
c@241 669
c@241 670 /* LU decomposition */
c@241 671 ret = dgetrf_(&M, &M, a, &M, ipiv, &ret); /* ret should be zero, negative if cov is singular */
c@241 672 if (ret < 0)
c@241 673 {
c@241 674 fprintf(stderr, "Covariance matrix was singular, couldn't invert\n");
c@241 675 exit(-1);
c@241 676 }
c@241 677
c@241 678 /* find determinant */
c@241 679 double det = 1;
c@241 680 for(i = 0; i < L; i++)
c@241 681 det *= a[i*L+i];
c@241 682 // TODO: get this to work!!! If detcov < 0 then cov is bad anyway...
c@241 683 /*
c@241 684 int sign = 1;
c@241 685 for (i = 0; i < L; i++)
c@241 686 if (ipiv[i] != i)
c@241 687 sign = -sign;
c@241 688 det *= sign;
c@241 689 */
c@241 690 if (det < 0)
c@241 691 det = -det;
c@241 692 *detcov = det;
c@241 693
c@241 694 /* allocate required working storage */
c@241 695 long lwork = -1;
c@241 696 double lwbest;
c@241 697 dgetri_(&M, a, &M, ipiv, &lwbest, &lwork, &ret);
c@241 698 lwork = (long) lwbest;
c@241 699 double* work = (double*) malloc(lwork*sizeof(double));
c@241 700
c@241 701 /* find inverse */
c@241 702 dgetri_(&M, a, &M, ipiv, work, &lwork, &ret);
c@241 703
c@241 704 for(j=0; j < L; j++)
c@241 705 for (i=0; i < L; i++)
c@241 706 icov[i][j] = a[j*L+i];
c@241 707
c@241 708 free(work);
c@241 709 free(a);
c@241 710 }
c@241 711
c@241 712 /* probability of multivariate Gaussian given mean, inverse and determinant of covariance */
c@241 713 double gauss(double* x, int L, double* mu, double** icov, double detcov, double* y, double* z)
c@241 714 {
c@241 715 int i, j;
c@241 716 double s = 0;
c@241 717 for (i = 0; i < L; i++)
c@241 718 y[i] = x[i] - mu[i];
c@241 719 for (i = 0; i < L; i++)
c@241 720 {
c@241 721 //z[i] = 0;
c@241 722 //for (j = 0; j < L; j++)
c@241 723 // z[i] += icov[i][j] * y[j];
c@241 724 z[i] = cblas_ddot(L, &icov[i][0], 1, y, 1);
c@241 725 }
c@241 726 s = cblas_ddot(L, z, 1, y, 1);
c@241 727 //for (i = 0; i < L; i++)
c@241 728 // s += z[i] * y[i];
c@241 729
c@241 730 return exp(-s/2.0) / (pow(2*PI, L/2.0) * sqrt(detcov));
c@241 731 }
c@241 732
c@241 733 /* log probability of multivariate Gaussian given mean, inverse and determinant of covariance */
c@241 734 double loggauss(double* x, int L, double* mu, double** icov, double detcov, double* y, double* z)
c@241 735 {
c@241 736 int i, j;
c@241 737 double s = 0;
c@241 738 double ret;
c@241 739 for (i = 0; i < L; i++)
c@241 740 y[i] = x[i] - mu[i];
c@241 741 for (i = 0; i < L; i++)
c@241 742 {
c@241 743 //z[i] = 0;
c@241 744 //for (j = 0; j < L; j++)
c@241 745 // z[i] += icov[i][j] * y[j];
c@241 746 z[i] = cblas_ddot(L, &icov[i][0], 1, y, 1);
c@241 747 }
c@241 748 s = cblas_ddot(L, z, 1, y, 1);
c@241 749 //for (i = 0; i < L; i++)
c@241 750 // s += z[i] * y[i];
c@241 751
c@241 752 ret = -0.5 * (s + L * log(2*PI) + log(detcov));
c@241 753
c@241 754 /*
c@241 755 // TEST
c@241 756 if (isinf(ret) > 0)
c@241 757 printf("loggauss returning infinity\n");
c@241 758 if (isinf(ret) < 0)
c@241 759 printf("loggauss returning -infinity\n");
c@241 760 if (isnan(ret))
c@241 761 printf("loggauss returning nan\n");
c@241 762 */
c@241 763
c@241 764 return ret;
c@241 765 }
c@241 766
c@241 767 void hmm_print(model_t* model)
c@241 768 {
c@241 769 int i, j;
c@241 770 printf("p0:\n");
c@241 771 for (i = 0; i < model->N; i++)
c@241 772 printf("%f ", model->p0[i]);
c@241 773 printf("\n\n");
c@241 774 printf("a:\n");
c@241 775 for (i = 0; i < model->N; i++)
c@241 776 {
c@241 777 for (j = 0; j < model->N; j++)
c@241 778 printf("%f ", model->a[i][j]);
c@241 779 printf("\n");
c@241 780 }
c@241 781 printf("\n\n");
c@241 782 printf("mu:\n");
c@241 783 for (i = 0; i < model->N; i++)
c@241 784 {
c@241 785 for (j = 0; j < model->L; j++)
c@241 786 printf("%f ", model->mu[i][j]);
c@241 787 printf("\n");
c@241 788 }
c@241 789 printf("\n\n");
c@241 790 printf("cov:\n");
c@241 791 for (i = 0; i < model->L; i++)
c@241 792 {
c@241 793 for (j = 0; j < model->L; j++)
c@241 794 printf("%f ", model->cov[i][j]);
c@241 795 printf("\n");
c@241 796 }
c@241 797 printf("\n\n");
c@241 798 }
c@241 799
c@241 800