aima.core.probability.hmm.exact.HMMForwardBackward Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aima-core Show documentation
Show all versions of aima-core Show documentation
AIMA-Java Core Algorithms from the book Artificial Intelligence a Modern Approach 3rd Ed.
The newest version!
package aima.core.probability.hmm.exact;
import java.util.ArrayList;
import java.util.List;
import aima.core.probability.CategoricalDistribution;
import aima.core.probability.hmm.HiddenMarkovModel;
import aima.core.probability.proposition.AssignmentProposition;
import aima.core.probability.temporal.ForwardBackwardInference;
import aima.core.util.math.Matrix;
/**
* Artificial Intelligence A Modern Approach (3rd Edition): page 576.
*
*
*
* function FORWARD-BACKWARD(ev, prior) returns a vector of probability distributions
* inputs: ev, a vector of evidence values for steps 1,...,t
* prior, the prior distribution on the initial state, P(X0)
* local variables: fv, a vector of forward messages for steps 0,...,t
* b, a representation of the backward message, initially all 1s
* sv, a vector of smoothed estimates for steps 1,...,t
*
* fv[0] <- prior
* for i = 1 to t do
* fv[i] <- FORWARD(fv[i-1], ev[i])
* for i = t downto 1 do
* sv[i] <- NORMALIZE(fv[i] * b)
* b <- BACKWARD(b, ev[i])
* return sv
*
*
* Figure 15.4 The forward-backward algorithm for smoothing: computing posterior
* probabilities of a sequence of states given a sequence of observations. The
* FORWARD and BACKWARD operators are defined by Equations (15.5) and (15.9),
* respectively.
*
* Note: An implementation of the FORWARD-BACKWARD algorithm using a
* Hidden Markov Model as the underlying model implementation.
*
* @author Ciaran O'Reilly
* @author Ravi Mohan
*/
public class HMMForwardBackward implements ForwardBackwardInference {
protected HiddenMarkovModel hmm = null;
public HMMForwardBackward(HiddenMarkovModel hmm) {
this.hmm = hmm;
}
//
// START-ForwardBackwardInference
@Override
public List forwardBackward(
List> ev, CategoricalDistribution prior) {
// local variables: fv, a vector of forward messages for steps 0,...,t
List fv = new ArrayList(ev.size() + 1);
// b, a representation of the backward message, initially all 1s
Matrix b = hmm.createUnitMessage();
// sv, a vector of smoothed estimates for steps 1,...,t
List sv = new ArrayList(ev.size());
// fv[0] <- prior
fv.add(hmm.convert(prior));
// for i = 1 to t do
for (int i = 0; i < ev.size(); i++) {
// fv[i] <- FORWARD(fv[i-1], ev[i])
fv.add(forward(fv.get(i), hmm.getEvidence(ev.get(i))));
}
// for i = t downto 1 do
for (int i = ev.size() - 1; i >= 0; i--) {
// sv[i] <- NORMALIZE(fv[i] * b)
sv.add(0, hmm.normalize(fv.get(i + 1).arrayTimes(b)));
// b <- BACKWARD(b, ev[i])
b = backward(b, hmm.getEvidence(ev.get(i)));
}
// return sv
return hmm.convert(sv);
}
@Override
public CategoricalDistribution forward(CategoricalDistribution f1_t,
List e_tp1) {
return hmm.convert(forward(hmm.convert(f1_t), hmm.getEvidence(e_tp1)));
}
@Override
public CategoricalDistribution backward(CategoricalDistribution b_kp2t,
List e_kp1) {
return hmm
.convert(backward(hmm.convert(b_kp2t), hmm.getEvidence(e_kp1)));
}
// END-ForwardBackwardInference
//
/**
* The forward equation (15.5) in Matrix form becomes (15.12):
*
*
* f1:t+1 = αOt+1TTf1:t
*
*
* @param f1_t
* f1:t
* @param O_tp1
* Ot+1
* @return f1:t+1
*/
public Matrix forward(Matrix f1_t, Matrix O_tp1) {
return hmm.normalize(O_tp1.times(hmm.getTransitionModel().transpose()
.times(f1_t)));
}
/**
* The backward equation (15.9) in Matrix form becomes (15.13):
*
*
* bk+1:t = TOk+1bk+2:t
*
*
* @param b_kp2t
* bk+2:t
* @param O_kp1
* Ok+1
* @return bk+1:t
*/
public Matrix backward(Matrix b_kp2t, Matrix O_kp1) {
return hmm.getTransitionModel().times(O_kp1).times(b_kp2t);
}
}