public function testRandomize() { $hmm = new slHiddenMarkovModel(4, array(1, 2, 3)); $hmm->randomize(); $size = count($hmm); for ($x = 0; $x < $size; ++$x) { $rowSum = 0; for ($y = 0; $y < $size; ++$y) { $rowSum += $hmm->getTransition($x, $y); } $this->assertEquals(1.0, $rowSum, null, 0.001); } }
/** * Train the HMM with the given input sequence * * @param slHiddenMarkovModel $hmm * @param array $sequence * @return void */ public function train(slHiddenMarkovModel $hmm, array $sequence) { $sequence = $hmm->mapLabels($sequence); $sequenceLength = count($sequence); $oldHmm = clone $hmm; $states = count($hmm); $labels = $hmm->countLabels(); // Calculate forward and backwards variables, first $forward = $this->calcForward($oldHmm, $sequence); $backward = $this->calcBackwards($oldHmm, $sequence); // Reevaluate the start probabilities for ($i = 0; $i < $states; ++$i) { $hmm->setStart($i, $this->calcGamma($oldHmm, $i, 0, $sequence, $forward, $backward)); } // Reevaluate the transistion probabilities for ($i = 0; $i < $states; ++$i) { for ($j = 0; $j < $states; ++$j) { $numerator = 0; $denominator = 0; for ($t = 0; $t <= $sequenceLength - 1; ++$t) { $numerator += $this->calcP($oldHmm, $t, $i, $j, $sequence, $forward, $backward); $denominator += $this->calcGamma($oldHmm, $i, $t, $sequence, $forward, $backward); } $hmm->setTransition($i, $j, $this->divide($numerator, $denominator)); } } // Reevaluate the emission probabilities for ($i = 0; $i < $states; ++$i) { for ($k = 0; $k < $labels; ++$k) { for ($t = 0; $t <= $sequenceLength - 1; ++$t) { $gamma = $this->calcGamma($oldHmm, $i, $t, $sequence, $forward, $backward); $numerator += $gamma * ($k == $sequence[$t] ? 1 : 0); $denominator += $gamma; } $hmm->setEmission($i, $k, $this->divide($numerator, $denominator)); } } }
/** * Test example train * * As documented here: * http://www.indiana.edu/~iulg/moss/hmmcalculations.pdf * * @return void */ public function testSimpleTrain() { $hmm = new slHiddenMarkovModel(2, array('A', 'B')); // Initialize the model $hmm->setStart(0, 0.85); $hmm->setStart(1, 0.15); $hmm->setTransition(0, 0, 0.3); $hmm->setTransition(0, 1, 0.7); $hmm->setTransition(1, 0, 0.1); $hmm->setTransition(1, 1, 0.9); $hmm->setEmission(0, 0, 0.4); $hmm->setEmission(0, 1, 0.6); $hmm->setEmission(1, 0, 0.5); $hmm->setEmission(1, 1, 0.5); $trainer = new slBaumWelchTrainer(); $trainer->trainCycle($hmm, array('A', 'B', 'B', 'A'), 1); $trainer->trainCycle($hmm, array('B', 'A', 'B'), 1); }