int prepareGconst_GMM(GMM * gmm) { int m; for (m = 0; m < gmm->nmix; m++) { if (gmm->full == FA) { gmm->gauss[m].gconst = cal_gconst(gmm->gauss[m].var, gmm->dim); } else { gmm->gauss[m].gconst = cal_gconstf(gmm->gauss[m].cov, gmm->dim); } if (gmm->gauss[m].gconst == 0) { return -1; } } return (0); }
int load_GMM(GMM * gmm, FILE * fp) { int m, l; freadf(gmm->weight, sizeof(*(gmm->weight)), gmm->nmix, fp); for (m = 0; m < gmm->nmix; m++) { freadf(gmm->gauss[m].mean, sizeof(*(gmm->gauss[m].mean)), gmm->dim, fp); if (gmm->full != TR) { freadf(gmm->gauss[m].var, sizeof(*(gmm->gauss[m].var)), gmm->dim, fp); gmm->gauss[m].gconst = cal_gconst(gmm->gauss[m].var, gmm->dim); } else { for (l = 0; l < gmm->dim; l++) { freadf(gmm->gauss[m].cov[l], sizeof(*(gmm->gauss[m].cov[l])), gmm->dim, fp); } } } return (0); }
int main(int argc, char **argv) { FILE *fp = stdin; GMM gmm, tgmm, floor; double E = DEF_E, V = DEF_V, W = DEF_W, *dat, *pd, *cb, *icb, *logwgd, logb, *sum, *sum_m, **sum_v, diff, sum_w, ave_logp0, ave_logp1, change = MAXVALUE, tmp1, tmp2; int ispipe, l, ll, L = DEF_L, m, M = DEF_M, N, t, T = DEF_T, S = DEF_S, full = FULL, n1, i, j, Imin = DEF_IMIN, Imax = DEF_IMAX, *tindex, *cntcb; if ((cmnd = strrchr(argv[0], '/')) == NULL) cmnd = argv[0]; else cmnd++; /* -- Check options -- */ while (--argc) if (**++argv == '-') { switch (*(*argv + 1)) { case 'h': usage(0); break; case 'l': L = atoi(*++argv); --argc; break; case 'm': M = atoi(*++argv); --argc; break; case 't': T = atoi(*++argv); --argc; break; case 's': S = atoi(*++argv); --argc; break; case 'a': Imin = atoi(*++argv); --argc; break; case 'b': Imax = atoi(*++argv); --argc; break; case 'e': E = atof(*++argv); --argc; break; case 'v': V = atof(*++argv); --argc; break; case 'w': W = atof(*++argv); --argc; break; case 'f': full = 1 - full; break; default: fprintf(stderr, "%s: Illegal option \"%s\".\n", cmnd, *argv); usage(1); } } else fp = getfp(*argv, "rb"); /* -- Count number of training vectors -- */ if (T == -1) { ispipe = fseek(fp, 0L, SEEK_END); T = (int) (ftell(fp) / (double) L / (double) sizeof(float)); rewind(fp); if (ispipe == -1) { /* training data is from standard input via pipe */ fprintf(stderr, "\n %s (Error) -t option must be specified for the standard input via pipe.\n", cmnd); usage(1); } } /* Memory allocation */ /* Training data */ dat = dgetmem(T * L); /* for VQ */ N = 1; while (N < M) N *= 2; cb = dgetmem(N * L); icb = dgetmem(L); tindex = (int *) getmem(T, sizeof(int)); cntcb = (int *) getmem(M, sizeof(int)); /* GMM */ gmm.weight = dgetmem(M); gmm.gauss = (Gauss *) getmem(M, sizeof(Gauss)); for (m = 0; m < M; m++) { gmm.gauss[m].mean = dgetmem(L); gmm.gauss[m].var = dgetmem(L); if (full == 1) { gmm.gauss[m].cov = (double **) malloc(sizeof(double *) * L); gmm.gauss[m].inv = (double **) malloc(sizeof(double *) * L); for (l = 0; l < L; l++) { gmm.gauss[m].cov[l] = dgetmem(L); gmm.gauss[m].inv[l] = dgetmem(L); } } } if (full == 1) { floor.gauss = (Gauss *) getmem(1, sizeof(Gauss)); floor.gauss[0].cov = (double **) malloc(sizeof(double *) * L); for (l = 0; l < L; l++) floor.gauss[0].cov[l] = dgetmem(L); sum_m = dgetmem(L); sum_v = (double **) malloc(sizeof(double *) * L); } /* temporary */ tgmm.weight = dgetmem(M); tgmm.gauss = (Gauss *) getmem(M, sizeof(Gauss)); for (m = 0; m < M; m++) { tgmm.gauss[m].mean = dgetmem(L); tgmm.gauss[m].var = dgetmem(L); if (full == 1) { tgmm.gauss[m].cov = (double **) malloc(sizeof(double *) * L); tgmm.gauss[m].inv = (double **) malloc(sizeof(double *) * L); for (l = 0; l < L; l++) { tgmm.gauss[m].cov[l] = dgetmem(L); tgmm.gauss[m].inv[l] = dgetmem(L); } } } logwgd = dgetmem(M); sum = dgetmem(M); /* Read training data */ freadf(dat, sizeof(*dat), T * L, fp); /* Initialization of GMM parameters */ /* LBG */ vaverage(dat, L, T, icb); lbg(dat, L, T, icb, 1, cb, N, ITER, MINTRAIN, S, CENTUP, DELTA, END); for (t = 0, pd = dat; t < T; t++, pd += L) { tindex[t] = vq(pd, cb, L, M); cntcb[tindex[t]]++; } for (m = 0; m < M; m++) if (cntcb[m] == 0) { fprintf(stderr, "Error: No data for mixture No.%d\n", m); usage(1); } fprintf(stderr, "T = %d L = %d M = %d\n", T, L, M); /* flooring value for weights */ W = 1.0 / (double) M *(double) W; /* weights */ for (m = 0, sum_w = 0.0; m < M; m++) { gmm.weight[m] = (double) cntcb[m] / (double) T; if (gmm.weight[m] < W) gmm.weight[m] = W; sum_w += gmm.weight[m]; } if (sum_w != 1.0) for (m = 0; m < M; m++) gmm.weight[m] /= sum_w; /* mean */ for (m = 0, pd = cb; m < M; m++, pd += L) movem(pd, gmm.gauss[m].mean, sizeof(double), L); /* variance */ if (full != 1) { for (t = 0, pd = dat; t < T; t++, pd += L) for (l = 0; l < L; l++) { diff = gmm.gauss[tindex[t]].mean[l] - pd[l]; gmm.gauss[tindex[t]].var[l] += sq(diff); } for (m = 0; m < M; m++) for (l = 0; l < L; l++) { gmm.gauss[m].var[l] /= (double) cntcb[m]; if (gmm.gauss[m].var[l] < V) gmm.gauss[m].var[l] = V; } for (m = 0; m < M; m++) gmm.gauss[m].gconst = cal_gconst(gmm.gauss[m].var, L); } /* full covariance */ else { for (t = 0, pd = dat; t < T; t++, pd += L) { for (l = 0; l < L; l++) { for (i = 0; i <= l; i++) { if (l == i) { diff = (gmm.gauss[tindex[t]].mean[l] - pd[l]) * (gmm.gauss[tindex[t]].mean[i] - pd[i]); floor.gauss[0].cov[l][i] += diff; } } } } for (l = 0; l < L; l++) { for (i = 0; i <= l; i++) { if (l == i) { floor.gauss[0].cov[l][i] /= T; floor.gauss[0].cov[l][i] *= V; } } } for (t = 0, pd = dat; t < T; t++, pd += L) { for (l = 0; l < L; l++) { for (i = 0; i <= l; i++) { diff = (gmm.gauss[tindex[t]].mean[l] - pd[l]) * (gmm.gauss[tindex[t]].mean[i] - pd[i]); gmm.gauss[tindex[t]].cov[l][i] += diff; } } } for (m = 0; m < M; m++) for (l = 0; l < L; l++) for (i = 0; i <= l; i++) { gmm.gauss[m].cov[l][i] /= (double) cntcb[m]; } } /* EM training of GMM parameters */ for (i = 0; (i <= Imax) && ((i <= Imin) || (fabs(change) > E)); i++) { if (full != 1) fillz_gmm(&tgmm, M, L); else fillz_gmmf(&tgmm, M, L); fillz(sum, sizeof(double), M); if (full != 1) { for (m = 0; m < M; m++) gmm.gauss[m].gconst = cal_gconst(gmm.gauss[m].var, L); } else { for (m = 0, n1 = 0; m < M; m++) { gmm.gauss[m].gconst = cal_gconstf(gmm.gauss[m].cov, L); if (gmm.gauss[m].gconst == 0) { n1++; for (l = 0; l < L; l++) gmm.gauss[m].cov[l][l] += floor.gauss[0].cov[l][l]; gmm.gauss[m].gconst = cal_gconstf(gmm.gauss[m].cov, L); } if (gmm.gauss[m].gconst == 0) { fprintf(stderr, "ERROR : Can't caluculate covdet"); exit(EXIT_FAILURE); } /* calculate inv */ cal_inv(gmm.gauss[m].cov, gmm.gauss[m].inv, L); } } if (full == 1) fprintf(stderr, "%d cov can't caluculate covdet\n", n1); for (t = 0, ave_logp1 = 0.0, pd = dat; t < T; t++, pd += L) { for (m = 0, logb = LZERO; m < M; m++) { if (full != 1) { logwgd[m] = log_wgd(&gmm, m, pd, L); logb = log_add(logb, logwgd[m]); } /* full */ else { logwgd[m] = log_wgdf(&gmm, m, pd, L); logb = log_add(logb, logwgd[m]); } } ave_logp1 += logb; for (m = 0; m < M; m++) { tmp1 = exp(logwgd[m] - logb); sum[m] += tmp1; for (l = 0; l < L; l++) { tmp2 = tmp1 * pd[l]; tgmm.gauss[m].mean[l] += tmp2; if (full != 1) tgmm.gauss[m].var[l] += tmp2 * pd[l]; else { for (j = 0; j <= l; j++) { tgmm.gauss[m].cov[l][j] += tmp1 * (pd[l] - gmm.gauss[m].mean[l]) * (pd[j] - gmm. gauss[m].mean [j]); } } } } } /* Output average log likelihood at each iteration */ ave_logp1 /= (double) T; if (i == 1 && m == 1) ave_logp0 = ave_logp1; fprintf(stderr, "iter %3d : ", i); fprintf(stderr, "ave_logprob = %g", ave_logp1); if (i) { change = ave_logp1 - ave_logp0; fprintf(stderr, " change = %g", change); } fprintf(stderr, "\n"); ave_logp0 = ave_logp1; /* Update perameters */ /* weights */ for (m = 0; m < M; m++) gmm.weight[m] = sum[m] / (double) T; /* mean, variance */ for (m = 0; m < M; m++) { for (l = 0; l < L; l++) gmm.gauss[m].mean[l] = tgmm.gauss[m].mean[l] / sum[m]; if (full != 1) { for (l = 0; l < L; l++) { gmm.gauss[m].var[l] = tgmm.gauss[m].var[l] / sum[m] - sq(gmm.gauss[m].mean[l]); if (gmm.gauss[m].var[l] < V) gmm.gauss[m].var[l] = V; } } /* full */ else { for (l = 0; l < L; l++) { for (j = 0; j <= l; j++) { gmm.gauss[m].cov[l][j] = tgmm.gauss[m].cov[l][j] / sum[m]; } } } } } /* Output GMM parameters */ fwritef(gmm.weight, sizeof(double), M, stdout); if (full != 1) { for (m = 0; m < M; m++) { fwritef(gmm.gauss[m].mean, sizeof(double), L, stdout); fwritef(gmm.gauss[m].var, sizeof(double), L, stdout); } } else { for (m = 0; m < M; m++) { fwritef(gmm.gauss[m].mean, sizeof(double), L, stdout); for (i = 0; i < L; i++) for (j = 0; j < i; j++) gmm.gauss[m].cov[j][i] = gmm.gauss[m].cov[i][j]; for (l = 0; l < L; l++) fwritef(gmm.gauss[m].cov[l], sizeof(double), L, stdout); } } return (0); }