/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.mahout.classifier.sequencelearning.hmm;
import org.apache.mahout.math.Matrix;
import org.apache.mahout.math.Vector;
import org.junit.Test;
public class HMMTrainerTest extends HMMTestBase {
@Test
public void testViterbiTraining() {
// initialize the expected model parameters (from R)
// expected transition matrix
double[][] transitionE = {{0.3125, 0.0625, 0.3125, 0.3125},
{0.25, 0.25, 0.25, 0.25}, {0.5, 0.071429, 0.357143, 0.071429},
{0.5, 0.1, 0.1, 0.3}};
// initialize the emission matrix
double[][] emissionE = {{0.882353, 0.058824, 0.058824},
{0.333333, 0.333333, 0.3333333}, {0.076923, 0.846154, 0.076923},
{0.111111, 0.111111, 0.777778}};
// train the given network to the following output sequence
int[] observed = {1, 0, 2, 2, 0, 0, 1, 1, 1, 0, 2, 0, 1, 0, 0};
HmmModel trained = HmmTrainer.trainViterbi(getModel(), observed, 0.5, 0.1, 10, false);
// now check whether the model matches our expectations
Matrix emissionMatrix = trained.getEmissionMatrix();
Matrix transitionMatrix = trained.getTransitionMatrix();
for (int i = 0; i < trained.getNrOfHiddenStates(); ++i) {
for (int j = 0; j < trained.getNrOfHiddenStates(); ++j) {
assertEquals(transitionMatrix.getQuick(i, j), transitionE[i][j], EPSILON);
}
for (int j = 0; j < trained.getNrOfOutputStates(); ++j) {
assertEquals(emissionMatrix.getQuick(i, j), emissionE[i][j], EPSILON);
}
}
}
@Test
public void testScaledViterbiTraining() {
// initialize the expected model parameters (from R)
// expected transition matrix
double[][] transitionE = {{0.3125, 0.0625, 0.3125, 0.3125},
{0.25, 0.25, 0.25, 0.25}, {0.5, 0.071429, 0.357143, 0.071429},
{0.5, 0.1, 0.1, 0.3}};
// initialize the emission matrix
double[][] emissionE = {{0.882353, 0.058824, 0.058824},
{0.333333, 0.333333, 0.3333333}, {0.076923, 0.846154, 0.076923},
{0.111111, 0.111111, 0.777778}};
// train the given network to the following output sequence
int[] observed = {1, 0, 2, 2, 0, 0, 1, 1, 1, 0, 2, 0, 1, 0, 0};
HmmModel trained = HmmTrainer.trainViterbi(getModel(), observed, 0.5, 0.1, 10,
true);
// now check whether the model matches our expectations
Matrix emissionMatrix = trained.getEmissionMatrix();
Matrix transitionMatrix = trained.getTransitionMatrix();
for (int i = 0; i < trained.getNrOfHiddenStates(); ++i) {
for (int j = 0; j < trained.getNrOfHiddenStates(); ++j) {
assertEquals(transitionMatrix.getQuick(i, j), transitionE[i][j],
EPSILON);
}
for (int j = 0; j < trained.getNrOfOutputStates(); ++j) {
assertEquals(emissionMatrix.getQuick(i, j), emissionE[i][j],
EPSILON);
}
}
}
@Test
public void testBaumWelchTraining() {
// train the given network to the following output sequence
int[] observed = {1, 0, 2, 2, 0, 0, 1, 1, 1, 0, 2, 0, 1, 0, 0};
// expected values from Matlab HMM package / R HMM package
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() {
// train the given network to the following output sequence
int[] observed = {1, 0, 2, 2, 0, 0, 1, 1, 1, 0, 2, 0, 1, 0, 0};
// expected values from Matlab HMM package / R HMM package
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);
}
}
}
}