Beispiel #1
0
int
rd_gau(const char *fn, uint32 n_o)
{
    if (s3gau_read(fn,
		   &igau,
		   &n_cb_i,
		   &n_stream,
		   &n_density,
		   &veclen) != S3_SUCCESS)
	return S3_ERROR;

    n_cb_o = n_o;
    
    ogau = (vector_t ***)gauden_alloc_param(n_cb_o,
					    n_stream,
					    n_density,
					    veclen);
    return S3_SUCCESS;
}
Beispiel #2
0
float64
reest_sum(uint32 ts,
	  vector_t **mean,
	  vector_t **var,
	  float32 **mixw,
	  uint32 n_density,
	  uint32 n_stream,
	  uint32 n_in_obs,
	  const uint32 *veclen,
	  uint32 n_iter,
	  uint32 twopassvar,
	  uint32 vartiethr)
{
    uint32 o, i, j, k, l;
    float32  *mixw_acc;
    float32  *cb_acc;
    vector_t  **mean_acc_xx;
    vector_t  **var_acc_xx;
    vector_t  *mean_acc;
    vector_t  *var_acc;
    float64 ol, ttt, diff, log_tot_ol = 0, p_log_tot_ol = 0;
    float64 **norm, *den;
    float64 log_a_den=0;
    float32 mixw_norm;

    vector_t obs;
    uint32 n_obs;

    vector_t ***n_mean_xx = NULL;
    vector_t *n_mean = NULL;

    float64 avg_lik=0, p_avg_lik=0;
    uint32 tievar = FALSE;

    E_INFO("EM reestimation of mixw/means/vars\n");
    
    if (twopassvar) {
	n_mean_xx = gauden_alloc_param(1, 1, n_density, veclen);
	n_mean = n_mean_xx[0][0];
    }
    
    /* allocate mixing weight accumulators */
    mixw_acc = (float32 *)ckd_calloc(n_density, sizeof(float32));

    cb_acc = (float32 *)ckd_calloc(n_density, sizeof(float32));
    mean_acc_xx = (vector_t **)alloc_gau_acc(1, n_density, veclen, feat_blksize());
    mean_acc = mean_acc_xx[0];
    var_acc_xx = (vector_t **)alloc_gau_acc(1, n_density, veclen, feat_blksize());
    var_acc = var_acc_xx[0];

    den = (float64 *)ckd_calloc(n_density, sizeof(float64));
    norm = (float64 **)ckd_calloc_2d(n_stream, n_density, sizeof(float64));

    for (j = 0; j < n_stream; j++) {
	n_obs = setup_obs(ts, j, n_in_obs, veclen);

	if (n_obs < vartiethr) tievar = TRUE;

	for (i = 0; i < n_iter; i++) {
	    p_log_tot_ol = log_tot_ol;
	    log_tot_ol = 0;

	    for (k = 0; k < n_density; k++) {
		/* floor variances */
		for (l = 0; l < veclen[j]; l++)
		    if (var[j][k][l] < 1e-4) var[j][k][l] = 1e-4; 

		/* compute normalization factors for Gaussian
		   densities */
		norm[j][k] = diag_norm(var[j][k], veclen[j]);

		/* precompute 1/(2sigma^2) terms */
		diag_eval_precomp(var[j][k], veclen[j]);
	    }

	    if (twopassvar) {
		/* do a pass over the corpus to compute reestimated means */
		for (o = 0; o < n_obs; o++) {
		    float64 mx;

		    obs = get_obs(o);
		
		    mx = MIN_NEG_FLOAT64;

		    for (k = 0; k < n_density; k++) {
			/* really log(den) for the moment */
			den[k] = log_diag_eval(obs, norm[j][k], mean[j][k], var[j][k], veclen[j]);
			if (mx < den[k]) mx = den[k];
		    }
		    for (k = 0, ol = 0; k < n_density; k++) {
			den[k] = exp(log_a_den - mx);
			ol += mixw[j][k] * den[k];
		    }

		    for (k = 0; k < n_density; k++) {
			ttt = mixw[j][k] * den[k] / ol;
		    
			cb_acc[k] += ttt;
			for (l = 0; l < veclen[j]; l++) {
			    mean_acc[k][l] += obs[l] * ttt;
			}
		    }
		}
	    
		cb_acc[0] = 1.0 / cb_acc[0];
		for (k = 1; k < n_density; k++) {
		    cb_acc[k] = 1.0 / cb_acc[k];
		}

		/* compute the reestimated mean value to be used in next pass */
		for (k = 0; k < n_density; k++) {
		    for (l = 0; l < veclen[j]; l++) {
			n_mean[k][l] = mean_acc[k][l] * cb_acc[k];
			mean_acc[k][l] = 0;
		    }
		    cb_acc[k] = 0;
		}
	    }
	    else {
		n_mean = mean[j];
	    }
		
	    for (o = 0; o < n_obs; o++) {
		float64 mx;

		/* Do a pass over the data to accumulate reestimation sums
		 * for the remaining parameters (including means
		 * if not a 2-pass config) */

		/* Get the next observation */
		obs = get_obs(o);

		mx = MIN_NEG_FLOAT64;

		/* Compute the mixture density value given the
		 * observation and the model parameters */
		for (k = 0; k < n_density; k++) {
		    /* really log(den) for the moment */
		    den[k] = log_diag_eval(obs, norm[j][k], mean[j][k], var[j][k], veclen[j]);
		    if (mx < den[k]) mx = den[k];
		}
		for (k = 0, ol = 0; k < n_density; k++) {
		    den[k] = exp(den[k] - mx);
		    ol += mixw[j][k] * den[k];
		}

		log_tot_ol += log(ol) + mx;

		/* Compute the reestimation sum terms for each
		 * of the component densities */
		for (k = 0; k < n_density; k++) {
		    ttt = mixw[j][k] * den[k] / ol;

		    mixw_acc[k] += ttt;

		    cb_acc[k] += ttt;
		    
		    for (l = 0; l < veclen[j]; l++) {
			/* if not doing two-pass variance computation
			 * n_mean <- mean above. */
			diff = obs[l] - n_mean[k][l];
			
			if (!twopassvar) {
			    mean_acc[k][l] += ttt * obs[l];
			}

			var_acc[k][l] += ttt * diff * diff;
		    }
		}
	    }

	    avg_lik = exp(log_tot_ol / n_obs);

	    if (p_log_tot_ol != 0)
		p_avg_lik = exp(p_log_tot_ol / n_obs);
	    else
		p_avg_lik = 0.5 * avg_lik;

	    E_INFO("EM stream %u: [%u] avg_lik %e conv_ratio %e\n",
		   j, i, avg_lik, (avg_lik - p_avg_lik) / p_avg_lik);
	    
	    /* normalize after iteration */

	    if (tievar) {
		/* create a sum over all densities in entry 0 */
		for (k = 1; k < n_density; k++) {
		    for (l = 0; l < veclen[j]; l++) {
			var[j][0][l] += var[j][k][l];
		    }
		    cb_acc[0] += cb_acc[k];
		}
		/* copy entry 0 back to remaining entries */
		for (k = 1; k < n_density; k++) {
		    for (l = 0; l < veclen[j]; l++) {
			var[j][k][l] = var[j][0][l];
		    }
		    cb_acc[k] = cb_acc[0];
		}		
	    }
		
	    for (k = 0, mixw_norm = 0; k < n_density; k++) {
		/* norm for per density expectations */
		cb_acc[k] = 1.0 / cb_acc[k];

		mixw_norm += mixw_acc[k];
	    }
	    mixw_norm = 1.0 / mixw_norm;

	    if (!twopassvar) {
		for (k = 0; k < n_density; k++) {
		    mixw[j][k] = mixw_acc[k] * mixw_norm;
		    mixw_acc[k] = 0;

		    for (l = 0; l < veclen[j]; l++) {
			mean[j][k][l] = mean_acc[k][l] * cb_acc[k];
			mean_acc[k][l] = 0;
			var[j][k][l]  = var_acc[k][l] * cb_acc[k];
			var_acc[k][l] = 0;
		    }
		    cb_acc[k] = 0;
		}
	    }
	    else {
		for (k = 0; k < n_density; k++) {
		    mixw[j][k] = mixw_acc[k] * mixw_norm;
		    mixw_acc[k] = 0;

		    for (l = 0; l < veclen[j]; l++) {
			/* already computed in first pass */
			mean[j][k][l] = n_mean[k][l];
			var[j][k][l]  = var_acc[k][l] * cb_acc[k];
			var_acc[k][l] = 0;
		    }
		    cb_acc[k] = 0;
		}
	    }
	}	/* end of EM iteration loop */

	E_INFO("EM stream %u: [final] n_obs %u avg_lik %e conv_ratio %e\n",
	       j, n_obs, avg_lik, (avg_lik - p_avg_lik) / p_avg_lik);

    }	/* end of feature stream loop */

    ckd_free((void *)mixw_acc);
    ckd_free((void *)cb_acc);
    ckd_free((void *)&mean_acc_xx[0][0][0]);
    ckd_free_2d((void **)mean_acc_xx);
    ckd_free((void *)&var_acc_xx[0][0][0]);
    ckd_free_2d((void **)var_acc_xx);
    if (n_mean_xx) {
	ckd_free((void *)&n_mean_xx[0][0][0]);
	ckd_free_2d((void **)n_mean);
    }

    ckd_free_2d((void **)norm);
    ckd_free((void *)den);

    return log_tot_ol;
}
Beispiel #3
0
static int
init_state(const char *obsdmp,
	   const char *obsidx,
	   uint32 n_density,
	   uint32 n_stream,
	   const uint32 *veclen,
	   int reest,
	   const char *mixwfn,
	   const char *meanfn,
	   const char *varfn,
	   uint32 ts_off,
	   uint32 ts_cnt,
	   uint32 n_ts,
	   uint32 n_d_ts)
{
    uint32 blksz;
    vector_t ***mean;
    vector_t ***var = NULL;
    vector_t ****fullvar = NULL;
    float32  ***mixw = NULL;
    uint32 n_frame;
    uint32 ignore = 0;
    codew_t *label;
    uint32 n_corpus = 0;
    float64 sqerr;
    float64 tot_sqerr;
    segdmp_type_t t;
    uint32 i, j, ts, n;
    timing_t *km_timer;
    timing_t *var_timer;
    timing_t *em_timer;
    int32 full_covar;

    km_timer = timing_get("km");
    var_timer = timing_get("var");
    em_timer = timing_get("em");
    
    blksz = feat_blksize();

    full_covar = cmd_ln_int32("-fullvar");
    /* fully-continuous for now */
    mean = gauden_alloc_param(ts_cnt, n_stream, n_density, veclen);
    if (full_covar)
	    fullvar  = gauden_alloc_param_full(ts_cnt, n_stream, n_density, veclen);
    else
	    var  = gauden_alloc_param(ts_cnt, n_stream, n_density, veclen);
    if (mixwfn)
	mixw = (float32 ***)ckd_calloc_3d(ts_cnt,
					  n_stream,
					  n_density,
					  sizeof(float32));

    if ((const char *)cmd_ln_access("-segidxfn")) {
	E_INFO("Multi-class dump\n");
	if (segdmp_open_read((const char **)cmd_ln_access("-segdmpdirs"),
			     (const char *)cmd_ln_access("-segdmpfn"),
			     (const char *)cmd_ln_access("-segidxfn"),
			     &n,
			     &t) != S3_SUCCESS) {
	    E_FATAL("Unable to open dumps\n");
	}

	if (n != n_d_ts) {
	    E_FATAL("Expected %u tied-states in dump, but apparently %u\n",
		    n_d_ts, n);
	}
	if (t != SEGDMP_TYPE_FEAT) {
	    E_FATAL("Expected feature dump, but instead saw %u\n", t);
	}
	
	multiclass = TRUE;
    }
    else {
	E_INFO("1-class dump file\n");
	
	multiclass = FALSE;
	
	dmp_fp = s3open((const char *)cmd_ln_access("-segdmpfn"), "rb",
			&dmp_swp);
	if (dmp_fp == NULL) {
	    E_ERROR_SYSTEM("Unable to open dump file %s for reading\n",
			   (const char *)cmd_ln_access("-segdmpfn"));

	    return S3_ERROR;
	}

	if (s3read(&n_frame, sizeof(uint32), 1, dmp_fp, dmp_swp, &ignore) != 1) {
	    E_ERROR_SYSTEM("Unable to open dump file %s for reading\n",
			   (const char *)cmd_ln_access("-segdmpfn"));

	    return S3_ERROR;
	}

	data_offset = ftell(dmp_fp);
    }

    tot_sqerr = 0;
    for (i = 0; i < ts_cnt; i++) {
	ts = ts_off + i;

	/* stride not accounted for yet */
	if (o2d == NULL) {
	    if (multiclass)
		n_frame = segdmp_n_seg(ts);
	}
	else {
	    for (j = 0, n_frame = 0; j < n_o2d[ts]; j++) {
		n_frame += segdmp_n_seg(o2d[ts][j]);
	    }
	}
    
	E_INFO("Corpus %u: sz==%u frames%s\n",
	       ts, n_frame,
	       (n_frame > *(uint32 *)cmd_ln_access("-vartiethr") ? "" : " tied var"));

	if (n_frame == 0) {
	    continue;
	}


	E_INFO("Convergence ratios are abs(cur - prior) / abs(prior)\n");
	/* Do some variety of k-means clustering */
	if (km_timer)
	    timing_start(km_timer);
	sqerr = cluster(ts, n_stream, n_frame, veclen, mean[i], n_density, &label);
	if (km_timer)
	    timing_stop(km_timer);

	if (sqerr < 0) {
	    E_ERROR("Unable to do k-means for state %u; skipping...\n", ts);

	    continue;
	}

	/* Given the k-means and assuming equal prior liklihoods
	 * compute the variances */
	if (var_timer)
	    timing_start(var_timer);
	if (full_covar)
		full_variances(ts, mean[i], fullvar[i], n_density, veclen,
			       n_frame, n_stream, label);
	else
		variances(ts, mean[i], var[i], n_density, veclen, n_frame, n_stream, label);
	if (var_timer)
	    timing_stop(var_timer);

	if (mixwfn) {
	    /* initialize the mixing weights by counting # of occurrances
	     * of the top codeword over the corpus and normalizing */
	    init_mixw(mixw[i], mean[i], n_density, veclen, n_frame, n_stream, label);

	    ckd_free(label);

	    if (reest == TRUE && full_covar)
		E_ERROR("EM re-estimation is not yet supported for full covariances\n");
	    else if (reest == TRUE) {
		if (em_timer)
		    timing_start(em_timer);
		/* Do iterations of EM to estimate the mixture densities */
		reest_sum(ts, mean[i], var[i], mixw[i], n_density, n_stream,
			  n_frame, veclen,
			  *(uint32 *)cmd_ln_access("-niter"),
			  FALSE,
			  *(uint32 *)cmd_ln_access("-vartiethr"));
		if (em_timer)
		    timing_stop(em_timer);
	    }
	}
	
	++n_corpus;
	tot_sqerr += sqerr;
	    
	E_INFO("sqerr [%u] == %e\n", ts, sqerr);
    }

    if (n_corpus > 0) {
	E_INFO("sqerr = %e tot %e rms\n", tot_sqerr, sqrt(tot_sqerr/n_corpus));
    }

    if (!multiclass)
	s3close(dmp_fp);
    
    if (meanfn) {
	if (s3gau_write(meanfn,
			(const vector_t ***)mean,
			ts_cnt,
			n_stream,
			n_density,
			veclen) != S3_SUCCESS) {
	    return S3_ERROR;
	}
    }
    else {
	E_INFO("No mean file given; none written\n");
    }
		    
    if (varfn) {
	if (full_covar) {
	    if (s3gau_write_full(varfn,
				 (const vector_t ****)fullvar,
				 ts_cnt,
				 n_stream,
				 n_density,
				 veclen) != S3_SUCCESS)
		return S3_ERROR;
	}
	else {
	    if (s3gau_write(varfn,
				 (const vector_t ***)var,
				 ts_cnt,
				 n_stream,
				 n_density,
				 veclen) != S3_SUCCESS)
		return S3_ERROR;
	}
    }
    else {
	E_INFO("No variance file given; none written\n");
    }

    if (mixwfn) {
	if (s3mixw_write(mixwfn,
			 mixw,
			 ts_cnt,
			 n_stream,
			 n_density) != S3_SUCCESS) {
	    return S3_ERROR;
	}
    }
    else {
	E_INFO("No mixing weight file given; none written\n");
    }

    return S3_SUCCESS;
}
Beispiel #4
0
int
main(int argc, char *argv[])
{
    vector_t ***mean;
    vector_t ***var = NULL;
    vector_t ****fullvar = NULL;
    vector_t ***new_mean;
    vector_t ***new_var = NULL;
    vector_t ****new_fullvar = NULL;
    float32  ***dnom;
    float32 ***mixw;
    float32 ***new_mixw;
    uint32 n_mixw;
    uint32 n_mgau;
    uint32 n_dnom;
    uint32 n_feat;
    uint32 n_density;
    uint32 n_inc;
    uint32 *veclen;
    int32 var_is_full;

    parse_cmd_ln(argc, argv);

    E_INFO("Reading mixing weight file %s.\n",
	   cmd_ln_str("-inmixwfn"));

    if (s3mixw_read(cmd_ln_str("-inmixwfn"),
		    &mixw,
		    &n_mixw,
		    &n_feat,
		    &n_density) != S3_SUCCESS) {
	return 1;
    }

    n_inc = cmd_ln_int32("-ninc");

    if (n_inc > n_density) {
	E_WARN("# of densities to split (== %u) > total # of densities/mixture (== %u); # split <- %u # den/mix\n",
	       n_inc, n_density, n_density);
	n_inc = n_density;
    }
    
    if (s3gau_read(cmd_ln_str("-inmeanfn"),
		   &mean,
		   &n_mgau,
		   &n_feat,
		   &n_density,
		   &veclen) != S3_SUCCESS) {
	return 1;
    }

    var_is_full = cmd_ln_int32("-fullvar");
    if (var_is_full) {
	if (s3gau_read_full(cmd_ln_str("-invarfn"),
			    &fullvar,
			    &n_mgau,
			    &n_feat,
			    &n_density,
			    &veclen) != S3_SUCCESS) {
	    return 1;
	}
    }
    else {
	if (s3gau_read(cmd_ln_str("-invarfn"),
		       &var,
		       &n_mgau,
		       &n_feat,
		       &n_density,
		       &veclen) != S3_SUCCESS) {
	    return 1;
	}
    }

    if (s3gaudnom_read(cmd_ln_str("-dcountfn"),
		       &dnom,
		       &n_dnom,
		       &n_feat,
		       &n_density) != S3_SUCCESS) {
	return 1;
    }
	
    new_mean = gauden_alloc_param(n_mgau, n_feat, n_density+n_inc, veclen);
    if (var_is_full)
	    new_fullvar  = gauden_alloc_param_full(n_mgau, n_feat, n_density+n_inc, veclen);
    else
	    new_var  = gauden_alloc_param(n_mgau, n_feat, n_density+n_inc, veclen);
    new_mixw = (float32 ***)ckd_calloc_3d(n_mixw, n_feat, n_density+n_inc,
					  sizeof(float32));
    
    E_INFO("output n_density == %u\n", n_density+n_inc);

    inc_densities(new_mixw,
		  new_mean,
		  new_var,
		  new_fullvar,

		  mixw,
		  mean,
		  var,
		  fullvar,
		  dnom,

		  n_mixw,
		  n_mgau,
		  n_dnom,
		  n_feat,
		  n_density,
		  veclen,

		  n_inc);

    if (cmd_ln_str("-outmixwfn") != NULL) {
	if (s3mixw_write(cmd_ln_str("-outmixwfn"),
			 new_mixw,
			 n_mixw,
			 n_feat,
			 n_density+n_inc) != S3_SUCCESS) {
	    return 1;
	}
    }
    else {
	E_FATAL("You must use the -outmixwfn argument\n");
    }

    if (cmd_ln_str("-outmeanfn") != NULL) {
	if (s3gau_write(cmd_ln_str("-outmeanfn"),
			(const vector_t ***)new_mean,
			n_mgau,
			n_feat,
			n_density+n_inc,
			veclen) != S3_SUCCESS) {
	    return 1;
	}
    }
    else {
	E_FATAL("You must use the -outmeanfn argument\n");
    }

    if (cmd_ln_str("-outvarfn") != NULL) {
	if (var_is_full) {
	    if (s3gau_write_full(cmd_ln_str("-outvarfn"),
				 (const vector_t ****)new_fullvar,
				 n_mgau,
				 n_feat,
				 n_density+n_inc,
				 veclen) != S3_SUCCESS) {
		return 1;
	    }
	}
	else {
	    if (s3gau_write(cmd_ln_str("-outvarfn"),
			    (const vector_t ***)new_var,
			    n_mgau,
			    n_feat,
			    n_density+n_inc,
			    veclen) != S3_SUCCESS) {
		return 1;
	    }
	}
    }
    else {
	E_FATAL("You must use the -outvarfn argument\n");
    }

    return 0;
}
Beispiel #5
0
static int
init_mixw()
{
    model_def_t *src_mdef;
    float32 ***src_mixw;
    vector_t ***src_mean;
    vector_t ***src_var = NULL;
    vector_t ****src_fullvar = NULL;
    float32 ***src_tmat;

    model_def_t *dest_mdef;
    float32 ***dest_mixw;
    vector_t ***dest_mean;
    vector_t ***dest_var = NULL;
    vector_t ****dest_fullvar = NULL;
    float32 ***dest_tmat;

    uint32 n_mixw_src;
    uint32 n_mixw_dest;
    uint32 n_feat;
    uint32 tmp_n_feat;
    uint32 n_gau;
    uint32 tmp_n_gau;
    uint32 n_cb_src;
    uint32 n_cb_dest;
    uint32 n_state_pm;
    uint32 n_tmat_src;
    uint32 n_tmat_dest;
    uint32 *veclen;
    uint32 *tmp_veclen;

    uint32 m;
    uint32 dest_m;
    uint32 dest_m_base;
    uint32 src_m;
    acmod_id_t src_m_base;
    const char *dest_m_name;
    const char *dest_m_base_name;

    uint32 i;
    uint32 n_ts;
    uint32 n_cb;

    const char *ts2cbfn;

    E_INFO("Reading src %s\n", cmd_ln_str("-src_moddeffn"));

    /* read in the source model definition file */
    if (model_def_read(&src_mdef,
                       cmd_ln_str("-src_moddeffn")) != S3_SUCCESS) {
        return S3_ERROR;
    }


    ts2cbfn = cmd_ln_str("-src_ts2cbfn");
    if (strcmp(SEMI_LABEL, ts2cbfn) == 0) {
        E_INFO("Generating semi-continous ts2cb mapping\n");
        src_mdef->cb = semi_ts2cb(src_mdef->n_tied_state);
        n_ts = src_mdef->n_tied_state;
        n_cb = 1;
    }
    else if (strcmp(CONT_LABEL, ts2cbfn) == 0) {
        E_INFO("Generating continous ts2cb mapping\n");
        src_mdef->cb = cont_ts2cb(src_mdef->n_tied_state);
        n_ts = src_mdef->n_tied_state;
        n_cb = src_mdef->n_tied_state;
    }
    else if (strcmp(PTM_LABEL, ts2cbfn) == 0) {
        E_INFO("Generating phonetically tied ts2cb mapping\n");
        src_mdef->cb = ptm_ts2cb(src_mdef);
        n_ts = src_mdef->n_tied_state;
        n_cb = src_mdef->acmod_set->n_ci;
    }
    else {
        E_INFO("Reading src %s\n", cmd_ln_str("-src_ts2cbfn"));
        if (s3ts2cb_read(ts2cbfn,
                         &src_mdef->cb,
                         &n_ts,
                         &n_cb) != S3_SUCCESS) {
            return S3_ERROR;
        }
    }

    E_INFO("Reading src %s\n", cmd_ln_str("-src_mixwfn"));

    /* read in the source mixing weight parameter file */
    if (s3mixw_read(cmd_ln_str("-src_mixwfn"),
                    &src_mixw, &n_mixw_src, &n_feat, &n_gau) != S3_SUCCESS) {

        return S3_ERROR;
    }

    E_INFO("Reading src %s\n",
           cmd_ln_str("-src_tmatfn"));

    if (s3tmat_read(cmd_ln_str("-src_tmatfn"),
                    &src_tmat,
                    &n_tmat_src,
                    &n_state_pm) != S3_SUCCESS) {
        return S3_ERROR;
    }

    E_INFO("Reading src %s\n", cmd_ln_str("-src_meanfn"));

    if (s3gau_read(cmd_ln_str("-src_meanfn"),
                   &src_mean,
                   &n_cb_src,
                   &tmp_n_feat,
                   &tmp_n_gau,
                   &veclen) != S3_SUCCESS) {
        return S3_ERROR;
    }

    if (tmp_n_feat != n_feat) {
        E_FATAL("src mean n_feat (== %u) != prior value (== %u)\n",
                tmp_n_feat, n_feat);
    }
    if (tmp_n_gau != n_gau) {
        E_FATAL("src mean n_gau (== %u) != prior value (== %u)\n",
                tmp_n_gau, n_gau);
    }
    if (n_cb_src != n_cb) {
        E_FATAL("src mean n_cb (== %u) is inconsistent with ts2cb mapping %u. Most probably phoneset has duplicated phones\n",
                n_cb_src, n_cb);
    }

    E_INFO("Reading src %s\n", cmd_ln_str("-src_varfn"));
    if (cmd_ln_int32("-fullvar")) {
        if (s3gau_read_full(cmd_ln_str("-src_varfn"),
                            &src_fullvar,
                            &n_cb_src,
                            &tmp_n_feat,
                            &tmp_n_gau,
                            &tmp_veclen) != S3_SUCCESS) {
            return S3_ERROR;
        }
    }
    else {
        if (s3gau_read(cmd_ln_str("-src_varfn"),
                       &src_var,
                       &n_cb_src,
                       &tmp_n_feat,
                       &tmp_n_gau,
                       &tmp_veclen) != S3_SUCCESS) {
            return S3_ERROR;
        }
    }

    if (tmp_n_feat != n_feat) {
        E_FATAL("src var n_feat (== %u) != prior value (== %u)\n",
                tmp_n_feat, n_feat);
    }
    if (tmp_n_gau != n_gau) {
        E_FATAL("src var n_gau (== %u) != prior value (== %u)\n",
                tmp_n_gau, n_gau);
    }
    if (n_cb_src != n_cb) {
        E_FATAL("src var n_cb (== %u) inconsistent w/ ts2cb mapping %u\n",
                n_cb_src, n_cb);
    }

    if (n_mixw_src < src_mdef->n_tied_state) {
        E_FATAL("Too few source mixing weights, %u, for the # of tied states, %u\n",
                n_mixw_src, src_mdef->n_tied_state);
    }

    for (i = 0; i < n_feat; i++) {
        if (veclen[i] != tmp_veclen[i]) {
            E_FATAL("src var veclen[%u] (== %u) != prior value (== %u)\n",
                    i, tmp_veclen[i], veclen[i]);
        }
    }
    ckd_free(tmp_veclen);

    E_INFO("Reading dest %s\n",
           cmd_ln_str("-dest_moddeffn"));

    /* read in the destination model definition file */
    if (model_def_read(&dest_mdef,
                       cmd_ln_str("-dest_moddeffn")) < S3_SUCCESS) {
        return S3_ERROR;
    }

    ts2cbfn = cmd_ln_str("-dest_ts2cbfn");
    if (strcmp(SEMI_LABEL, ts2cbfn) == 0) {
        E_INFO("Generating semi-continous ts2cb mapping\n");
        dest_mdef->cb = semi_ts2cb(dest_mdef->n_tied_state);
        n_ts = dest_mdef->n_tied_state;
        n_cb = 1;
    }
    else if (strcmp(CONT_LABEL, ts2cbfn) == 0) {
        E_INFO("Generating continous ts2cb mapping\n");
        dest_mdef->cb = cont_ts2cb(dest_mdef->n_tied_state);
        n_ts = dest_mdef->n_tied_state;
        n_cb = dest_mdef->n_tied_state;
    }
    else if (strcmp(PTM_LABEL, ts2cbfn) == 0) {
        E_INFO("Generating phonetically tied ts2cb mapping\n");
        dest_mdef->cb = ptm_ts2cb(dest_mdef);
        n_ts = dest_mdef->n_tied_state;
        n_cb = dest_mdef->acmod_set->n_ci;
    }
    else {
        E_INFO("Reading dest %s\n",
               cmd_ln_str("-dest_ts2cbfn"));


        if (s3ts2cb_read(ts2cbfn,
                         &dest_mdef->cb,
                         &n_ts,
                         &n_cb) != S3_SUCCESS) {
            return S3_ERROR;
        }
    }

    E_INFO("Calculating initial model parameters\n");

    n_tmat_dest = dest_mdef->n_tied_tmat;
    tmat_dest_list = init_was_added(n_tmat_dest);

    E_INFO("Alloc %ux%ux%u dest tmat\n",
           n_tmat_dest,
           n_state_pm-1,
           n_state_pm);

    dest_tmat = (float32 ***)ckd_calloc_3d(n_tmat_dest,
                                           n_state_pm-1,
                                           n_state_pm,
                                           sizeof(float32));

    n_mixw_dest = dest_mdef->n_tied_state;
    mixw_dest_list = init_was_added(n_mixw_dest);

    E_INFO("Alloc %ux%ux%u dest mixw\n",
           n_mixw_dest, n_feat, n_gau);
    dest_mixw = (float32 ***)ckd_calloc_3d(n_mixw_dest, n_feat, n_gau, sizeof(float32));

    for (i = 0, n_cb_dest = 0; i < n_mixw_dest; i++) {
        if (dest_mdef->cb[i] > n_cb_dest) {
            n_cb_dest = dest_mdef->cb[i];
        }
    }
    ++n_cb_dest;

    cb_dest_list = init_was_added(n_cb_dest);

    E_INFO("Alloc %ux%ux%u dest mean and var\n",
           n_cb_dest, n_feat, n_gau);
    dest_mean = gauden_alloc_param(n_cb_dest, n_feat, n_gau, veclen);
    if (src_var)
        dest_var = gauden_alloc_param(n_cb_dest, n_feat, n_gau, veclen);
    else if (src_fullvar)
        dest_fullvar = gauden_alloc_param_full(n_cb_dest, n_feat, n_gau, veclen);

    for (dest_m = 0; dest_m < dest_mdef->n_defn; dest_m++) {
        dest_m_name = acmod_set_id2name(dest_mdef->acmod_set, dest_m);
        src_m = acmod_set_name2id(src_mdef->acmod_set, dest_m_name);
        if (src_m == NO_ACMOD) {
            /* No corresponding phone model in the source set */

            /* See if there is a source base phone corresponding to this destination model
               base phone */
            dest_m_base = acmod_set_base_phone(dest_mdef->acmod_set, dest_m);
            dest_m_base_name = acmod_set_id2name(dest_mdef->acmod_set, dest_m_base);

            src_m_base = acmod_set_name2id(src_mdef->acmod_set, dest_m_base_name);
            if (src_m_base == NO_ACMOD) {
                /* No corresponding model or base model found.  Use uniform distribution */

                E_INFO("No source base phone %s found.  Initializing %s using uniform distribution\n",
                       dest_m_base_name, dest_m_name);

                if (src_tmat) {
                    E_INFO("Uniform initialization of tmat not supported\n");
                }
                init_uniform(dest_mixw, &dest_mdef->defn[dest_m], n_feat, n_gau);
            }
            else {
                /* No corresponding model, but a base model was found.  Use base distribution. */
                init_model(dest_mixw, dest_mean, dest_var, dest_fullvar, dest_tmat,
                           &dest_mdef->defn[dest_m], dest_mdef->cb, dest_mdef->acmod_set,
                           src_mixw, src_mean, src_var, src_fullvar, src_tmat,
                           &src_mdef->defn[src_m_base], src_mdef->cb, src_mdef->acmod_set,
                           n_feat, n_gau, n_state_pm, veclen);
            }
        }
        else {
            /* Found a corresponding model in the source set, so use source distributions to init
               the destination */
            init_model(dest_mixw, dest_mean, dest_var, dest_fullvar, dest_tmat,
                       &dest_mdef->defn[dest_m], dest_mdef->cb, dest_mdef->acmod_set,
                       src_mixw, src_mean, src_var, src_fullvar, src_tmat,
                       &src_mdef->defn[src_m], src_mdef->cb, src_mdef->acmod_set,
                       n_feat, n_gau, n_state_pm, veclen);
        }
    }

    for (m = 0; m < n_mixw_dest; m++) {
        if (mixw_dest_list[m] == NULL) {
            E_WARN("Destination state %u has not been initialized!\n", m);
        }
    }

    for (m = 0; m < n_cb_dest; m++) {
        if (cb_dest_list[m] == NULL) {
            E_WARN("Destination cb %u has not been initialized!\n", m);
        }
        else if (cb_dest_list[m]->next != NULL) {
            E_WARN("dest cb %u has > 1 corresponding source cb\n", m);
        }
    }

    E_INFO("Writing dest %s\n",
           cmd_ln_str("-dest_tmatfn"));

    if (s3tmat_write(cmd_ln_str("-dest_tmatfn"),
                     dest_tmat,
                     n_tmat_dest,
                     n_state_pm) != S3_SUCCESS) {
        return S3_ERROR;
    }


    E_INFO("Writing dest %s\n",
           cmd_ln_str("-dest_mixwfn"));

    if (s3mixw_write(cmd_ln_str("-dest_mixwfn"),
                     dest_mixw,
                     dest_mdef->n_tied_state, n_feat, n_gau) < S3_SUCCESS) {
        return S3_ERROR;
    }

    E_INFO("Writing dest %s\n",
           cmd_ln_str("-dest_meanfn"));

    if (s3gau_write(cmd_ln_str("-dest_meanfn"),
                    (const vector_t ***)dest_mean,
                    n_cb_dest,
                    n_feat,
                    n_gau,
                    veclen) != S3_SUCCESS) {
        return S3_ERROR;
    }

    E_INFO("Writing dest %s\n",
           cmd_ln_str("-dest_varfn"));
    if (cmd_ln_int32("-fullvar")) {
        if (s3gau_write_full(cmd_ln_str("-dest_varfn"),
                             (const vector_t ****)dest_fullvar,
                             n_cb_dest,
                             n_feat,
                             n_gau,
                             veclen) != S3_SUCCESS) {
            return S3_ERROR;
        }
    }
    else {
        if (s3gau_write(cmd_ln_str("-dest_varfn"),
                        (const vector_t ***)dest_var,
                        n_cb_dest,
                        n_feat,
                        n_gau,
                        veclen) != S3_SUCCESS) {
            return S3_ERROR;
        }
    }
    ckd_free(veclen);
    return S3_SUCCESS;
}
Beispiel #6
0
/********************************************************************
 *	Make MLLR matrix A and B using conventional MLLR method
 ********************************************************************/
int
mllr_mat(float32 	*****out_A,
         float32 	****out_B,
         const char 	*var_fn,
         vector_t 	***mean,
         vector_t        ***wt_mean,             /* read from bw accum */
         float32         ***wt_dcount,           /* read from bw accum */
         uint32 		gau_begin,
         int32 		*cb2mllr,
         uint32 		mllr_mult,
         uint32 		mllr_add,
         float32		varfloor,
         uint32 		n_mgau,
         uint32 		n_stream,
         uint32 		n_density,
         uint32 		n_mllr_class,
         const uint32 	*veclen)


{
    vector_t 	***var  	= NULL;
    float32 	****A  		= NULL;
    float32 	***B   		= NULL;

    float32 	*****regl  	= NULL;
    float32 	****regr   	= NULL;

    float32     wt_mean_var;
    float32     wt_dcount_var;
    float32     wt_dcount_var_mean;

    float32	*tmean		= NULL;
    uint32 	n_mgau_rd;
    uint32 	n_stream_rd;
    uint32 	n_density_rd;

    uint32    *veclen_rd	= NULL;

    uint32 i, j, k, l, s, p , q;
    int32 m, mc;
    int32 len=0;

    /*      uint32 	i, j, k, l, p, q, s;
        int32	m, mc, mi; */

    E_INFO("\n");
    E_INFO(" ---- mllr_solve(): Conventional MLLR method\n");

    if (cmd_ln_int32("-fullvar")) {
        /* Extract diagonals to solve MLLR (we are not doing
           variance adaptation, yet) */
        vector_t ****fullvar;
        uint32 i, j, k, l;

        if (s3gau_read_full(var_fn,
                            &fullvar,
                            &n_mgau_rd,
                            &n_stream_rd,
                            &n_density_rd,
                            &veclen_rd) != S3_SUCCESS) {
            E_FATAL("Couldn't read %s", var_fn);
        }
        var = gauden_alloc_param(n_mgau_rd,
                                 n_stream_rd,
                                 n_density_rd,
                                 veclen_rd);
        for (i = 0; i < n_mgau_rd; ++i)
            for (j = 0; j < n_stream_rd; ++j)
                for (k = 0; k < n_density_rd; ++k)
                    for (l = 0; l < veclen_rd[j]; ++l)
                        var[i][j][k][l] =
                            fullvar[i][j][k][l][l];
        gauden_free_param_full(fullvar);
    }
    else {
        if (s3gau_read(var_fn,
                       &var,
                       &n_mgau_rd,
                       &n_stream_rd,
                       &n_density_rd,
                       &veclen_rd) != S3_SUCCESS) {
            E_FATAL("Couldn't read %s", var_fn);
        }
    }

    if (n_mgau != n_mgau_rd) {
        E_FATAL("n_mgau mismatch (%u : %u)\n",n_mgau,n_mgau_rd);
    }
    if (n_stream != n_stream_rd) {
        E_FATAL("n_stream mismatch (%u : %u)\n",n_stream,n_stream_rd);
    }
    if (n_density != n_density_rd) {
        E_FATAL("n_density mismatch (%u : %u)\n",n_density,n_density_rd);
    }
    for (s = 0; s < n_stream; s++) {
        if (veclen[s] != veclen_rd[s]) {
            E_FATAL("vector length of stream %u (== %u) "
                    "!= prior length (== %u)\n", s, veclen_rd[s], veclen[s]);
        }
    }
    ckd_free((void *)veclen_rd);
    veclen_rd = NULL;


    /* Invert variances. */
    for (i = 0; i < n_mgau; i++) {
        for (j = 0; j < n_stream; j++) {
            for (k = 0; k < n_density; k++) {
                for (l = 0; l < veclen[j]; l++) {
                    if (var[i][j][k][l] <= 0.) {
                        var[i][j][k][l] = VAR_CONST;
                    }
                    else if (var[i][j][k][l] < varfloor) {
                        var[i][j][k][l] = 1. / varfloor;
                    }
                    else {
                        var[i][j][k][l] = 1. / var[i][j][k][l];
                    }
                }
            }
        }
    }


    fprintf(stderr,"\n");

    E_INFO(" ---- A. Accum regl, regr\n");
    E_INFO(" No classes %d, no. stream %d\n",n_mllr_class,n_stream);

    /* Legetter's set of G matrices, one per dimension per class. */
    regl = (float32 *****)ckd_calloc_2d(n_mllr_class, n_stream, sizeof(float32 ***));
    /* Legetter's Z matrices, one per class. */
    regr = (float32 ****) ckd_calloc_2d(n_mllr_class, n_stream, sizeof(float32 **));

    for (i = 0; i < n_mllr_class; i++) {
        for (j = 0; j < n_stream; j++) {
            len = veclen[j];
            regl[i][j] = (float32 ***)ckd_calloc_3d(len, len+1, len+1, sizeof(float32));
            regr[i][j] = (float32 **) ckd_calloc_2d(len, len+1, sizeof(float32));
        }
    }

    /*      E_INFO(" Checking\n");*/

    for (i = gau_begin; i < n_mgau; i++) {
        mc = cb2mllr[i];
        if (mc < 0) continue;	/* skip */

        for (j = 0; j < n_stream; j++) {
            len=veclen[j];

            for (k = 0; k < n_density; k++) {
                if (wt_dcount[i][j][k] > 0.) {
                    tmean = mean[i][j][k];
                    for (l = 0; l < len; l++) {
                        wt_mean_var   = wt_mean[i][j][k][l] * var[i][j][k][l];
                        wt_dcount_var = wt_dcount[i][j][k]  * var[i][j][k][l];

                        for (p = 0; p < len; p++) {
                            wt_dcount_var_mean = wt_dcount_var * tmean[p];
                            for (q = p; q < len; q++) {
                                /* This is g(l)_{pq} = sum_r(v_{ii}(r) d_{pq}(r))*/
                                /* or in other words sum(likelihood * invvar * outer(mean, mean)) */
                                regl[mc][j][l][p][q] += (float32) (wt_dcount_var_mean * tmean[q]);
                            }
                            /* G corresponding to extended element of q. */
                            regl[mc][j][l][p][len] += (float32)(wt_dcount_var_mean);
                            /* This is z_{lp} = sum(likelihood * invvar * obs * mean_p) */
                            regr[mc][j][l][p] += (float32)(wt_mean_var * tmean[p]);
                        }
                        /* G corresponding to extended element of p and q. */
                        /* Question: what about regl[mc][j][l][len][0..len]? */
                        /* Answer: G(l) is symmetric, so we already calculated them. */
                        regl[mc][j][l][len][len] += (float32)wt_dcount_var;
                        /* Z corresponding to extended element of p. */
                        regr[mc][j][l][len] += (float32)(wt_mean_var);
                    }
                }
            }
        }
    }

    gauden_free_param(mean);
    gauden_free_param(wt_mean);
    ckd_free_3d((void ***)wt_dcount);

    /* Fill in the lower triangular part of regl. */
    for (m = 0; m < n_mllr_class; m++) {
        for (j = 0; j < n_stream; j++) {
            for (l = 0; l < veclen[j]; l++) {
                for (p = 0; p <= veclen[j]; p++) {
                    for (q = p+1; q <= veclen[j]; q++) {
                        regl[m][j][l][q][p] = regl[m][j][l][p][q];
                    }
                }
            }
        }
    }

    E_INFO(" ---- B. Compute MLLR matrices (A,B)\n");
    if(compute_mllr(regl,
                    regr,
                    veclen,
                    n_mllr_class,
                    n_stream,
                    mllr_mult,
                    mllr_add,
                    &A,
                    &B) != S3_SUCCESS) {
        E_FATAL("MLLR computation failed\n");
    }

    free_mllr_reg(regl,regr, n_mllr_class, n_stream);

    *out_A = A;
    *out_B = B;

    return S3_SUCCESS;
}