private double UpdateHelper(Message <GaussianDistribution> message1, Message <GaussianDistribution> message2, Variable <GaussianDistribution> variable1, Variable <GaussianDistribution> variable2) { GaussianDistribution message1Value = message1.Value.Clone(); GaussianDistribution message2Value = message2.Value.Clone(); GaussianDistribution marginal1 = variable1.Value.Clone(); GaussianDistribution marginal2 = variable2.Value.Clone(); double a = _Precision / (_Precision + marginal2.Precision - message2Value.Precision); GaussianDistribution newMessage = GaussianDistribution.FromPrecisionMean( a * (marginal2.PrecisionMean - message2Value.PrecisionMean), a * (marginal2.Precision - message2Value.Precision)); GaussianDistribution oldMarginalWithoutMessage = marginal1 / message1Value; GaussianDistribution newMarginal = oldMarginalWithoutMessage * newMessage; /// Update the message and marginal message1.Value = newMessage; variable1.Value = newMarginal; /// Return the difference in the new marginal return(newMarginal - marginal1); }
protected override double UpdateMessage(Message <GaussianDistribution> message, Variable <GaussianDistribution> variable) { GaussianDistribution oldMarginal = variable.Value.Clone(); GaussianDistribution oldMessage = message.Value.Clone(); GaussianDistribution messageFromVariable = oldMarginal / oldMessage; double c = messageFromVariable.Precision; double d = messageFromVariable.PrecisionMean; double sqrtC = Math.Sqrt(c); double dOnSqrtC = d / sqrtC; double epsilonTimesSqrtC = _Epsilon * sqrtC; d = messageFromVariable.PrecisionMean; double denominator = 1.0 - TruncatedGaussianCorrectionFunctions.WWithinMargin(dOnSqrtC, epsilonTimesSqrtC); double newPrecision = c / denominator; double newPrecisionMean = (d + sqrtC * TruncatedGaussianCorrectionFunctions.VWithinMargin(dOnSqrtC, epsilonTimesSqrtC)) / denominator; GaussianDistribution newMarginal = GaussianDistribution.FromPrecisionMean(newPrecisionMean, newPrecision); GaussianDistribution newMessage = oldMessage * newMarginal / oldMarginal; /// Update the message and marginal message.Value = newMessage; variable.Value = newMarginal; /// Return the difference in the new marginal return(newMarginal - oldMarginal); }
public GaussianPriorFactor(double mean, double variance, Variable <GaussianDistribution> variable) : base(String.Format("Prior value going to {0}", variable)) { _NewMessage = new GaussianDistribution(mean, Math.Sqrt(variance)); CreateVariableToMessageBinding(variable, new Message <GaussianDistribution>( GaussianDistribution.FromPrecisionMean(0, 0), "message from {0} to {1}", this, variable)); }
private double UpdateHelper(double[] weights, double[] weightsSquared, IList <Message <GaussianDistribution> > messages, IList <Variable <GaussianDistribution> > variables) { // Potentially look at http://mathworld.wolfram.com/NormalSumDistribution.html for clues as // to what it's doing GaussianDistribution message0 = messages[0].Value.Clone(); GaussianDistribution marginal0 = variables[0].Value.Clone(); // The math works out so that 1/newPrecision = sum of a_i^2 /marginalsWithoutMessages[i] double inverseOfNewPrecisionSum = 0.0; double anotherInverseOfNewPrecisionSum = 0.0; double weightedMeanSum = 0.0; double anotherWeightedMeanSum = 0.0; for (int i = 0; i < weightsSquared.Length; i++) { // These flow directly from the paper inverseOfNewPrecisionSum += weightsSquared[i] / (variables[i + 1].Value.Precision - messages[i + 1].Value.Precision); GaussianDistribution diff = (variables[i + 1].Value / messages[i + 1].Value); anotherInverseOfNewPrecisionSum += weightsSquared[i] / diff.Precision; weightedMeanSum += weights[i] * (variables[i + 1].Value.PrecisionMean - messages[i + 1].Value.PrecisionMean) / (variables[i + 1].Value.Precision - messages[i + 1].Value.Precision); anotherWeightedMeanSum += weights[i] * diff.PrecisionMean / diff.Precision; } double newPrecision = 1.0 / inverseOfNewPrecisionSum; double anotherNewPrecision = 1.0 / anotherInverseOfNewPrecisionSum; double newPrecisionMean = newPrecision * weightedMeanSum; double anotherNewPrecisionMean = anotherNewPrecision * anotherWeightedMeanSum; GaussianDistribution newMessage = GaussianDistribution.FromPrecisionMean(newPrecisionMean, newPrecision); GaussianDistribution oldMarginalWithoutMessage = marginal0 / message0; GaussianDistribution newMarginal = oldMarginalWithoutMessage * newMessage; /// Update the message and marginal messages[0].Value = newMessage; variables[0].Value = newMarginal; /// Return the difference in the new marginal return(newMarginal - marginal0); }
protected override double UpdateMessage(Message <GaussianDistribution> message, Variable <GaussianDistribution> variable) { GaussianDistribution oldMarginal = variable.Value.Clone(); Message <GaussianDistribution> oldMessage = message; GaussianDistribution newMarginal = GaussianDistribution.FromPrecisionMean( oldMarginal.PrecisionMean + _NewMessage.PrecisionMean - oldMessage.Value.PrecisionMean, oldMarginal.Precision + _NewMessage.Precision - oldMessage.Value.Precision); variable.Value = newMarginal; message.Value = _NewMessage; return(oldMarginal - newMarginal); }
public TrueSkillFactorGraph(GameInfo gameInfo, IEnumerable <IDictionary <TPlayer, Rating> > teams, int[] teamRanks) { _PriorLayer = new PlayerPriorValuesToSkillsLayer <TPlayer>(this, teams); GameInfo = gameInfo; VariableFactory = new VariableFactory <GaussianDistribution>(() => GaussianDistribution.FromPrecisionMean(0, 0)); _Layers = new List <FactorGraphLayerBase <GaussianDistribution> > { _PriorLayer, new PlayerSkillsToPerformancesLayer <TPlayer>(this), new PlayerPerformancesToTeamPerformancesLayer <TPlayer>(this), new IteratedTeamDifferencesInnerLayer <TPlayer>( this, new TeamPerformancesToTeamPerformanceDifferencesLayer <TPlayer>(this), new TeamDifferencesComparisonLayer <TPlayer>(this, teamRanks)) }; }
public static Rating GetPartialUpdate(Rating prior, Rating fullPosterior, double updatePercentage) { var priorGaussian = new GaussianDistribution(prior.Mean, prior.StandardDeviation); var posteriorGaussian = new GaussianDistribution(fullPosterior.Mean, fullPosterior.StandardDeviation); // From a clarification email from Ralf Herbrich: // "the idea is to compute a linear interpolation between the prior and posterior skills of each player // ... in the canonical space of parameters" double precisionDifference = posteriorGaussian.Precision - priorGaussian.Precision; double partialPrecisionDifference = updatePercentage * precisionDifference; double precisionMeanDifference = posteriorGaussian.PrecisionMean - priorGaussian.PrecisionMean; double partialPrecisionMeanDifference = updatePercentage * precisionMeanDifference; GaussianDistribution partialPosteriorGaussion = GaussianDistribution.FromPrecisionMean( priorGaussian.PrecisionMean + partialPrecisionMeanDifference, priorGaussian.Precision + partialPrecisionDifference); return(new Rating(partialPosteriorGaussion.Mean, partialPosteriorGaussion.StandardDeviation, prior._ConservativeStandardDeviationMultiplier)); }