/*
Copyright (c) 2009-2011
Speech Group at Informatik 5, Univ. Erlangen-Nuremberg, GERMANY
Korbinian Riedhammer
Tobias Bocklet
This file is part of the Java Speech Toolkit (JSTK).
The JSTK is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The JSTK is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the JSTK. If not, see <http://www.gnu.org/licenses/>.
*/
package de.fau.cs.jstk.stat.hmm;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import de.fau.cs.jstk.io.IOUtil;
import de.fau.cs.jstk.stat.Density.Flags;
import de.fau.cs.jstk.stat.DensityDiagonal;
import de.fau.cs.jstk.stat.DensityFull;
import de.fau.cs.jstk.stat.Mixture;
import de.fau.cs.jstk.stat.MleDensityAccumulator.MleOptions;
import de.fau.cs.jstk.stat.MleMixtureAccumulator;
/**
* The continuous HMM state features an individual mixture density. Though this
* results in easier code, the training complexity increases due to the large
* number of variables.
*
* @author sikoried
*/
public class CState extends State {
/** codebook for this state */
Mixture cb = null;
MleMixtureAccumulator acc = null;
private double ga = 0.;
/** cache for mixture posteriors */
private transient double [] p;
/**
* Generate a new State using a copy of the given codebook.
* @param codebook
*/
public CState(Mixture codebook) {
this.cb = codebook.clone();
this.p = new double [codebook.nd];
}
/**
* Generate a new continuous state by a deep copy of the referenced one.
* @param copy
*/
public CState(CState copy) {
this.cb = copy.cb.clone();
this.p = new double [this.cb.nd];
}
/**
* Create an HMM state by reading from the given InputStream
* @param is
*/
public CState(InputStream is) throws IOException {
cb = new Mixture(is);
p = new double [cb.nd];
}
/**
* Write the continuous state to the given OutputStream
*/
void write(OutputStream os) throws IOException {
IOUtil.writeByte(os, getTypeCode());
cb.write(os);
}
/**
* Emission probability of feature vector x
*/
public double emits(double[] x) {
return cb.evaluate2(x);
}
/**
* Initialize a new accumulator.
*/
public void init() {
try {
acc = new MleMixtureAccumulator(cb.fd, cb.nd, cb.diagonal() ? DensityDiagonal.class : DensityFull.class);
} catch (Exception e) {
throw new RuntimeException(e.toString());
}
ga = 0.;
}
/**
* Accumulate the given feature vector using the state's posterior.
*/
public void accumulate(double gamma, double [] x) {
// save your breath
if (gamma == 0.)
return;
// evaluate the mixtures and compute posteriors
cb.evaluate(x);
cb.posteriors(p);
// sum up all gammas for later interpolation
ga += gamma;
// for all densities...
for (int j = 0; j < cb.nd; ++j) {
// gamma_t(i,k)
acc.accumulate(gamma * p[j], x, j);
}
}
public double gamma() {
return ga;
}
/**
* Absorb the given state's accumulator and delete if afterwards.
*/
public void propagate(State source) {
CState state = (CState) source;
// absorb the statistics
acc.propagate(state.acc);
}
/**
* Interpolate the local sufficient statistics with the ones from the
* referenced state.
*/
public void interpolate(State source, double rho) {
CState state = (CState) source;
acc.interpolate(state.acc, rho / (rho + ga));
}
public void pinterpolate(double wt, State source) {
cb.pinterpolate(wt, ((CState) source).cb);
}
/**
* Reestimate this state's codebook.
*/
public void reestimate() {
Mixture old = cb.clone();
MleMixtureAccumulator.MleUpdate(old, MleOptions.pDefaultOptions, Flags.fAllParams, acc, cb);
}
/**
* Discard the current accumulator.
*/
public void discard() {
ga = 0.;
acc = null;
}
/**
* Generate a String representation of this state.
*/
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append(cb.toString());
return buf.toString();
}
/**
* Get the type code for continuous states 'c'
*/
public byte getTypeCode() {
return 'c';
}
}