HmmTrainer { public static HmmModel trainBaumWelch(HmmModel initialModel, int[] observedSequence, double epsilon, int maxIterations, boolean scaled) { HmmModel lastIteration = initialModel.clone(); HmmModel iteration = initialModel.clone(); int hiddenCount = initialModel.getNrOfHiddenStates(); int visibleCount = observedSequence.length; Matrix alpha = new DenseMatrix(visibleCount, hiddenCount); Matrix beta = new DenseMatrix(visibleCount, hiddenCount); for (int it = 0; it < maxIterations; ++it) { Vector initialProbabilities = iteration.getInitialProbabilities(); Matrix emissionMatrix = iteration.getEmissionMatrix(); Matrix transitionMatrix = iteration.getTransitionMatrix(); HmmAlgorithms.forwardAlgorithm(alpha, iteration, observedSequence, scaled); HmmAlgorithms.backwardAlgorithm(beta, iteration, observedSequence, scaled); if (scaled) { logScaledBaumWelch(observedSequence, iteration, alpha, beta); } else { unscaledBaumWelch(observedSequence, iteration, alpha, beta); } double isum = 0; for (int j = 0; j < iteration.getNrOfHiddenStates(); ++j) { double sum = 0; for (int k = 0; k < iteration.getNrOfHiddenStates(); ++k) { sum += transitionMatrix.getQuick(j, k); } for (int k = 0; k < iteration.getNrOfHiddenStates(); ++k) { transitionMatrix .setQuick(j, k, transitionMatrix.getQuick(j, k) / sum); } sum = 0; for (int k = 0; k < iteration.getNrOfOutputStates(); ++k) { sum += emissionMatrix.getQuick(j, k); } for (int k = 0; k < iteration.getNrOfOutputStates(); ++k) { emissionMatrix.setQuick(j, k, emissionMatrix.getQuick(j, k) / sum); } isum += initialProbabilities.getQuick(j); } for (int i = 0; i < iteration.getNrOfHiddenStates(); ++i) { initialProbabilities.setQuick(i, initialProbabilities.getQuick(i) / isum); } if (checkConvergence(lastIteration, iteration, epsilon)) { break; } lastIteration.assign(iteration); } return iteration; } private  HmmTrainer(); static HmmModel trainSupervised(int nrOfHiddenStates, int nrOfOutputStates, int[] observedSequence,
      int[] hiddenSequence, double pseudoCount); static HmmModel trainSupervisedSequence(int nrOfHiddenStates,
                                                 int nrOfOutputStates, Collection<int[]> hiddenSequences,
                                                 Collection<int[]> observedSequences, double pseudoCount); static HmmModel trainViterbi(HmmModel initialModel,
                                      int[] observedSequence, double pseudoCount, double epsilon,
                                      int maxIterations, boolean scaled); static HmmModel trainBaumWelch(HmmModel initialModel,
                                        int[] observedSequence, double epsilon, int maxIterations, boolean scaled);  }
@Test public void testBaumWelchTraining() { int[] observed = {1, 0, 2, 2, 0, 0, 1, 1, 1, 0, 2, 0, 1, 0, 0}; double[] initialExpected = {0, 0, 1.0, 0}; double[][] transitionExpected = {{0.2319, 0.0993, 0.0005, 0.6683}, {0.0001, 0.3345, 0.6654, 0}, {0.5975, 0, 0.4025, 0}, {0.0024, 0.6657, 0, 0.3319}}; double[][] emissionExpected = {{0.9995, 0.0004, 0.0001}, {0.9943, 0.0036, 0.0021}, {0.0059, 0.9941, 0}, {0, 0, 1}}; HmmModel trained = HmmTrainer.trainBaumWelch(getModel(), observed, 0.1, 10, false); Vector initialProbabilities = trained.getInitialProbabilities(); Matrix emissionMatrix = trained.getEmissionMatrix(); Matrix transitionMatrix = trained.getTransitionMatrix(); for (int i = 0; i < trained.getNrOfHiddenStates(); ++i) { assertEquals(initialProbabilities.get(i), initialExpected[i], 0.0001); for (int j = 0; j < trained.getNrOfHiddenStates(); ++j) { assertEquals(transitionMatrix.getQuick(i, j), transitionExpected[i][j], 0.0001); } for (int j = 0; j < trained.getNrOfOutputStates(); ++j) { assertEquals(emissionMatrix.getQuick(i, j), emissionExpected[i][j], 0.0001); } } }
@Test public void testScaledBaumWelchTraining() { int[] observed = {1, 0, 2, 2, 0, 0, 1, 1, 1, 0, 2, 0, 1, 0, 0}; double[] initialExpected = {0, 0, 1.0, 0}; double[][] transitionExpected = {{0.2319, 0.0993, 0.0005, 0.6683}, {0.0001, 0.3345, 0.6654, 0}, {0.5975, 0, 0.4025, 0}, {0.0024, 0.6657, 0, 0.3319}}; double[][] emissionExpected = {{0.9995, 0.0004, 0.0001}, {0.9943, 0.0036, 0.0021}, {0.0059, 0.9941, 0}, {0, 0, 1}}; HmmModel trained = HmmTrainer .trainBaumWelch(getModel(), observed, 0.1, 10, true); Vector initialProbabilities = trained.getInitialProbabilities(); Matrix emissionMatrix = trained.getEmissionMatrix(); Matrix transitionMatrix = trained.getTransitionMatrix(); for (int i = 0; i < trained.getNrOfHiddenStates(); ++i) { assertEquals(initialProbabilities.get(i), initialExpected[i], 0.0001); for (int j = 0; j < trained.getNrOfHiddenStates(); ++j) { assertEquals(transitionMatrix.getQuick(i, j), transitionExpected[i][j], 0.0001); } for (int j = 0; j < trained.getNrOfOutputStates(); ++j) { assertEquals(emissionMatrix.getQuick(i, j), emissionExpected[i][j], 0.0001); } } }