示例#1
0
 /**
  * Sends the factor-graph message with and returns the log-normalization constant.
  */
 protected function sendMessageVariable(Message $message, Variable $variable)
 {
     $marginal = $variable->getValue();
     $messageValue = $message->getValue();
     $logZ = GaussianDistribution::logProductNormalization($marginal, $messageValue);
     $variable->setValue(GaussianDistribution::multiply($marginal, $messageValue));
     return $logZ;
 }
 public function testMultiplication()
 {
     // I verified this against the formula at http://www.tina-vision.net/tina-knoppix/tina-memo/2003-003.pdf
     $standardNormal = new GaussianDistribution(0, 1);
     $shiftedGaussian = new GaussianDistribution(2, 3);
     $product = GaussianDistribution::multiply($standardNormal, $shiftedGaussian);
     $this->assertEquals(0.2, $product->getMean(), '', GaussianDistributionTest::ERROR_TOLERANCE);
     $this->assertEquals(3.0 / sqrt(10), $product->getStandardDeviation(), '', GaussianDistributionTest::ERROR_TOLERANCE);
     $m4s5 = new GaussianDistribution(4, 5);
     $m6s7 = new GaussianDistribution(6, 7);
     $product2 = GaussianDistribution::multiply($m4s5, $m6s7);
     $expectedMean = (4 * square(7) + 6 * square(5)) / (square(5) + square(7));
     $this->assertEquals($expectedMean, $product2->getMean(), '', GaussianDistributionTest::ERROR_TOLERANCE);
     $expectedSigma = sqrt(square(5) * square(7) / (square(5) + square(7)));
     $this->assertEquals($expectedSigma, $product2->getStandardDeviation(), '', GaussianDistributionTest::ERROR_TOLERANCE);
 }
 private function updateHelper(Message $message1, Message $message2, Variable $variable1, Variable $variable2)
 {
     $message1Value = clone $message1->getValue();
     $message2Value = clone $message2->getValue();
     $marginal1 = clone $variable1->getValue();
     $marginal2 = clone $variable2->getValue();
     $a = $this->_precision / ($this->_precision + $marginal2->getPrecision() - $message2Value->getPrecision());
     $newMessage = GaussianDistribution::fromPrecisionMean($a * ($marginal2->getPrecisionMean() - $message2Value->getPrecisionMean()), $a * ($marginal2->getPrecision() - $message2Value->getPrecision()));
     $oldMarginalWithoutMessage = GaussianDistribution::divide($marginal1, $message1Value);
     $newMarginal = GaussianDistribution::multiply($oldMarginalWithoutMessage, $newMessage);
     // Update the message and marginal
     $message1->setValue($newMessage);
     $variable1->setValue($newMarginal);
     // Return the difference in the new marginal
     return GaussianDistribution::subtract($newMarginal, $marginal1);
 }
示例#4
0
 protected function updateMessageVariable(Message &$message, Variable &$variable)
 {
     $oldMarginal = clone $variable->getValue();
     $oldMessage = clone $message->getValue();
     $messageFromVariable = GaussianDistribution::divide($oldMarginal, $oldMessage);
     $c = $messageFromVariable->getPrecision();
     $d = $messageFromVariable->getPrecisionMean();
     $sqrtC = sqrt($c);
     $dOnSqrtC = $d / $sqrtC;
     $epsilonTimesSqrtC = $this->_epsilon * $sqrtC;
     $d = $messageFromVariable->getPrecisionMean();
     $denominator = 1.0 - TruncatedGaussianCorrectionFunctions::wWithinMargin($dOnSqrtC, $epsilonTimesSqrtC);
     $newPrecision = $c / $denominator;
     $newPrecisionMean = ($d + $sqrtC * TruncatedGaussianCorrectionFunctions::vWithinMargin($dOnSqrtC, $epsilonTimesSqrtC)) / $denominator;
     $newMarginal = GaussianDistribution::fromPrecisionMean($newPrecisionMean, $newPrecision);
     $newMessage = GaussianDistribution::divide(GaussianDistribution::multiply($oldMessage, $newMarginal), $oldMarginal);
     // Update the message and marginal
     $message->setValue($newMessage);
     $variable->setValue($newMarginal);
     // Return the difference in the new marginal
     return GaussianDistribution::subtract($newMarginal, $oldMarginal);
 }
 private function updateHelper(array $weights, array $weightsSquared, array $messages, array $variables)
 {
     // Potentially look at http://mathworld.wolfram.com/NormalSumDistribution.html for clues as
     // to what it's doing
     $message0 = clone $messages[0]->getValue();
     $marginal0 = clone $variables[0]->getValue();
     // The math works out so that 1/newPrecision = sum of a_i^2 /marginalsWithoutMessages[i]
     $inverseOfNewPrecisionSum = 0.0;
     $anotherInverseOfNewPrecisionSum = 0.0;
     $weightedMeanSum = 0.0;
     $anotherWeightedMeanSum = 0.0;
     $weightsSquaredLength = count($weightsSquared);
     for ($i = 0; $i < $weightsSquaredLength; $i++) {
         // These flow directly from the paper
         $inverseOfNewPrecisionSum += $weightsSquared[$i] / ($variables[$i + 1]->getValue()->getPrecision() - $messages[$i + 1]->getValue()->getPrecision());
         $diff = GaussianDistribution::divide($variables[$i + 1]->getValue(), $messages[$i + 1]->getValue());
         $anotherInverseOfNewPrecisionSum += $weightsSquared[$i] / $diff->getPrecision();
         $weightedMeanSum += $weights[$i] * ($variables[$i + 1]->getValue()->getPrecisionMean() - $messages[$i + 1]->getValue()->getPrecisionMean()) / ($variables[$i + 1]->getValue()->getPrecision() - $messages[$i + 1]->getValue()->getPrecision());
         $anotherWeightedMeanSum += $weights[$i] * $diff->getPrecisionMean() / $diff->getPrecision();
     }
     $newPrecision = 1.0 / $inverseOfNewPrecisionSum;
     $anotherNewPrecision = 1.0 / $anotherInverseOfNewPrecisionSum;
     $newPrecisionMean = $newPrecision * $weightedMeanSum;
     $anotherNewPrecisionMean = $anotherNewPrecision * $anotherWeightedMeanSum;
     $newMessage = GaussianDistribution::fromPrecisionMean($newPrecisionMean, $newPrecision);
     $oldMarginalWithoutMessage = GaussianDistribution::divide($marginal0, $message0);
     $newMarginal = GaussianDistribution::multiply($oldMarginalWithoutMessage, $newMessage);
     // Update the message and marginal
     $messages[0]->setValue($newMessage);
     $variables[0]->setValue($newMarginal);
     // Return the difference in the new marginal
     $finalDiff = GaussianDistribution::subtract($newMarginal, $marginal0);
     return $finalDiff;
 }